模組:沙盒/PexEric/1
外观
local p = {}
-- 依赖模块
local Arguments = require('Module:Arguments')
local TPV = require('Module:Template parameter value') -- Template Parameter Value
-- WikiProject banner shell 及其重定向的Lua正则表达式列表 (小写处理,匹配时会忽略大小写)
-- 这些模式用于 Module:Template parameter value
local WPBANNER_SHELL_PATTERNS = {
"wiki%s*project%s*banner%s*shell",
"w?pj?%s*banner%s*shell",
"wiki%s*project%s*banners",
"multiple%s*wikiprojects?",
"wiki%s*project%s*shell",
"pjbs",
"[維维]基[专專][题題][橫横]幅",
"多?[個个]?[維维]?基?[专專][题題][橫横]幅",
"[維维]基[专專][题題]",
"多?[個个]?[維维]?基?[专專][题題]",
"[专專][题題][橫横]幅",
"通用[評评][級级]",
}
-- 内部函数:从页面内容中获取候选项目列表
-- 基于 Module:PatternedCandidateUtils 的 getCandidates 逻辑
local function _getCandidatesInternal(args_table)
local page_title_str = args_table.title
if not page_title_str or page_title_str == '' then
return {} -- 没有提供页面标题
end
local title_obj = mw.title.new(page_title_str)
if not title_obj or not title_obj.exists then
return {} -- 页面不存在
end
local page_content = title_obj:getContent()
if not page_content then
return {} -- 获取页面内容失败
end
local matches = {}
local black = {} -- 黑名单
if args_table.black then
for b in mw.text.gsplit(args_table.black, '|', true) do
black[b] = true
end
end
local pattern = args_table.pattern
if not pattern or pattern == '' then
return {} -- 没有提供匹配模式
end
-- 替换 MediaWiki 模板语法到 Lua 模式
pattern = pattern:gsub('%%{{!', '{{')
pattern = pattern:gsub('%%}}', '}}')
pattern = pattern:gsub('%%{{', '{') -- %{{ -> {
pattern = pattern:gsub('%%}}', '}') -- %}} -> }
for m in mw.ustring.gmatch(page_content, pattern) do
local clean_m = mw.text.trim(m) -- 清理可能捕获到的空白
-- 如果模式捕获的是类似 [[Article|Display]] 或 [[Article]] 的内容,尝试提取真实条目名
-- 这是一个基本清理,更复杂的清理应由 pattern 本身完成
clean_m = mw.ustring.gsub(clean_m, "^%[%[([^%]|]+)|.+%]%]$", "%1") -- [[Article|Display]] -> Article
clean_m = mw.ustring.gsub(clean_m, "^%[%[([^%]]+)%]%]$", "%1") -- [[Article]] -> Article
if not black[clean_m] and not (args_table.blackregex and mw.ustring.match(clean_m, args_table.blackregex)) then
table.insert(matches, clean_m)
end
end
return matches
end
-- 内部函数:获取指定条目的所属专题列表
local function _getProjectsForArticle(article_title_str)
if not article_title_str or article_title_str == '' then
return {}
end
local article_title_obj = mw.title.new(article_title_str)
if not article_title_obj then
return {} -- 无效的条目名
end
local talk_page_title_obj = article_title_obj:getTalkPage()
if not talk_page_title_obj or not talk_page_title_obj.exists then
return {} -- 讨论页不存在
end
-- 使用 Module:Template parameter value 获取参数 '1'
-- WPBANNER_SHELL_PATTERNS 包含所有 WikiProject banner shell 的重定向 (作为正则表达式)
local success, banner_shell_content = TPV.getParameter(
talk_page_title_obj.prefixedText,
WPBANNER_SHELL_PATTERNS,
'1', -- 匿名参数1
{ treat_as_regex = true, ignore_blank = true } -- 模板名列表是正则表达式,忽略空参数
)
if not success or not banner_shell_content or banner_shell_content == '' then
return {} -- 未找到专题横幅或参数1为空
end
local projects = {}
-- 从参数内容中提取模板名,例如 {{模板名1}}{{模板名2|参数=值}}
-- 这个 gmatch 会尝试匹配 {{...}} 结构,然后提取花括号后的第一个非空白、非管道符、非等号的序列作为模板名
for template_invocation in mw.ustring.gmatch(banner_shell_content, "{{.-}}") do
-- 提取模板名:{{ 开头,后面跟非 | 和 } 的字符,直到 | 或 }}
local project_name = mw.ustring.match(template_invocation, "{{%s*([^}|]+)")
if project_name then
project_name = mw.text.trim(project_name)
if project_name ~= "" then
table.insert(projects, project_name)
end
end
end
return projects
end
-- 主要函数1:以表格形式列出某个特定内容评选中所有候选项目对应的所属专题
function p.listProjectsForCandidates(frame)
local args = Arguments.getArgs(frame)
local candidates_fetch_args = {
title = args.title,
pattern = args.pattern,
black = args.black,
blackregex = args.blackregex
}
local candidates = _getCandidatesInternal(candidates_fetch_args)
if #candidates == 0 then
return args.no_candidates_text or "''当前没有候选项目。''"
end
local item_prefix = args.item_prefix or ""
local item_suffix = args.item_suffix or ""
local project_name_prefix = args.project_prefix or "{{tl|" -- 默认使用 {{tl|}} 包裹专题名
local project_name_suffix = args.project_suffix or "}}"
local linkprefix = args.linkprefix or "" -- 用于生成候选项目链接的前缀
local output_table = {'{| class="wikitable sortable candidate-projects-table"'}
table.insert(output_table, '! 候选项目 !! 所属专题')
for _, candidate_name in ipairs(candidates) do
local display_candidate_name = candidate_name:gsub("_", " ") -- 链接显示时替换下划线为空格
local linked_candidate_name
if linkprefix ~= "" then
linked_candidate_name = '[[:' .. linkprefix .. candidate_name .. '|' .. display_candidate_name .. ']]'
else
linked_candidate_name = '[[:' .. display_candidate_name .. ']]'
end
local wrapped_candidate_name = item_prefix .. linked_candidate_name .. item_suffix
local projects = _getProjectsForArticle(candidate_name)
local projects_str
if #projects > 0 then
local formatted_projects = {}
for _, proj_name in ipairs(projects) do
table.insert(formatted_projects, project_name_prefix .. proj_name .. project_name_suffix)
end
projects_str = table.concat(formatted_projects, '、') -- 使用顿号分隔
else
projects_str = args.no_projects_text or "''暂无专题''"
end
table.insert(output_table, '|-\n| ' .. wrapped_candidate_name .. ' || ' .. projects_str)
end
table.insert(output_table, '|}')
return table.concat(output_table, '\n')
end
-- 主要函数2:获取特定内容评选栏目中指定的属于一个或多个给定专题的候选项目
function p.filterCandidatesByProjects(frame)
local args = Arguments.getArgs(frame)
local candidates_fetch_args = {
title = args.title,
pattern = args.pattern,
black = args.black,
blackregex = args.blackregex
}
local candidates = _getCandidatesInternal(candidates_fetch_args)
if #candidates == 0 then
return args.no_candidates_text or "''当前没有候选项目。''"
end
-- 收集 projectN 参数作为正则表达式
local project_patterns = {}
local i = 1
while true do
local proj_arg_name = 'project' .. i
if args[proj_arg_name] then
table.insert(project_patterns, args[proj_arg_name])
else
-- 检查是否存在 project(无数字后缀),作为 project1 的别名
if i == 1 and args.project then
table.insert(project_patterns, args.project)
else
break -- 没有更多的 projectN 参数了
end
end
i = i + 1
end
if #project_patterns == 0 then
return "''错误:未指定任何专题进行筛选(缺少 project 或 project1 等参数)。''"
end
local item_prefix = args.item_prefix or ""
local item_suffix = args.item_suffix or ""
local linkprefix = args.linkprefix or ""
local matched_candidates_output = {}
for _, candidate_name in ipairs(candidates) do
local article_projects = _getProjectsForArticle(candidate_name)
local found_match_for_this_candidate = false
if #article_projects > 0 then
for _, actual_project_name in ipairs(article_projects) do
for _, pattern_to_match in ipairs(project_patterns) do
-- mw.ustring.match 返回非nil即为匹配成功
if mw.ustring.match(actual_project_name, pattern_to_match) then
found_match_for_this_candidate = true
break -- 当前条目的一个专题已匹配一个模式,无需再检查此条目的其他专题或模式
end
end
if found_match_for_this_candidate then
break -- 已找到匹配,跳出外层专题循环
end
end
end
if found_match_for_this_candidate then
local display_candidate_name = candidate_name:gsub("_", " ")
local linked_candidate_name
if linkprefix ~= "" then
linked_candidate_name = '[[:' .. linkprefix .. candidate_name .. '|' .. display_candidate_name .. ']]'
else
linked_candidate_name = '[[:' .. display_candidate_name .. ']]'
end
local wrapped_candidate_name = item_prefix .. linked_candidate_name .. item_suffix
table.insert(matched_candidates_output, wrapped_candidate_name)
end
end
if #matched_candidates_output > 0 then
return '# ' .. table.concat(matched_candidates_output, '\n# ') -- 输出为 # 号列表
else
return args.no_filtered_results_text or "''没有找到符合指定专题条件的候选项目。''"
end
end
return p