模块:Quote:修订间差异
来自星露谷物语扩展百科
更多操作
删除的内容 添加的内容
无编辑摘要 |
无编辑摘要 |
||
| 第4行: | 第4行: | ||
local quoteLast = "" |
local quoteLast = "" |
||
-- 预编译的正则表达式模式(避免重复编译) |
|||
-- 内部函数:分割引文文本(高度优化版本) |
|||
local COLON_PATTERN = ":" |
|||
local PUNCT_PATTERN = "[,。]" |
|||
local TRIPLE_QUOTE = "'''" |
|||
local STAR_SPAN = "<span>*</span>" |
|||
-- 预编译的HTML模板片段(避免重复字符串拼接) |
|||
local HTML_TABLE_START = '<table class="quotetable"><tr><td rowspan="2" class="decorativesquote"></td><td class="' |
|||
local HTML_QUOTE_START = '"' |
|||
local HTML_QUOTE_END = '"</td></tr>' |
|||
local HTML_SOURCE_START = '<tr><td class="' |
|||
local HTML_SOURCE_MID = '">— ' |
|||
local HTML_SOURCE_END = '</td></tr>' |
|||
local HTML_TABLE_END = '</table>' |
|||
local COLON_CHAR = ':' |
|||
-- 性别标记检查的预编译模式 |
|||
local MALE_MARKER = "(男)" |
|||
local FEMALE_MARKER = "(女)" |
|||
-- 样式类名预编译 |
|||
local TEXT_CLASS_NORMAL = "squotetext" |
|||
local TEXT_CLASS_ENGLISH = "squotetextenglish" |
|||
local SOURCE_CLASS_NORMAL = "quotesource" |
|||
local SOURCE_CLASS_ENGLISH = "quotesourceenglish" |
|||
-- 内部函数:分割引文文本(极致优化版本) |
|||
local function splitQuote(text) |
local function splitQuote(text) |
||
-- 快速检查:如果文本为空,返回空结果 |
-- 快速检查:如果文本为空,返回空结果 |
||
if not text |
if not text then |
||
return "", "" |
return "", "" |
||
end |
end |
||
local textLen = #text |
|||
-- 使用更高效的方式:先找第一个冒号,再检查是否有第二个 |
|||
if textLen == 0 then |
|||
local firstColonPos = mw.ustring.find(text, ":") |
|||
return "", "" |
|||
if not firstColonPos then |
|||
return "", text -- 没有冒号,整个文本作为引文内容 |
|||
end |
end |
||
-- |
-- 极致优化:一次遍历完成冒号检查 |
||
local colonPos = nil |
|||
local secondColonPos = mw.ustring.find(text, ":", firstColonPos + 1) |
|||
local colonCount = 0 |
|||
return "", text -- 有多个冒号,整个文本作为引文内容 |
|||
-- 使用 mw.ustring.gmatch 一次性获取所有冒号位置 |
|||
for pos in mw.ustring.gmatch(text, "():") do |
|||
colonCount = colonCount + 1 |
|||
if colonCount == 1 then |
|||
colonPos = pos |
|||
else |
|||
-- 有多个冒号,直接返回 |
|||
return "", text |
|||
end |
|||
end |
end |
||
-- 没有冒号 |
|||
-- 现在确定只有一个冒号,检查冒号前面是否有中文逗号或中文句号 |
|||
if colonCount == 0 then |
|||
local beforeColon = mw.ustring.sub(text, 1, firstColonPos - 1) |
|||
return "", text |
|||
if mw.ustring.find(beforeColon, "[,。]") then |
|||
return "", text -- 不符合条件,整个文本作为引文内容 |
|||
end |
end |
||
-- 检查冒号前是否有标点(只检查冒号前的部分) |
|||
-- 分割文本 |
|||
if colonPos > 1 then |
|||
local afterColon = mw.ustring.sub(text, firstColonPos + 1) |
|||
local beforeColonText = mw.ustring.sub(text, 1, colonPos - 1) |
|||
if mw.ustring.find(beforeColonText, PUNCT_PATTERN) then |
|||
-- 处理特例:'''123:'''456 格式和星号开头(优化:对ASCII字符使用string函数) |
|||
return "", text |
|||
-- 检查开头是否为ASCII字符(单引号或星号) |
|||
if afterColon:sub(1, 1) == "'" then |
|||
-- 检查是否为三个单引号 |
|||
if afterColon:sub(1, 3) == "'''" then |
|||
-- 移除冒号后的三个单引号,在冒号前添加三个单引号 |
|||
afterColon = afterColon:sub(4) |
|||
beforeColon = beforeColon .. "'''" |
|||
end |
end |
||
end |
|||
elseif afterColon:sub(1, 1) == "*" then |
|||
-- 处理冒号后文本开头的星号 |
|||
-- 分割文本(一次性完成) |
|||
afterColon = "<span>*</span>" .. afterColon:sub(2) |
|||
local beforeColon = mw.ustring.sub(text, 1, colonPos - 1) |
|||
local afterColon = mw.ustring.sub(text, colonPos + 1) |
|||
-- 极致优化:预检查 afterColon 的第一个字节 |
|||
-- 对于中文文本,大部分情况下不会以 ' 或 * 开头 |
|||
if textLen > colonPos then |
|||
local firstByte = text:byte(colonPos + 1) |
|||
-- ASCII 单引号 (39) 或星号 (42) 的快速检查 |
|||
if firstByte == 39 then -- ' |
|||
-- 使用混合方法:先用 string 快速检查,再用 mw.ustring 精确处理 |
|||
if text:sub(colonPos + 1, colonPos + 3) == TRIPLE_QUOTE then |
|||
-- 确认是三个单引号,使用 mw.ustring 精确处理 |
|||
local afterLen = mw.ustring.len(afterColon) |
|||
if afterLen >= 3 and mw.ustring.sub(afterColon, 1, 3) == TRIPLE_QUOTE then |
|||
afterColon = mw.ustring.sub(afterColon, 4) |
|||
beforeColon = beforeColon .. TRIPLE_QUOTE |
|||
end |
|||
end |
|||
elseif firstByte == 42 then -- * |
|||
-- 星号处理:混合方法 |
|||
if mw.ustring.sub(afterColon, 1, 1) == "*" then |
|||
afterColon = STAR_SPAN .. mw.ustring.sub(afterColon, 2) |
|||
end |
|||
end |
|||
-- 对于其他字符(主要是中文),跳过特殊处理 |
|||
end |
end |
||
| 第49行: | 第102行: | ||
end |
end |
||
-- 主要的 squote 函数,处理整个引文模板逻辑( |
-- 主要的 squote 函数,处理整个引文模板逻辑(极致优化版本) |
||
function p.squote(frame) |
function p.squote(frame) |
||
local |
local args = frame.args |
||
local |
local text = args[1] or "引文" |
||
local |
local source = args[2] or "" |
||
local textStyle = args.text or "" |
|||
-- 分割引文 |
-- 分割引文 |
||
local quoteBefore, quoteAfter = splitQuote(text) |
local quoteBefore, quoteAfter = splitQuote(text) |
||
-- 极致优化:预计算所有条件 |
|||
-- 检查是否需要清除说话人名称(使用缓存的变量,避免重复调用) |
|||
local hasQuoteBefore = quoteBefore ~= "" |
|||
local shouldClearBefore = false |
local shouldClearBefore = false |
||
if quoteBefore ~= "" and quoteBefore == quoteLast then |
|||
if hasQuoteBefore and quoteBefore == quoteLast then |
|||
-- 检查引文内容是否包含性别标记(优化:使用普通字符串查找) |
|||
-- 性别标记检查:使用预编译的常量和字节级搜索 |
|||
local afterText = quoteAfter |
local afterText = quoteAfter |
||
local hasGenderMarker = afterText:find(MALE_MARKER, 1, true) or afterText:find(FEMALE_MARKER, 1, true) |
|||
shouldClearBefore = not hasGenderMarker |
|||
end |
|||
end |
end |
||
-- 预计算样式类名 |
-- 预计算样式类名 |
||
local |
local isEnglish = textStyle == "english" |
||
local |
local textClass = isEnglish and TEXT_CLASS_ENGLISH or TEXT_CLASS_NORMAL |
||
-- 构建HTML结果(使用字符串拼接 |
-- 构建HTML结果(极致优化:使用table.concat减少字符串拼接开销) |
||
local htmlParts = {} |
|||
local html = '<table class="quotetable"><tr><td rowspan="2" class="decorativesquote"></td><td class="' .. textClass .. '">' |
|||
local partCount = 0 |
|||
-- 添加表格开始和文本类 |
|||
partCount = partCount + 1 |
|||
htmlParts[partCount] = HTML_TABLE_START .. textClass .. '">' |
|||
-- 添加说话人 |
-- 添加说话人(如果需要) |
||
if |
if hasQuoteBefore and not shouldClearBefore then |
||
partCount = partCount + 1 |
|||
htmlParts[partCount] = quoteBefore .. COLON_CHAR |
|||
-- 更新缓存的说话人 |
-- 更新缓存的说话人 |
||
quoteLast = quoteBefore |
quoteLast = quoteBefore |
||
-- |
-- 延迟设置全局变量到最后(减少中断) |
||
frame:callParserFunction('#vardefine', {'quote_last', quoteBefore}) |
frame:callParserFunction('#vardefine', {'quote_last', quoteBefore}) |
||
end |
end |
||
-- 添加引文内容 |
-- 添加引文内容 |
||
partCount = partCount + 1 |
|||
htmlParts[partCount] = HTML_QUOTE_START |
|||
partCount = partCount + 1 |
|||
if quoteAfter ~= "" then |
if quoteAfter ~= "" then |
||
htmlParts[partCount] = quoteAfter |
|||
else |
else |
||
htmlParts[partCount] = text -- 如果没有成功分割,使用原文本 |
|||
end |
end |
||
html = html .. '”</td></tr>' |
|||
partCount = partCount + 1 |
|||
htmlParts[partCount] = HTML_QUOTE_END |
|||
-- 添加来源行(如果提供了来源) |
-- 添加来源行(如果提供了来源) |
||
if source ~= "" then |
if source ~= "" then |
||
local sourceClass = isEnglish and SOURCE_CLASS_ENGLISH or SOURCE_CLASS_NORMAL |
|||
html = html .. '<tr><td class="' .. sourceClass .. '">— ' .. source .. '</td></tr>' |
|||
partCount = partCount + 1 |
|||
htmlParts[partCount] = HTML_SOURCE_START .. sourceClass .. HTML_SOURCE_MID .. source .. HTML_SOURCE_END |
|||
end |
end |
||
partCount = partCount + 1 |
|||
htmlParts[partCount] = HTML_TABLE_END |
|||
-- 一次性拼接所有HTML片段(最高效的字符串拼接方法) |
|||
return html |
|||
return table.concat(htmlParts, "", 1, partCount) |
|||
end |
end |
||
2025年7月10日 (四) 18:58的版本
local p = {}
-- 缓存全局变量以减少重复调用
local quoteLast = ""
-- 预编译的正则表达式模式(避免重复编译)
local COLON_PATTERN = ":"
local PUNCT_PATTERN = "[,。]"
local TRIPLE_QUOTE = "'''"
local STAR_SPAN = "<span>*</span>"
-- 预编译的HTML模板片段(避免重复字符串拼接)
local HTML_TABLE_START = '<table class="quotetable"><tr><td rowspan="2" class="decorativesquote"></td><td class="'
local HTML_QUOTE_START = '"'
local HTML_QUOTE_END = '"</td></tr>'
local HTML_SOURCE_START = '<tr><td class="'
local HTML_SOURCE_MID = '">— '
local HTML_SOURCE_END = '</td></tr>'
local HTML_TABLE_END = '</table>'
local COLON_CHAR = ':'
-- 性别标记检查的预编译模式
local MALE_MARKER = "(男)"
local FEMALE_MARKER = "(女)"
-- 样式类名预编译
local TEXT_CLASS_NORMAL = "squotetext"
local TEXT_CLASS_ENGLISH = "squotetextenglish"
local SOURCE_CLASS_NORMAL = "quotesource"
local SOURCE_CLASS_ENGLISH = "quotesourceenglish"
-- 内部函数:分割引文文本(极致优化版本)
local function splitQuote(text)
-- 快速检查:如果文本为空,返回空结果
if not text then
return "", ""
end
local textLen = #text
if textLen == 0 then
return "", ""
end
-- 极致优化:一次遍历完成冒号检查
local colonPos = nil
local colonCount = 0
-- 使用 mw.ustring.gmatch 一次性获取所有冒号位置
for pos in mw.ustring.gmatch(text, "():") do
colonCount = colonCount + 1
if colonCount == 1 then
colonPos = pos
else
-- 有多个冒号,直接返回
return "", text
end
end
-- 没有冒号
if colonCount == 0 then
return "", text
end
-- 检查冒号前是否有标点(只检查冒号前的部分)
if colonPos > 1 then
local beforeColonText = mw.ustring.sub(text, 1, colonPos - 1)
if mw.ustring.find(beforeColonText, PUNCT_PATTERN) then
return "", text
end
end
-- 分割文本(一次性完成)
local beforeColon = mw.ustring.sub(text, 1, colonPos - 1)
local afterColon = mw.ustring.sub(text, colonPos + 1)
-- 极致优化:预检查 afterColon 的第一个字节
-- 对于中文文本,大部分情况下不会以 ' 或 * 开头
if textLen > colonPos then
local firstByte = text:byte(colonPos + 1)
-- ASCII 单引号 (39) 或星号 (42) 的快速检查
if firstByte == 39 then -- '
-- 使用混合方法:先用 string 快速检查,再用 mw.ustring 精确处理
if text:sub(colonPos + 1, colonPos + 3) == TRIPLE_QUOTE then
-- 确认是三个单引号,使用 mw.ustring 精确处理
local afterLen = mw.ustring.len(afterColon)
if afterLen >= 3 and mw.ustring.sub(afterColon, 1, 3) == TRIPLE_QUOTE then
afterColon = mw.ustring.sub(afterColon, 4)
beforeColon = beforeColon .. TRIPLE_QUOTE
end
end
elseif firstByte == 42 then -- *
-- 星号处理:混合方法
if mw.ustring.sub(afterColon, 1, 1) == "*" then
afterColon = STAR_SPAN .. mw.ustring.sub(afterColon, 2)
end
end
-- 对于其他字符(主要是中文),跳过特殊处理
end
return beforeColon, afterColon
end
-- 主要的 squote 函数,处理整个引文模板逻辑(极致优化版本)
function p.squote(frame)
local args = frame.args
local text = args[1] or "引文"
local source = args[2] or ""
local textStyle = args.text or ""
-- 分割引文
local quoteBefore, quoteAfter = splitQuote(text)
-- 极致优化:预计算所有条件
local hasQuoteBefore = quoteBefore ~= ""
local shouldClearBefore = false
if hasQuoteBefore and quoteBefore == quoteLast then
-- 性别标记检查:使用预编译的常量和字节级搜索
local afterText = quoteAfter
local hasGenderMarker = afterText:find(MALE_MARKER, 1, true) or afterText:find(FEMALE_MARKER, 1, true)
shouldClearBefore = not hasGenderMarker
end
-- 预计算样式类名
local isEnglish = textStyle == "english"
local textClass = isEnglish and TEXT_CLASS_ENGLISH or TEXT_CLASS_NORMAL
-- 构建HTML结果(极致优化:使用table.concat减少字符串拼接开销)
local htmlParts = {}
local partCount = 0
-- 添加表格开始和文本类
partCount = partCount + 1
htmlParts[partCount] = HTML_TABLE_START .. textClass .. '">'
-- 添加说话人(如果需要)
if hasQuoteBefore and not shouldClearBefore then
partCount = partCount + 1
htmlParts[partCount] = quoteBefore .. COLON_CHAR
-- 更新缓存的说话人
quoteLast = quoteBefore
-- 延迟设置全局变量到最后(减少中断)
frame:callParserFunction('#vardefine', {'quote_last', quoteBefore})
end
-- 添加引文内容
partCount = partCount + 1
htmlParts[partCount] = HTML_QUOTE_START
partCount = partCount + 1
if quoteAfter ~= "" then
htmlParts[partCount] = quoteAfter
else
htmlParts[partCount] = text -- 如果没有成功分割,使用原文本
end
partCount = partCount + 1
htmlParts[partCount] = HTML_QUOTE_END
-- 添加来源行(如果提供了来源)
if source ~= "" then
local sourceClass = isEnglish and SOURCE_CLASS_ENGLISH or SOURCE_CLASS_NORMAL
partCount = partCount + 1
htmlParts[partCount] = HTML_SOURCE_START .. sourceClass .. HTML_SOURCE_MID .. source .. HTML_SOURCE_END
end
partCount = partCount + 1
htmlParts[partCount] = HTML_TABLE_END
-- 一次性拼接所有HTML片段(最高效的字符串拼接方法)
return table.concat(htmlParts, "", 1, partCount)
end
return p