打开/关闭菜单
331
1.7K
131
11.8K
星露谷物语扩展百科
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

模块:Quote:修订间差异

来自星露谷物语扩展百科
Sizau留言 | 贡献
无编辑摘要
Sizau留言 | 贡献
无编辑摘要
第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 = '">&mdash; '
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 or text == "" then
     if not text then
        return "", ""
    end
   
    local textLen = #text
    if textLen == 0 then
         return "", ""
         return "", ""
     end
     end


     -- 使用更高效的方式:先找第一个冒号,再检查是否有第二个
     -- 极致优化:一次遍历完成冒号检查
     local firstColonPos = mw.ustring.find(text, ":")
     local colonPos = nil
    if not firstColonPos then
    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
 
   
     -- 检查是否有第二个冒号(从第一个冒号之后开始查找)
     -- 没有冒号
     local secondColonPos = mw.ustring.find(text, ":", firstColonPos + 1)
     if colonCount == 0 then
    if secondColonPos then
         return "", text
         return "", text -- 有多个冒号,整个文本作为引文内容
     end
     end
 
   
     -- 现在确定只有一个冒号,检查冒号前面是否有中文逗号或中文句号
     -- 检查冒号前是否有标点(只检查冒号前的部分)
     local beforeColon = mw.ustring.sub(text, 1, firstColonPos - 1)
     if colonPos > 1 then
    if mw.ustring.find(beforeColon, "[,。]") then
        local beforeColonText = mw.ustring.sub(text, 1, colonPos - 1)
        return "", text -- 不符合条件,整个文本作为引文内容
        if mw.ustring.find(beforeColonText, PUNCT_PATTERN) then
            return "", text
        end
     end
     end
 
   
     -- 分割文本
     -- 分割文本(一次性完成)
     local afterColon = mw.ustring.sub(text, firstColonPos + 1)
    local beforeColon = mw.ustring.sub(text, 1, colonPos - 1)
 
     local afterColon = mw.ustring.sub(text, colonPos + 1)
     -- 处理特例:'''123:'''456 格式和星号开头(优化:对ASCII字符使用string函数)
   
     -- 检查开头是否为ASCII字符(单引号或星号)
     -- 极致优化:预检查 afterColon 的第一个字节
     if afterColon:sub(1, 1) == "'" then
     -- 对于中文文本,大部分情况下不会以 ' 或 * 开头
        -- 检查是否为三个单引号
     if textLen > colonPos then
        if afterColon:sub(1, 3) == "'''" then
        local firstByte = text:byte(colonPos + 1)
            -- 移除冒号后的三个单引号,在冒号前添加三个单引号
       
            afterColon = afterColon:sub(4)
        -- ASCII 单引号 (39) 或星号 (42) 的快速检查
            beforeColon = beforeColon .. "'''"
        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
    elseif afterColon:sub(1, 1) == "*" then
         -- 对于其他字符(主要是中文),跳过特殊处理
         -- 处理冒号后文本开头的星号
        afterColon = "<span>*</span>" .. afterColon:sub(2)
     end
     end


第49行: 第102行:
end
end


-- 主要的 squote 函数,处理整个引文模板逻辑(高度优化版本)
-- 主要的 squote 函数,处理整个引文模板逻辑(极致优化版本)
function p.squote(frame)
function p.squote(frame)
     local text = frame.args[1] or "引文"
     local args = frame.args
     local source = frame.args[2] or ""
    local text = args[1] or "引文"
     local textStyle = frame.args.text or ""
     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
         if not (afterText:find("(男)", 1, true) or afterText:find("(女)", 1, true)) then
         local hasGenderMarker = afterText:find(MALE_MARKER, 1, true) or afterText:find(FEMALE_MARKER, 1, true)
            shouldClearBefore = true
        shouldClearBefore = not hasGenderMarker
        end
     end
     end


     -- 预计算样式类名(避免重复字符串拼接)
     -- 预计算样式类名
     local textClass = textStyle == "english" and "squotetextenglish" or "squotetext"
     local isEnglish = textStyle == "english"
     local sourceClass = textStyle == "english" and "quotesourceenglish" or "quotesource"
     local textClass = isEnglish and TEXT_CLASS_ENGLISH or TEXT_CLASS_NORMAL
 
   
     -- 构建HTML结果(使用字符串拼接,减少函数调用开销)
     -- 构建HTML结果(极致优化:使用table.concat减少字符串拼接开销)
     local html = '<table class="quotetable"><tr><td rowspan="2" class="decorativesquote"></td><td class="' .. textClass .. '">'
     local htmlParts = {}
    local partCount = 0
   
    -- 添加表格开始和文本类
    partCount = partCount + 1
    htmlParts[partCount] = HTML_TABLE_START .. textClass .. '">'


     -- 添加说话人和引文内容
     -- 添加说话人(如果需要)
     if quoteBefore ~= "" and not shouldClearBefore then
     if hasQuoteBefore and not shouldClearBefore then
         html = html .. quoteBefore .. ':'
         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


     -- 添加引文内容
     -- 添加引文内容
     html = html .. '“'
     partCount = partCount + 1
    htmlParts[partCount] = HTML_QUOTE_START
   
    partCount = partCount + 1
     if quoteAfter ~= "" then
     if quoteAfter ~= "" then
         html = html .. quoteAfter
         htmlParts[partCount] = quoteAfter
     else
     else
         html = html .. text -- 如果没有成功分割,使用原文本
         htmlParts[partCount] = text -- 如果没有成功分割,使用原文本
     end
     end
     html = html .. '”</td></tr>'
      
    partCount = partCount + 1
    htmlParts[partCount] = HTML_QUOTE_END


     -- 添加来源行(如果提供了来源)
     -- 添加来源行(如果提供了来源)
     if source ~= "" then
     if source ~= "" then
         html = html .. '<tr><td class="' .. sourceClass .. '">&mdash; ' .. source .. '</td></tr>'
         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
     end


     html = html .. '</table>'
     partCount = partCount + 1
    htmlParts[partCount] = HTML_TABLE_END


     return html
    -- 一次性拼接所有HTML片段(最高效的字符串拼接方法)
     return table.concat(htmlParts, "", 1, partCount)
end
end


return p
return p

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 = '">&mdash; '
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