Module:PageSummary
武外梗百科 爱国好学自强图新的百科全书
更多操作
此模块的文档可以在Module:PageSummary/doc创建
local p = {}
-- ────────────────────────────────────────────────
-- 剥离图片、分类等 [[File:…]] [[Category:…]] 结构,避免出现在摘要中
-- ────────────────────────────────────────────────
local function stripImages(text)
if not text or text == "" then return "" end
-- 统一常见命名空间写法,减少匹配分支
text = text:gsub("%[%[(文件|File|Image|图像):", "[[File:")
:gsub("%[%[(分类|Category):", "[[Category:")
local out = {}
local i = 1
local len = #text
while i <= len do
if text:byte(i) == 91 and text:byte(i+1) == 91 then -- [[
local chunk = text:sub(i, i+15)
if chunk:match("^%[%[File:") or chunk:match("^%[%[Category:") 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 + 2
end
else
table.insert(out, text:sub(i,i))
i = i + 1
end
if i > 1200 then break end -- 极端安全阀
end
return table.concat(out)
end
-- ────────────────────────────────────────────────
-- 清理模板、参考文献、标题、列表等,得到纯文本摘要
-- ────────────────────────────────────────────────
local function cleanFinal(text)
if not text or text == "" then return "" end
text = text
:gsub("{{[^{}]*}}", "") -- 模板(简单版,够用)
:gsub("<ref.-</?ref[^>]*>", "") -- 参考文献
:gsub("<!%-%-.-%-%->", "") -- HTML 注释
: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 or content == "" then return "" end
-- 安全取前 300 个 unicode 字符(避免字节截断中文)
local rawExcerpt = mw.ustring.sub(content, 1, 300)
-- 提取第一张图片(优先标准写法)
local firstImage = mw.ustring.match(rawExcerpt, "%[%[(File|文件|Image|图像):([^|%]]+)")
-- 备选:更宽松匹配,但只接受文件类
if not firstImage then
local candidate = mw.ustring.match(rawExcerpt, "%[%[([^|%]]+)%]")
if candidate then
local ns = candidate:match("^([^:]+):")
if ns and (ns:lower() == "file" or ns == "文件" or ns:lower() == "image" or ns == "图像") then
firstImage = candidate
end
end
end
local step1 = stripImages(rawExcerpt) or ""
local cleanText = cleanFinal(step1) or ""
local targetLen = 120
local summary = cleanText:sub(1, targetLen * 2) or ""
local ulen = mw.ustring.len(summary) or 0
if ulen > targetLen then
summary = mw.ustring.sub(summary, 1, targetLen) or ""
-- 尽量避免截在中文单词/句子中间
local rev = summary:reverse()
local lastBreak = rev:find("[ %s%p,。!?;:,…]") or 1
if lastBreak > 1 and lastBreak < 20 then
summary = mw.ustring.sub(summary, 1, #summary - lastBreak + 1) or ""
end
summary = mw.text.trim(summary) .. "..."
end
summary = mw.text.trim(summary)
-- ── 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 and firstImage ~= "" then
firstImage = mw.text.trim(firstImage)
local img = '[[' .. firstImage .. '|120px|right|link=' .. pageName .. ']]'
textDiv:wikitext(img)
end
textDiv:wikitext(summary)
return tostring(container)
end
return p