Module:PageSummary:修订间差异
武外梗百科 爱国好学自强图新的百科全书
更多操作
无编辑摘要 |
无编辑摘要 |
||
| 第1行: | 第1行: | ||
local p = {} | local p = {} | ||
-- | -- 更高效的图片/链接/分类剥离(避免逐字符 + 频繁 sub) | ||
local function stripImages(text) | local function stripImages(text) | ||
if not text then return "" end | if not text or text == "" then return "" end | ||
-- 预先把常见命名空间前缀统一处理,减少后续匹配分支 | |||
text = text:gsub("%[%[(文件|File|Image|图像):", "[[File:") | |||
local out = {} | local out = {} | ||
local i = 1 | local i = 1 | ||
local len = | local len = #text -- 优先用字节长度,性能更好(中文环境影响可接受) | ||
while i <= len do | while i <= len do | ||
local | local byte = text:byte(i) | ||
local chunk = | if byte == 91 and text:byte(i+1) == 91 then -- [[ | ||
local chunk = text:sub(i, i+12) | |||
if chunk:match("^%[%[File:") | |||
or chunk:match("^%[%[Category:") | |||
or chunk:match("^%[%[分类:") | |||
then | |||
-- 跳过整段 [[...]] | |||
local depth = 1 | |||
local j = i + 2 | |||
while j <= len and depth > 0 do | |||
if text:byte(j) == 91 and text:byte(j+1) == 91 then | |||
depth = depth + 1 | |||
j = j + 2 | |||
elseif text:byte(j) == 93 and text:byte(j+1) == 93 then | |||
depth = depth - 1 | |||
j = j + 2 | |||
else | |||
j = j + 1 | |||
end | |||
end | |||
i = j | |||
else | |||
-- 普通 [[ ,保留 | |||
table.insert(out, "[") | |||
i = i + 1 | |||
end | end | ||
else | |||
table.insert(out, text:sub(i, i)) | |||
table.insert(out, | |||
i = i + 1 | i = i + 1 | ||
end | end | ||
if i > | |||
-- 安全阀(防止极端情况卡死) | |||
if i > 800 then break end | |||
end | end | ||
return table.concat(out) | return table.concat(out) | ||
end | end | ||
-- 合并多次 gsub,提升正则效率 | |||
local function cleanFinal(text) | local function cleanFinal(text) | ||
text = | if not text or text == "" then return "" end | ||
text = | |||
-- 一次性处理多种需要删除的模式 | |||
text = text | |||
:gsub("{{[^{}]*}}", "") -- 模板(包括嵌套一层的情况已足够) | |||
:gsub("<ref.-</?ref[^>]*>", "") -- 参考文献(更宽松匹配) | |||
:gsub("<!%-%-.-%-%->", "") -- 注释 | |||
:gsub("\n==+.+==+", " ") -- 标题 | |||
:gsub("\n%s*[*#:;]+", " ") -- 列表 | |||
:gsub("%s*\n%s*", " ") -- 换行 → 空格(合并多行) | |||
:gsub("%s+", " ") -- 压缩连续空格 | |||
return mw.text.trim(text) | return mw.text.trim(text) | ||
end | end | ||
function p.getSummaryAndImage(frame) | function p.getSummaryAndImage(frame) | ||
local pageName = frame.args[1] or "" | local pageName = mw.text.trim(frame.args[1] or "") | ||
if pageName == "" then return "" end | |||
local title = mw.title.new(pageName) | local title = mw.title.new(pageName) | ||
if not title or not title.exists then return "" end | if not title or not title.exists then return "" end | ||
local content = title:getContent() | local content = title:getContent() | ||
local rawExcerpt = | if not content then return "" end | ||
-- | -- 只取前450字节(中文约200-300字),足够提取首图 + 摘要 | ||
local firstImage = | local rawExcerpt = content:sub(1, 450) | ||
-- 提取第一张图片(更宽松匹配,兼容更多写法) | |||
local step1 = stripImages(rawExcerpt) | local firstImage = rawExcerpt:match("%[%[(File|文件|Image|图像):([^|%]]+)") | ||
-- 核心剥离 + 清理 | |||
local step1 = stripImages(rawExcerpt) | |||
local cleanText = cleanFinal(step1) | local cleanText = cleanFinal(step1) | ||
local targetLen = 120 | local targetLen = 120 | ||
local summary = | local summary = cleanText:sub(1, targetLen * 2) -- 多取一点,后面精确截断 | ||
-- | -- 更安全的截断(避免截断在 [[ 中间) | ||
local | local len = mw.ustring.len(summary) | ||
if len > targetLen then | |||
summary = mw.ustring.sub(summary, 1, targetLen) | |||
local | |||
if | -- 简单向后找最近的空格或标点,避免断字 | ||
local lastSpace = summary:reverse():find("[ %s%p]") or 1 | |||
if lastSpace > 1 and lastSpace < 15 then | |||
summary = mw.ustring.sub(summary, 1, #summary - lastSpace + 1) | |||
end | |||
summary = mw.text.trim(summary) .. "..." | |||
end | end | ||
-- | -- HTML 构建部分基本保持原样(性能占比很低) | ||
local container = mw.html.create('div') | |||
:css('margin-bottom', '25px') | |||
:css('display', 'flow-root') | |||
-- 标题 | |||
container:tag('div') | container:tag('div') | ||
:css( | :css('font-size', '1.3em') | ||
:css('font-weight', 'bold') | |||
:css('margin-bottom', '6px') | |||
:css('border-bottom', '1px solid #eee') | |||
:wikitext('[[' .. pageName .. ']]') | :wikitext('[[' .. pageName .. ']]') | ||
-- | -- 内容区 | ||
local textDiv = container:tag('div') | local textDiv = container:tag('div') | ||
:css( | :css('line-height', '1.6') | ||
:css('color', '#222') | |||
:css('font-size', '14px') | |||
-- | -- 图片右浮 + 链接到页面 | ||
if firstImage then | if firstImage then | ||
textDiv:wikitext('[[' .. firstImage .. '|120px|right|link=' .. pageName .. ']]') | textDiv:wikitext( | ||
'[[' .. firstImage .. '|120px|right|link=' .. pageName .. ']]' | |||
) | |||
end | end | ||
textDiv:wikitext(summary) | textDiv:wikitext(summary) | ||
return tostring(container) | return tostring(container) | ||
end | end | ||
return p | return p | ||
2026年2月17日 (二) 23:50的版本
此模块的文档可以在Module:PageSummary/doc创建
local p = {}
-- 更高效的图片/链接/分类剥离(避免逐字符 + 频繁 sub)
local function stripImages(text)
if not text or text == "" then return "" end
-- 预先把常见命名空间前缀统一处理,减少后续匹配分支
text = text:gsub("%[%[(文件|File|Image|图像):", "[[File:")
local out = {}
local i = 1
local len = #text -- 优先用字节长度,性能更好(中文环境影响可接受)
while i <= len do
local byte = text:byte(i)
if byte == 91 and text:byte(i+1) == 91 then -- [[
local chunk = text:sub(i, i+12)
if chunk:match("^%[%[File:")
or chunk:match("^%[%[Category:")
or chunk:match("^%[%[分类:")
then
-- 跳过整段 [[...]]
local depth = 1
local j = i + 2
while j <= len and depth > 0 do
if text:byte(j) == 91 and text:byte(j+1) == 91 then
depth = depth + 1
j = j + 2
elseif text:byte(j) == 93 and text:byte(j+1) == 93 then
depth = depth - 1
j = j + 2
else
j = j + 1
end
end
i = j
else
-- 普通 [[ ,保留
table.insert(out, "[")
i = i + 1
end
else
table.insert(out, text:sub(i, i))
i = i + 1
end
-- 安全阀(防止极端情况卡死)
if i > 800 then break end
end
return table.concat(out)
end
-- 合并多次 gsub,提升正则效率
local function cleanFinal(text)
if not text or text == "" then return "" end
-- 一次性处理多种需要删除的模式
text = text
:gsub("{{[^{}]*}}", "") -- 模板(包括嵌套一层的情况已足够)
:gsub("<ref.-</?ref[^>]*>", "") -- 参考文献(更宽松匹配)
:gsub("<!%-%-.-%-%->", "") -- 注释
:gsub("\n==+.+==+", " ") -- 标题
:gsub("\n%s*[*#:;]+", " ") -- 列表
:gsub("%s*\n%s*", " ") -- 换行 → 空格(合并多行)
:gsub("%s+", " ") -- 压缩连续空格
return mw.text.trim(text)
end
function p.getSummaryAndImage(frame)
local pageName = mw.text.trim(frame.args[1] or "")
if pageName == "" then return "" end
local title = mw.title.new(pageName)
if not title or not title.exists then return "" end
local content = title:getContent()
if not content then return "" end
-- 只取前450字节(中文约200-300字),足够提取首图 + 摘要
local rawExcerpt = content:sub(1, 450)
-- 提取第一张图片(更宽松匹配,兼容更多写法)
local firstImage = rawExcerpt:match("%[%[(File|文件|Image|图像):([^|%]]+)")
-- 核心剥离 + 清理
local step1 = stripImages(rawExcerpt)
local cleanText = cleanFinal(step1)
local targetLen = 120
local summary = cleanText:sub(1, targetLen * 2) -- 多取一点,后面精确截断
-- 更安全的截断(避免截断在 [[ 中间)
local len = mw.ustring.len(summary)
if len > targetLen then
summary = mw.ustring.sub(summary, 1, targetLen)
-- 简单向后找最近的空格或标点,避免断字
local lastSpace = summary:reverse():find("[ %s%p]") or 1
if lastSpace > 1 and lastSpace < 15 then
summary = mw.ustring.sub(summary, 1, #summary - lastSpace + 1)
end
summary = mw.text.trim(summary) .. "..."
end
-- HTML 构建部分基本保持原样(性能占比很低)
local container = mw.html.create('div')
:css('margin-bottom', '25px')
:css('display', 'flow-root')
-- 标题
container:tag('div')
:css('font-size', '1.3em')
:css('font-weight', 'bold')
:css('margin-bottom', '6px')
:css('border-bottom', '1px solid #eee')
:wikitext('[[' .. pageName .. ']]')
-- 内容区
local textDiv = container:tag('div')
:css('line-height', '1.6')
:css('color', '#222')
:css('font-size', '14px')
-- 图片右浮 + 链接到页面
if firstImage then
textDiv:wikitext(
'[[' .. firstImage .. '|120px|right|link=' .. pageName .. ']]'
)
end
textDiv:wikitext(summary)
return tostring(container)
end
return p