模块:Documentation:修订间差异
来自星露谷物语扩展百科
更多操作
fork from minecraft wiki |
无编辑摘要 |
||
| (未显示同一用户的21个中间版本) | |||
| 第1行: | 第1行: | ||
local p = {} | local p = {} | ||
-- Load modules (language wikis exclusive) | |||
local stconv = require("Module:STConversion").lan | |||
-- Customizable strings | -- Customizable strings | ||
local i18n = { | local i18n = { | ||
-- | -- 设置 | ||
defaultDocPage = | defaultDocPage = "doc", -- 文档页后缀 | ||
defaultSandboxPage = | defaultSandboxPage = "sandbox", -- 沙盒页后缀 | ||
defaultTestCasePage = | defaultTestCasePage = "testcases", -- 测试用例页后缀 | ||
defaultPreload = | defaultPreload = "模板:Documentation/preload", -- 存储文档页标准内容的页面 | ||
defaultStyles = | defaultStyles = "Module:Documentation/styles.css", -- TemplateStyles 样式表 | ||
-- | -- 格式字符串 | ||
commonInternalLink = | commonInternalLink = "[[%s]]", | ||
commonInternalLinkPipe = | commonInternalLinkPipe = "[[%s|%s]]", | ||
commonExternalLink = | commonExternalLink = "[%s]", | ||
commonExternalLinkWithName = | commonExternalLinkWithName = "[%s %s]", | ||
commonNamespacedPage = | commonNamespacedPage = "%s:%s", | ||
commonNamespacedPageWithSub = | commonNamespacedPageWithSub = "%s:%s/%s", | ||
-- | -- 命名空间名称 | ||
namespaceCategory = | namespaceCategory = "分类", | ||
namespaceSpecial = | namespaceSpecial = "特殊", | ||
namespaceUser = | namespaceUser = "用户", | ||
specialPurge = "Purge", | |||
specialPurge = | specialEdit = "EditPage", | ||
specialEdit = | specialHistory = "PageHistory", | ||
specialHistory = | |||
-- | -- 页面类型名称 | ||
pageType_page = | pageType_page = stconv({ | ||
pageType_template = | ["zh-hans"] = "页面", | ||
pageType_module = | ["zh-hk"] = "頁面", | ||
pageType_stylesheet = | }), | ||
pageType_script = | pageType_template = "模板", | ||
pageType_json = | pageType_module = stconv({ | ||
pageType_message = | ["zh-hans"] = "模块", | ||
["zh-hk"] = "模組", | |||
}), | |||
pageType_stylesheet = stconv({ | |||
["zh-hans"] = "样式表", | |||
["zh-hk"] = "樣式表", | |||
}), | |||
pageType_script = stconv({ | |||
["zh-hans"] = "脚本", | |||
["zh-hk"] = "腳本", | |||
}), | |||
pageType_json = "JSON", | |||
pageType_message = stconv({ | |||
["zh-hans"] = "界面信息", | |||
["zh-hk"] = "介面訊息", | |||
}), | |||
-- | -- 链接显示方式 | ||
linkBar = mw.text.nowiki( | linkBar = mw.text.nowiki("[ ") .. "%s" .. mw.text.nowiki(" ]"), -- 整个链接条使用的整体样式 | ||
linkFormat = | linkFormat = "%s", -- 单个链接使用的样式 | ||
linkSeparator = mw.text.nowiki( mw.getCurrentFrame():callParserFunction( | linkSeparator = mw.text.nowiki(mw.getCurrentFrame():callParserFunction("int:pipe-separator")), -- 不同链接间的分隔符 | ||
-- | -- 不同类型链接的显示名称 | ||
linkTextPurge = mw.getCurrentFrame():callParserFunction( | linkTextPurge = mw.getCurrentFrame():callParserFunction("int:purge"), | ||
linkTextView = mw.getCurrentFrame():callParserFunction( | linkTextView = mw.getCurrentFrame():callParserFunction("int:view"), | ||
linkTextEdit = mw.getCurrentFrame():callParserFunction( | linkTextEdit = mw.getCurrentFrame():callParserFunction("int:edit"), | ||
linkTextHistory = mw.getCurrentFrame():callParserFunction( | linkTextHistory = mw.getCurrentFrame():callParserFunction("int:history_short"), | ||
linkTextCreate = mw.getCurrentFrame():callParserFunction( | linkTextCreate = mw.getCurrentFrame():callParserFunction("int:create"), | ||
-- p.create()中使用的字符串:使用{{doc}}或{{subst:doc}}时显示的内容 | -- p.create() 中使用的字符串:使用 {{doc}} 或 {{subst:doc}} 时显示的内容 | ||
createOutputFormat = | createOutputFormat = "<noinclude>%s%s</noinclude>", -- 整体格式 | ||
createSplitDocPagePrompt = | createSplitDocPagePrompt = "\n<!-- 请将分类/语言链接放在文档页面 -->", -- 要创建的文档页面为独立页面时显示的字符串 | ||
createNoSubstCategory = | createNoSubstCategory = "需要替换模板的页面", -- 使用 {{doc}} 时未使用替代语法所添加的追踪分类 | ||
-- p.docPage()中使用的字符串:文档页显示的内容 | -- p.docPage() 中使用的字符串:文档页显示的内容 | ||
-- For messages with format placeholders, store the template with placeholders | |||
docPagePrompt_template_hans = "当前页面是文档页面,%s被%s引入。查看[[模板:Documentation]]获取更多信息。", | |||
docPagePrompt_template_hant = "這是說明文件頁面,它%s被放置到%s。查看[[Template:Documentation]]以取得更多資訊。", | |||
docPageCategory = | docPagePromptWill = stconv({ | ||
["zh-hans"] = "会", | |||
["zh-hk"] = "將", | |||
}), | |||
docPagePromptShould = stconv({ | |||
["zh-hans"] = "会", | |||
["zh-hk"] = "應該", | |||
}), | |||
docPageBadDocPrompt_template_hans = "<br>'''%s的文档页面质量较低或信息缺失,需要进一步修改。'''", | |||
docPageBadDocPrompt_template_hant = "<br>'''此%s的說明文件頁面需要改進或加上附加資訊。'''", | |||
docPageCategory = "文档页面", -- 文档页的追踪分类 | |||
-- p.page()中使用的字符串:代码页显示的内容 | -- p.page() 中使用的字符串:代码页显示的内容 | ||
pageNoDocPrompt_template_hans = "'''当前%s文档缺失,需要扩充。'''", | |||
pageNoDocPrompt_template_hant = "'''此%s没有說明文件頁面。如果你知道此%s的使用方法,請幫助為其建立說明文件頁面。'''", | |||
pageNoDocCategoryDefault = ' | |||
pageNoDocCategory_template_hans = "文档缺失的%s", | |||
pageBadDocCategoryDefault = | pageNoDocCategoryDefault = "文档缺失的页面", | ||
pageDocHeaderTitle = | |||
pageDocJumpToCode = | pageBadDocPrompt_template_hans = "'''%s的文档页面质量较低或信息缺失,需要进一步修改。'''\n", | ||
pageBadDocPrompt_template_hant = "'''此%s的說明文件頁面需要改進或加上附加資訊。'''\n", | |||
pageBadDocCategory_template_hans = "文档质量较低的%s", | |||
pageBadDocCategoryDefault = "文档质量较低的页面", | |||
pageDocHeaderTitle = stconv({ | |||
["zh-hans"] = "文档页面", | |||
["zh-hk"] = "說明文件頁面", | |||
}), | |||
pageDocJumpToCode = stconv({ | |||
["zh-hans"] = "跳转至代码 ↴", | |||
["zh-hk"] = "跳轉至程式碼 ↴", | |||
}), | |||
pageDocHeaderBottom_template_hans = "上述文档的内容来自%s。", | |||
pageDocHeaderBottom_template_hant = "上述說明文件嵌入至%s。", | |||
-- 全局跨语言链接 | |||
globalInterwikiLinks = { | |||
{ lang = "de", prefix = "Vorlage" }, | |||
{ lang = "en", prefix = "Template" }, | |||
{ lang = "es", prefix = "Plantilla" }, | |||
{ lang = "fr", prefix = "Modèle" }, | |||
{ lang = "it", prefix = "Template" }, | |||
{ lang = "ja", prefix = "テンプレート" }, | |||
{ lang = "ko", prefix = "틀" }, | |||
{ lang = "hu", prefix = "Sablon" }, | |||
{ lang = "pt", prefix = "Predefinição" }, | |||
{ lang = "ru", prefix = "Шаблон" }, | |||
{ lang = "tr", prefix = "Şablon" }, | |||
}, | |||
} | } | ||
-- Helper function to format strings with language conversion | |||
local function formatWithConv(hans_template, hant_template, ...) | |||
local args = {...} | |||
-- Count the number of %s in each template | |||
local hans_count = select(2, string.gsub(hans_template, "%%s", "")) | |||
local hant_count = select(2, string.gsub(hant_template, "%%s", "")) | |||
-- Build arguments for each template based on their placeholder count | |||
local hans_args = {} | |||
local hant_args = {} | |||
for i = 1, math.max(hans_count, hant_count) do | |||
if i <= hans_count then | |||
hans_args[i] = args[i] or "" | |||
end | |||
if i <= hant_count then | |||
hant_args[i] = args[i] or "" | |||
end | |||
end | |||
local hans_result = string.format(hans_template, unpack(hans_args)) | |||
local hant_result = string.format(hant_template, unpack(hant_args)) | |||
return stconv({ | |||
["zh-hans"] = hans_result, | |||
["zh-hk"] = hant_result, | |||
}) | |||
end | |||
-- Customizable functions | -- Customizable functions | ||
local function pageCategoryHandler( category ) | local function pageCategoryHandler(category) | ||
return i18n.commonInternalLink:format( i18n.commonNamespacedPage:format( i18n.namespaceCategory, category ) ) | return i18n.commonInternalLink:format(i18n.commonNamespacedPage:format(i18n.namespaceCategory, category)) | ||
end | end | ||
-- Load modules | -- Load modules | ||
local loadStyles = require( | local loadStyles = require("Module:TSLoader").call | ||
local static = require( | local static = require("Module:Static") | ||
if not static.Documentation then | if not static.Documentation then | ||
static.Documentation = {} | static.Documentation = {} | ||
| 第87行: | 第174行: | ||
-- Internal functions | -- Internal functions | ||
local function getType( namespace, page ) | local function getType(namespace, page) | ||
local pageType = | local pageType = "page" | ||
if namespace == | if namespace == "Template" then | ||
pageType = | pageType = "template" | ||
elseif namespace == | elseif namespace == "Module" then | ||
pageType = | pageType = "module" | ||
elseif page.fullText:gsub( | elseif page.fullText:gsub("/" .. i18n.defaultDocPage .. "$", ""):find("%.css$") then | ||
pageType = | pageType = "stylesheet" | ||
elseif page.fullText:gsub( | elseif page.fullText:gsub("/" .. i18n.defaultDocPage .. "$", ""):find("%.js$") then | ||
pageType = | pageType = "script" | ||
elseif page.fullText:gsub( | elseif page.fullText:gsub("/" .. i18n.defaultDocPage .. "$", ""):find("%.json$") then | ||
pageType = | pageType = "json" | ||
elseif namespace == | elseif namespace == "MediaWiki" then | ||
pageType = | pageType = "message" | ||
end | end | ||
return pageType | return pageType | ||
end | end | ||
local function getDisplayType( pageType ) | local function getDisplayType(pageType) | ||
return i18n[ | return i18n["pageType_" .. pageType] or i18n.pageType_page | ||
end | |||
local function generateGlobalInterwikiLinks(f) | |||
local pageName = f:preprocess("{{PAGENAME}}") | |||
local links = {} | |||
for _, item in ipairs(i18n.globalInterwikiLinks) do | |||
table.insert(links, string.format("[[%s:%s:%s]]", item.lang, item.prefix, pageName)) | |||
end | |||
return "\n" .. table.concat(links, "\n") | |||
end | end | ||
-- Exported functions | -- Exported functions | ||
function p.create( f ) -- Creating a documentation page or transclusion through {{subst:doc}} | function p.create(f) -- Creating a documentation page or transclusion through {{subst:doc}} | ||
local args = require( | local args = require("Module:ProcessArgs").norm() | ||
local page = mw.title.getCurrentTitle() | local page = mw.title.getCurrentTitle() | ||
local docPage = args.page or i18n.commonNamespacedPageWithSub:format( page.nsText, page.baseText, i18n.defaultDocPage ) | local docPage = args.page | ||
or i18n.commonNamespacedPageWithSub:format(page.nsText, page.baseText, i18n.defaultDocPage) | |||
local out | local out | ||
if not args.content and tostring( page ) == docPage then | if not args.content and tostring(page) == docPage then | ||
local pageType = mw.ustring.lower( args.type or getType( page.nsText, page ) ) | local pageType = mw.ustring.lower(args.type or getType(page.nsText, page)) | ||
local pageTypeDisplay = getDisplayType( pageType ) | local pageTypeDisplay = getDisplayType(pageType) | ||
out = f:preprocess( mw.title.new( i18n.defaultPreload ):getContent():gsub( | out = f:preprocess(mw.title.new(i18n.defaultPreload):getContent():gsub("$1", pageTypeDisplay)) | ||
else | else | ||
local templateArgs = {} | local templateArgs = {} | ||
for _, key in ipairs{ | for _, key in ipairs({ "type", "page", "content", "nodoc", "baddoc", "global" }) do | ||
local val = args[ key ] | local val = args[key] | ||
if val then | if val then | ||
if key == | if key == "content" then | ||
table.insert( templateArgs, key .. | val = "\n" .. val .. "\n" | ||
end | |||
table.insert(templateArgs, key .. "=" .. val) | |||
end | end | ||
end | end | ||
out = | out = "{{Documentation|" .. table.concat(templateArgs, "|") .. "}}" | ||
out = out:gsub( | out = out:gsub("|}}", "}}") | ||
out = i18n.createOutputFormat:format( out, args.content and | out = i18n.createOutputFormat:format(out, args.content and "" or i18n.createSplitDocPagePrompt) | ||
end | end | ||
if not mw.isSubsting() then | if not mw.isSubsting() then | ||
out = f:preprocess( out ) | out = f:preprocess(out) | ||
if not args.nocat then | if not args.nocat then | ||
out = out .. i18n.commonInternalLink:format( i18n.commonNamespacedPage:format( i18n.namespaceCategory, i18n.createNoSubstCategory ) ) | out = out | ||
.. i18n.commonInternalLink:format( | |||
i18n.commonNamespacedPage:format(i18n.namespaceCategory, i18n.createNoSubstCategory) | |||
) | |||
end | end | ||
end | end | ||
| 第144行: | 第248行: | ||
end | end | ||
function p.docPage( f ) -- Header on the documentation page | function p.docPage(f) -- Header on the documentation page | ||
local args = require( | local args = require("Module:ProcessArgs").merge(true) | ||
local badDoc = args.baddoc | local badDoc = args.baddoc | ||
if badDoc then | if badDoc then | ||
static.Documentation.badDoc = | static.Documentation.badDoc = "1" | ||
end | end | ||
| 第159行: | 第263行: | ||
end | end | ||
local docPage = mw.title.new( args.page or i18n.commonNamespacedPageWithSub:format( page.nsText, page.baseText, i18n.defaultDocPage ) ) | local docPage = mw.title.new( | ||
if docPage ~= page then return end | args.page or i18n.commonNamespacedPageWithSub:format(page.nsText, page.baseText, i18n.defaultDocPage) | ||
) | |||
if docPage ~= page then | |||
return | |||
end | |||
local namespace = page.nsText | local namespace = page.nsText | ||
local pageType = mw.ustring.lower( args.type or getType( namespace, page ) ) | local pageType = mw.ustring.lower(args.type or getType(namespace, page)) | ||
local pageTypeDisplay = getDisplayType( pageType ) | local pageTypeDisplay = getDisplayType(pageType) | ||
local body = mw.html.create( | local body = mw.html.create("div"):addClass("documentation") | ||
body | body:addClass(badDoc and "documentation-badDoc" or "") | ||
:tag("div") | |||
:tag( | :addClass("documentation-header-tools") | ||
:wikitext( | |||
i18n.linkBar:format( | |||
i18n.linkFormat:format( | |||
i18n.commonInternalLinkPipe:format( | |||
i18n.commonNamespacedPageWithSub:format(i18n.namespaceSpecial, i18n.specialPurge, page.fullText), | |||
i18n.linkTextPurge | |||
) | |||
) | |||
) | |||
) | |||
:done() | :done() | ||
:wikitext( i18n. | :wikitext( | ||
formatWithConv( | |||
i18n.docPagePrompt_template_hans, | |||
i18n.docPagePrompt_template_hant, | |||
pageType == "module" and i18n.docPagePromptWill or i18n.docPagePromptShould, | |||
i18n.commonInternalLink:format(i18n.commonNamespacedPage:format(namespace, page.baseText)) | |||
) | |||
) | |||
if badDoc then | if badDoc then | ||
body:wikitext( i18n. | body:wikitext(formatWithConv( | ||
i18n.docPageBadDocPrompt_template_hans, | |||
i18n.docPageBadDocPrompt_template_hant, | |||
pageTypeDisplay | |||
)) | |||
end | end | ||
if not ( args.nocat or namespace == i18n.namespaceUser ) then | if not (args.nocat or namespace == i18n.namespaceUser) then | ||
body:wikitext( i18n.commonInternalLink:format( i18n.commonNamespacedPage:format( i18n.namespaceCategory, i18n.docPageCategory ) ) ) | body:wikitext( | ||
i18n.commonInternalLink:format( | |||
i18n.commonNamespacedPage:format(i18n.namespaceCategory, i18n.docPageCategory) | |||
) | |||
) | |||
end | end | ||
return loadStyles( i18n.defaultStyles ) .. tostring( body ) | return loadStyles(i18n.defaultStyles) .. tostring(body) | ||
end | end | ||
function p.page( f ) -- Wrapper around the documentation on the main page | function p.page(f) -- Wrapper around the documentation on the main page | ||
-- mw.text.trim uses mw.ustring.gsub, which silently fails on large strings | -- mw.text.trim uses mw.ustring.gsub, which silently fails on large strings | ||
local function trim( s ) | local function trim(s) | ||
return ( s:gsub( | return (s:gsub("^[\t\r\n\f ]+", ""):gsub("[\t\r\n\f ]+$", "")) | ||
--return string.gsub( s, '^[\t\r\n\f ]*(.-)[\t\r\n\f ]*$', '%1' ) | --return string.gsub( s, '^[\t\r\n\f ]*(.-)[\t\r\n\f ]*$', '%1' ) | ||
end | end | ||
local args = require( | local args = require("Module:ProcessArgs").merge(true) | ||
local page = mw.title.getCurrentTitle() | local page = mw.title.getCurrentTitle() | ||
local subpage = page.subpageText | local subpage = page.subpageText | ||
| 第197行: | 第328行: | ||
end | end | ||
local namespace = page.nsText | local namespace = page.nsText | ||
local docText = trim( args.content or | local docText = trim(args.content or "") | ||
if docText == | if docText == "" then | ||
docText = nil | |||
end | |||
local docPage | local docPage | ||
| 第205行: | 第338行: | ||
docPage = page | docPage = page | ||
else | else | ||
docPage = mw.title.new( args.page or i18n.commonNamespacedPageWithSub:format( namespace, page.text, i18n.defaultDocPage ) ) | docPage = mw.title.new( | ||
args.page or i18n.commonNamespacedPageWithSub:format(namespace, page.text, i18n.defaultDocPage) | |||
) | |||
noDoc = args.nodoc or not docPage.exists | noDoc = args.nodoc or not docPage.exists | ||
end | end | ||
local badDoc = args.baddoc | local badDoc = args.baddoc | ||
local pageType = mw.ustring.lower( args.type or getType( namespace, page ) ) | local pageType = mw.ustring.lower(args.type or getType(namespace, page)) | ||
local pageTypeDisplay = getDisplayType( pageType ) | local pageTypeDisplay = getDisplayType(pageType) | ||
if not docText and not noDoc then | if not docText and not noDoc then | ||
docText = trim( f:expandTemplate{ title = | docText = trim(f:expandTemplate({ title = ":" .. docPage.fullText })) | ||
if static.Documentation.badDoc and static.Documentation.badDoc == | if static.Documentation.badDoc and static.Documentation.badDoc == "1" then | ||
badDoc = 1 | badDoc = 1 | ||
end | end | ||
if docText == | if docText == "" then | ||
docText = nil | docText = nil | ||
noDoc = 1 | noDoc = 1 | ||
| 第224行: | 第359行: | ||
end | end | ||
if docText then | if docText then | ||
docText = | docText = "\n" .. docText .. "\n" | ||
end | end | ||
local docClass = | local docClass = "" | ||
local message | local message | ||
local category | local category | ||
if noDoc then | if noDoc then | ||
docClass = | docClass = "documentation-noDoc" | ||
message = i18n. | -- pageNoDocPrompt_template_hant has 2 %s, both need the same value | ||
if not ( args.nocat or namespace == i18n.namespaceUser ) then | message = formatWithConv( | ||
category = | i18n.pageNoDocPrompt_template_hans, | ||
if | i18n.pageNoDocPrompt_template_hant, | ||
pageTypeDisplay, | |||
pageTypeDisplay -- Second argument for zh-hant template | |||
) | |||
if not (args.nocat or namespace == i18n.namespaceUser) then | |||
-- Use simplified Chinese category name directly | |||
local categoryName = string.format(i18n.pageNoDocCategory_template_hans, pageTypeDisplay) | |||
-- Check if the category exists | |||
local categoryTitle = mw.title.new(i18n.commonNamespacedPage:format(i18n.namespaceCategory, categoryName)) | |||
if categoryTitle and categoryTitle.exists then | |||
category = categoryName | |||
else | |||
category = i18n.pageNoDocCategoryDefault | category = i18n.pageNoDocCategoryDefault | ||
end | end | ||
end | end | ||
elseif badDoc then | elseif badDoc then | ||
docClass = | docClass = "documentation-badDoc" | ||
message = i18n. | message = formatWithConv( | ||
if not ( args.nocat or namespace == i18n.namespaceUser ) then | i18n.pageBadDocPrompt_template_hans, | ||
category = | i18n.pageBadDocPrompt_template_hant, | ||
if | pageTypeDisplay | ||
) | |||
if not (args.nocat or namespace == i18n.namespaceUser) then | |||
-- Use simplified Chinese category name directly | |||
local categoryName = string.format(i18n.pageBadDocCategory_template_hans, pageTypeDisplay) | |||
-- Check if the category exists | |||
local categoryTitle = mw.title.new(i18n.commonNamespacedPage:format(i18n.namespaceCategory, categoryName)) | |||
if categoryTitle and categoryTitle.exists then | |||
category = categoryName | |||
else | |||
category = i18n.pageBadDocCategoryDefault | category = i18n.pageBadDocCategoryDefault | ||
end | end | ||
| 第251行: | 第408行: | ||
-- Generates the link bar | -- Generates the link bar | ||
local links = mw.html.create( | local links = mw.html.create("span"):attr("id", "documentation-header-tools") | ||
local linkList = {} | local linkList = {} | ||
if not noDoc then | if not noDoc then | ||
if page ~= docPage then | if page ~= docPage then | ||
table.insert( linkList, i18n.linkFormat:format( i18n.commonInternalLinkPipe:format( docPage.fullText, i18n.linkTextView ) ) ) | table.insert( | ||
linkList, | |||
i18n.linkFormat:format(i18n.commonInternalLinkPipe:format(docPage.fullText, i18n.linkTextView)) | |||
) | |||
end | end | ||
table.insert( linkList, i18n.linkFormat:format( i18n.commonInternalLinkPipe:format( i18n.commonNamespacedPageWithSub:format( i18n.namespaceSpecial, i18n.specialEdit, docPage.fullText ), i18n.linkTextEdit ) ) ) | table.insert( | ||
table.insert( linkList, i18n.linkFormat:format( i18n.commonInternalLinkPipe:format( i18n.commonNamespacedPageWithSub:format( i18n.namespaceSpecial, i18n.specialHistory, docPage.fullText ), i18n.linkTextHistory ) ) ) | linkList, | ||
i18n.linkFormat:format( | |||
i18n.commonInternalLinkPipe:format( | |||
i18n.commonNamespacedPageWithSub:format(i18n.namespaceSpecial, i18n.specialEdit, docPage.fullText), | |||
i18n.linkTextEdit | |||
) | |||
) | |||
) | |||
table.insert( | |||
linkList, | |||
i18n.linkFormat:format( | |||
i18n.commonInternalLinkPipe:format( | |||
i18n.commonNamespacedPageWithSub:format( | |||
i18n.namespaceSpecial, | |||
i18n.specialHistory, | |||
docPage.fullText | |||
), | |||
i18n.linkTextHistory | |||
) | |||
) | |||
) | |||
else | else | ||
table.insert( linkList, i18n.linkFormat:format( i18n.commonExternalLinkWithName:format( docPage:canonicalUrl{ action = | table.insert( | ||
linkList, | |||
i18n.linkFormat:format( | |||
i18n.commonExternalLinkWithName:format( | |||
docPage:canonicalUrl({ | |||
action = "edit", | |||
preload = i18n.defaultPreload, | |||
preloadparams = pageTypeDisplay, | |||
}), | |||
i18n.linkTextCreate | |||
) | |||
) | |||
) | |||
end | end | ||
table.insert( linkList, i18n.linkFormat:format( i18n.commonInternalLinkPipe:format( i18n.commonNamespacedPageWithSub:format( i18n.namespaceSpecial, i18n.specialPurge, docPage.fullText ), i18n.linkTextPurge ) ) ) | table.insert( | ||
links:wikitext( i18n.linkBar:format( table.concat( linkList, i18n.linkSeparator ) ) ) | linkList, | ||
i18n.linkFormat:format( | |||
i18n.commonInternalLinkPipe:format( | |||
i18n.commonNamespacedPageWithSub:format(i18n.namespaceSpecial, i18n.specialPurge, docPage.fullText), | |||
i18n.linkTextPurge | |||
) | |||
) | |||
) | |||
links:wikitext(i18n.linkBar:format(table.concat(linkList, i18n.linkSeparator))) | |||
local body = mw.html.create( | local body = mw.html.create("div"):addClass("documentation") | ||
body | body:addClass(docClass) | ||
local header = mw.html.create( | local header = mw.html.create("div"):addClass("documentation-header-top") | ||
header | header:node(links):tag("span"):addClass("documentation-header-title"):wikitext(i18n.pageDocHeaderTitle) | ||
local codePages = { | local codePages = { | ||
| 第285行: | 第478行: | ||
script = true, | script = true, | ||
} | } | ||
if not noDoc and codePages[ pageType ] then | if not noDoc and codePages[pageType] then | ||
header | header | ||
:tag( | :tag("span") | ||
:attr("id", "documentation-jump-to-code") | |||
:wikitext(i18n.commonInternalLinkPipe:format("#the-code", i18n.pageDocJumpToCode)) | |||
end | end | ||
body | body:node(header):done():wikitext(message):wikitext(docText) | ||
if not noDoc and page ~= docPage then | if not noDoc and page ~= docPage then | ||
body | body:tag("div") | ||
:addClass("documentation-header-bottom") | |||
:node(links) | |||
:wikitext(formatWithConv( | |||
i18n.pageDocHeaderBottom_template_hans, | |||
i18n.pageDocHeaderBottom_template_hant, | |||
i18n.commonInternalLink:format(docPage.fullText) | |||
)) | |||
end | end | ||
if category then | if category then | ||
body:wikitext( pageCategoryHandler( category ) ) | body:wikitext(pageCategoryHandler(category)) | ||
end | |||
local anchor = "" | |||
if not noDoc and pageType ~= "template" and pageType ~= "message" then | |||
anchor = mw.html.create("div"):attr("id", "the-code") | |||
end | end | ||
local anchor | local output = loadStyles(i18n.defaultStyles) .. tostring(body) .. tostring(anchor) | ||
if | |||
-- Add global interwiki links if requested | |||
if args.global then | |||
output = output .. generateGlobalInterwikiLinks(f) | |||
end | end | ||
return | return output | ||
end | end | ||
return p | return p | ||
2026年1月23日 (五) 21:05的最新版本
local p = {}
-- Load modules (language wikis exclusive)
local stconv = require("Module:STConversion").lan
-- Customizable strings
local i18n = {
-- 设置
defaultDocPage = "doc", -- 文档页后缀
defaultSandboxPage = "sandbox", -- 沙盒页后缀
defaultTestCasePage = "testcases", -- 测试用例页后缀
defaultPreload = "模板:Documentation/preload", -- 存储文档页标准内容的页面
defaultStyles = "Module:Documentation/styles.css", -- TemplateStyles 样式表
-- 格式字符串
commonInternalLink = "[[%s]]",
commonInternalLinkPipe = "[[%s|%s]]",
commonExternalLink = "[%s]",
commonExternalLinkWithName = "[%s %s]",
commonNamespacedPage = "%s:%s",
commonNamespacedPageWithSub = "%s:%s/%s",
-- 命名空间名称
namespaceCategory = "分类",
namespaceSpecial = "特殊",
namespaceUser = "用户",
specialPurge = "Purge",
specialEdit = "EditPage",
specialHistory = "PageHistory",
-- 页面类型名称
pageType_page = stconv({
["zh-hans"] = "页面",
["zh-hk"] = "頁面",
}),
pageType_template = "模板",
pageType_module = stconv({
["zh-hans"] = "模块",
["zh-hk"] = "模組",
}),
pageType_stylesheet = stconv({
["zh-hans"] = "样式表",
["zh-hk"] = "樣式表",
}),
pageType_script = stconv({
["zh-hans"] = "脚本",
["zh-hk"] = "腳本",
}),
pageType_json = "JSON",
pageType_message = stconv({
["zh-hans"] = "界面信息",
["zh-hk"] = "介面訊息",
}),
-- 链接显示方式
linkBar = mw.text.nowiki("[ ") .. "%s" .. mw.text.nowiki(" ]"), -- 整个链接条使用的整体样式
linkFormat = "%s", -- 单个链接使用的样式
linkSeparator = mw.text.nowiki(mw.getCurrentFrame():callParserFunction("int:pipe-separator")), -- 不同链接间的分隔符
-- 不同类型链接的显示名称
linkTextPurge = mw.getCurrentFrame():callParserFunction("int:purge"),
linkTextView = mw.getCurrentFrame():callParserFunction("int:view"),
linkTextEdit = mw.getCurrentFrame():callParserFunction("int:edit"),
linkTextHistory = mw.getCurrentFrame():callParserFunction("int:history_short"),
linkTextCreate = mw.getCurrentFrame():callParserFunction("int:create"),
-- p.create() 中使用的字符串:使用 {{doc}} 或 {{subst:doc}} 时显示的内容
createOutputFormat = "<noinclude>%s%s</noinclude>", -- 整体格式
createSplitDocPagePrompt = "\n<!-- 请将分类/语言链接放在文档页面 -->", -- 要创建的文档页面为独立页面时显示的字符串
createNoSubstCategory = "需要替换模板的页面", -- 使用 {{doc}} 时未使用替代语法所添加的追踪分类
-- p.docPage() 中使用的字符串:文档页显示的内容
-- For messages with format placeholders, store the template with placeholders
docPagePrompt_template_hans = "当前页面是文档页面,%s被%s引入。查看[[模板:Documentation]]获取更多信息。",
docPagePrompt_template_hant = "這是說明文件頁面,它%s被放置到%s。查看[[Template:Documentation]]以取得更多資訊。",
docPagePromptWill = stconv({
["zh-hans"] = "会",
["zh-hk"] = "將",
}),
docPagePromptShould = stconv({
["zh-hans"] = "会",
["zh-hk"] = "應該",
}),
docPageBadDocPrompt_template_hans = "<br>'''%s的文档页面质量较低或信息缺失,需要进一步修改。'''",
docPageBadDocPrompt_template_hant = "<br>'''此%s的說明文件頁面需要改進或加上附加資訊。'''",
docPageCategory = "文档页面", -- 文档页的追踪分类
-- p.page() 中使用的字符串:代码页显示的内容
pageNoDocPrompt_template_hans = "'''当前%s文档缺失,需要扩充。'''",
pageNoDocPrompt_template_hant = "'''此%s没有說明文件頁面。如果你知道此%s的使用方法,請幫助為其建立說明文件頁面。'''",
pageNoDocCategory_template_hans = "文档缺失的%s",
pageNoDocCategoryDefault = "文档缺失的页面",
pageBadDocPrompt_template_hans = "'''%s的文档页面质量较低或信息缺失,需要进一步修改。'''\n",
pageBadDocPrompt_template_hant = "'''此%s的說明文件頁面需要改進或加上附加資訊。'''\n",
pageBadDocCategory_template_hans = "文档质量较低的%s",
pageBadDocCategoryDefault = "文档质量较低的页面",
pageDocHeaderTitle = stconv({
["zh-hans"] = "文档页面",
["zh-hk"] = "說明文件頁面",
}),
pageDocJumpToCode = stconv({
["zh-hans"] = "跳转至代码 ↴",
["zh-hk"] = "跳轉至程式碼 ↴",
}),
pageDocHeaderBottom_template_hans = "上述文档的内容来自%s。",
pageDocHeaderBottom_template_hant = "上述說明文件嵌入至%s。",
-- 全局跨语言链接
globalInterwikiLinks = {
{ lang = "de", prefix = "Vorlage" },
{ lang = "en", prefix = "Template" },
{ lang = "es", prefix = "Plantilla" },
{ lang = "fr", prefix = "Modèle" },
{ lang = "it", prefix = "Template" },
{ lang = "ja", prefix = "テンプレート" },
{ lang = "ko", prefix = "틀" },
{ lang = "hu", prefix = "Sablon" },
{ lang = "pt", prefix = "Predefinição" },
{ lang = "ru", prefix = "Шаблон" },
{ lang = "tr", prefix = "Şablon" },
},
}
-- Helper function to format strings with language conversion
local function formatWithConv(hans_template, hant_template, ...)
local args = {...}
-- Count the number of %s in each template
local hans_count = select(2, string.gsub(hans_template, "%%s", ""))
local hant_count = select(2, string.gsub(hant_template, "%%s", ""))
-- Build arguments for each template based on their placeholder count
local hans_args = {}
local hant_args = {}
for i = 1, math.max(hans_count, hant_count) do
if i <= hans_count then
hans_args[i] = args[i] or ""
end
if i <= hant_count then
hant_args[i] = args[i] or ""
end
end
local hans_result = string.format(hans_template, unpack(hans_args))
local hant_result = string.format(hant_template, unpack(hant_args))
return stconv({
["zh-hans"] = hans_result,
["zh-hk"] = hant_result,
})
end
-- Customizable functions
local function pageCategoryHandler(category)
return i18n.commonInternalLink:format(i18n.commonNamespacedPage:format(i18n.namespaceCategory, category))
end
-- Load modules
local loadStyles = require("Module:TSLoader").call
local static = require("Module:Static")
if not static.Documentation then
static.Documentation = {}
end
-- Internal functions
local function getType(namespace, page)
local pageType = "page"
if namespace == "Template" then
pageType = "template"
elseif namespace == "Module" then
pageType = "module"
elseif page.fullText:gsub("/" .. i18n.defaultDocPage .. "$", ""):find("%.css$") then
pageType = "stylesheet"
elseif page.fullText:gsub("/" .. i18n.defaultDocPage .. "$", ""):find("%.js$") then
pageType = "script"
elseif page.fullText:gsub("/" .. i18n.defaultDocPage .. "$", ""):find("%.json$") then
pageType = "json"
elseif namespace == "MediaWiki" then
pageType = "message"
end
return pageType
end
local function getDisplayType(pageType)
return i18n["pageType_" .. pageType] or i18n.pageType_page
end
local function generateGlobalInterwikiLinks(f)
local pageName = f:preprocess("{{PAGENAME}}")
local links = {}
for _, item in ipairs(i18n.globalInterwikiLinks) do
table.insert(links, string.format("[[%s:%s:%s]]", item.lang, item.prefix, pageName))
end
return "\n" .. table.concat(links, "\n")
end
-- Exported functions
function p.create(f) -- Creating a documentation page or transclusion through {{subst:doc}}
local args = require("Module:ProcessArgs").norm()
local page = mw.title.getCurrentTitle()
local docPage = args.page
or i18n.commonNamespacedPageWithSub:format(page.nsText, page.baseText, i18n.defaultDocPage)
local out
if not args.content and tostring(page) == docPage then
local pageType = mw.ustring.lower(args.type or getType(page.nsText, page))
local pageTypeDisplay = getDisplayType(pageType)
out = f:preprocess(mw.title.new(i18n.defaultPreload):getContent():gsub("$1", pageTypeDisplay))
else
local templateArgs = {}
for _, key in ipairs({ "type", "page", "content", "nodoc", "baddoc", "global" }) do
local val = args[key]
if val then
if key == "content" then
val = "\n" .. val .. "\n"
end
table.insert(templateArgs, key .. "=" .. val)
end
end
out = "{{Documentation|" .. table.concat(templateArgs, "|") .. "}}"
out = out:gsub("|}}", "}}")
out = i18n.createOutputFormat:format(out, args.content and "" or i18n.createSplitDocPagePrompt)
end
if not mw.isSubsting() then
out = f:preprocess(out)
if not args.nocat then
out = out
.. i18n.commonInternalLink:format(
i18n.commonNamespacedPage:format(i18n.namespaceCategory, i18n.createNoSubstCategory)
)
end
end
return out
end
function p.docPage(f) -- Header on the documentation page
local args = require("Module:ProcessArgs").merge(true)
local badDoc = args.baddoc
if badDoc then
static.Documentation.badDoc = "1"
end
local page = mw.title.getCurrentTitle()
local subpage = page.subpageText
if subpage == i18n.defaultSandboxPage or subpage == i18n.defaultTestCasePage then
page = page.basePageTitle
end
local docPage = mw.title.new(
args.page or i18n.commonNamespacedPageWithSub:format(page.nsText, page.baseText, i18n.defaultDocPage)
)
if docPage ~= page then
return
end
local namespace = page.nsText
local pageType = mw.ustring.lower(args.type or getType(namespace, page))
local pageTypeDisplay = getDisplayType(pageType)
local body = mw.html.create("div"):addClass("documentation")
body:addClass(badDoc and "documentation-badDoc" or "")
:tag("div")
:addClass("documentation-header-tools")
:wikitext(
i18n.linkBar:format(
i18n.linkFormat:format(
i18n.commonInternalLinkPipe:format(
i18n.commonNamespacedPageWithSub:format(i18n.namespaceSpecial, i18n.specialPurge, page.fullText),
i18n.linkTextPurge
)
)
)
)
:done()
:wikitext(
formatWithConv(
i18n.docPagePrompt_template_hans,
i18n.docPagePrompt_template_hant,
pageType == "module" and i18n.docPagePromptWill or i18n.docPagePromptShould,
i18n.commonInternalLink:format(i18n.commonNamespacedPage:format(namespace, page.baseText))
)
)
if badDoc then
body:wikitext(formatWithConv(
i18n.docPageBadDocPrompt_template_hans,
i18n.docPageBadDocPrompt_template_hant,
pageTypeDisplay
))
end
if not (args.nocat or namespace == i18n.namespaceUser) then
body:wikitext(
i18n.commonInternalLink:format(
i18n.commonNamespacedPage:format(i18n.namespaceCategory, i18n.docPageCategory)
)
)
end
return loadStyles(i18n.defaultStyles) .. tostring(body)
end
function p.page(f) -- Wrapper around the documentation on the main page
-- mw.text.trim uses mw.ustring.gsub, which silently fails on large strings
local function trim(s)
return (s:gsub("^[\t\r\n\f ]+", ""):gsub("[\t\r\n\f ]+$", ""))
--return string.gsub( s, '^[\t\r\n\f ]*(.-)[\t\r\n\f ]*$', '%1' )
end
local args = require("Module:ProcessArgs").merge(true)
local page = mw.title.getCurrentTitle()
local subpage = page.subpageText
if subpage == i18n.defaultSandboxPage or subpage == i18n.defaultTestCasePage then
page = page.basePageTitle
end
local namespace = page.nsText
local docText = trim(args.content or "")
if docText == "" then
docText = nil
end
local docPage
local noDoc
if docText then
docPage = page
else
docPage = mw.title.new(
args.page or i18n.commonNamespacedPageWithSub:format(namespace, page.text, i18n.defaultDocPage)
)
noDoc = args.nodoc or not docPage.exists
end
local badDoc = args.baddoc
local pageType = mw.ustring.lower(args.type or getType(namespace, page))
local pageTypeDisplay = getDisplayType(pageType)
if not docText and not noDoc then
docText = trim(f:expandTemplate({ title = ":" .. docPage.fullText }))
if static.Documentation.badDoc and static.Documentation.badDoc == "1" then
badDoc = 1
end
if docText == "" then
docText = nil
noDoc = 1
end
end
if docText then
docText = "\n" .. docText .. "\n"
end
local docClass = ""
local message
local category
if noDoc then
docClass = "documentation-noDoc"
-- pageNoDocPrompt_template_hant has 2 %s, both need the same value
message = formatWithConv(
i18n.pageNoDocPrompt_template_hans,
i18n.pageNoDocPrompt_template_hant,
pageTypeDisplay,
pageTypeDisplay -- Second argument for zh-hant template
)
if not (args.nocat or namespace == i18n.namespaceUser) then
-- Use simplified Chinese category name directly
local categoryName = string.format(i18n.pageNoDocCategory_template_hans, pageTypeDisplay)
-- Check if the category exists
local categoryTitle = mw.title.new(i18n.commonNamespacedPage:format(i18n.namespaceCategory, categoryName))
if categoryTitle and categoryTitle.exists then
category = categoryName
else
category = i18n.pageNoDocCategoryDefault
end
end
elseif badDoc then
docClass = "documentation-badDoc"
message = formatWithConv(
i18n.pageBadDocPrompt_template_hans,
i18n.pageBadDocPrompt_template_hant,
pageTypeDisplay
)
if not (args.nocat or namespace == i18n.namespaceUser) then
-- Use simplified Chinese category name directly
local categoryName = string.format(i18n.pageBadDocCategory_template_hans, pageTypeDisplay)
-- Check if the category exists
local categoryTitle = mw.title.new(i18n.commonNamespacedPage:format(i18n.namespaceCategory, categoryName))
if categoryTitle and categoryTitle.exists then
category = categoryName
else
category = i18n.pageBadDocCategoryDefault
end
end
end
-- Generates the link bar
local links = mw.html.create("span"):attr("id", "documentation-header-tools")
local linkList = {}
if not noDoc then
if page ~= docPage then
table.insert(
linkList,
i18n.linkFormat:format(i18n.commonInternalLinkPipe:format(docPage.fullText, i18n.linkTextView))
)
end
table.insert(
linkList,
i18n.linkFormat:format(
i18n.commonInternalLinkPipe:format(
i18n.commonNamespacedPageWithSub:format(i18n.namespaceSpecial, i18n.specialEdit, docPage.fullText),
i18n.linkTextEdit
)
)
)
table.insert(
linkList,
i18n.linkFormat:format(
i18n.commonInternalLinkPipe:format(
i18n.commonNamespacedPageWithSub:format(
i18n.namespaceSpecial,
i18n.specialHistory,
docPage.fullText
),
i18n.linkTextHistory
)
)
)
else
table.insert(
linkList,
i18n.linkFormat:format(
i18n.commonExternalLinkWithName:format(
docPage:canonicalUrl({
action = "edit",
preload = i18n.defaultPreload,
preloadparams = pageTypeDisplay,
}),
i18n.linkTextCreate
)
)
)
end
table.insert(
linkList,
i18n.linkFormat:format(
i18n.commonInternalLinkPipe:format(
i18n.commonNamespacedPageWithSub:format(i18n.namespaceSpecial, i18n.specialPurge, docPage.fullText),
i18n.linkTextPurge
)
)
)
links:wikitext(i18n.linkBar:format(table.concat(linkList, i18n.linkSeparator)))
local body = mw.html.create("div"):addClass("documentation")
body:addClass(docClass)
local header = mw.html.create("div"):addClass("documentation-header-top")
header:node(links):tag("span"):addClass("documentation-header-title"):wikitext(i18n.pageDocHeaderTitle)
local codePages = {
module = true,
stylesheet = true,
script = true,
}
if not noDoc and codePages[pageType] then
header
:tag("span")
:attr("id", "documentation-jump-to-code")
:wikitext(i18n.commonInternalLinkPipe:format("#the-code", i18n.pageDocJumpToCode))
end
body:node(header):done():wikitext(message):wikitext(docText)
if not noDoc and page ~= docPage then
body:tag("div")
:addClass("documentation-header-bottom")
:node(links)
:wikitext(formatWithConv(
i18n.pageDocHeaderBottom_template_hans,
i18n.pageDocHeaderBottom_template_hant,
i18n.commonInternalLink:format(docPage.fullText)
))
end
if category then
body:wikitext(pageCategoryHandler(category))
end
local anchor = ""
if not noDoc and pageType ~= "template" and pageType ~= "message" then
anchor = mw.html.create("div"):attr("id", "the-code")
end
local output = loadStyles(i18n.defaultStyles) .. tostring(body) .. tostring(anchor)
-- Add global interwiki links if requested
if args.global then
output = output .. generateGlobalInterwikiLinks(f)
end
return output
end
return p