跳转到内容

Module:Documentation:修订间差异

勤求古训,博采众方
无编辑摘要
已更改“Module:Documentation”的保护设置​([编辑=仅允许管理员](无限期)​[移动=仅允许管理员](无限期))​[连锁保护]
 
(未显示同一用户的7个中间版本)
第1行: 第1行:
-- 这个模块实现 {{documentation}} 模板。
-- This module implements {{documentation}}.


-- 获取所需的模块。
-- Get required modules.
local getArgs = require('Module:Arguments').getArgs
local getArgs = require('Module:Arguments').getArgs
local messageBox = require('Module:Message box')


-- 获取配置表。
-- Get the config table.
local cfg = mw.loadData('Module:Documentation/config')
local cfg = mw.loadData('Module:Documentation/config')
local i18n = mw.loadData('Module:Documentation/i18n')
 
local p = {}
local p = {}


-- 常用函数。
-- Often-used functions.
local ugsub = mw.ustring.gsub
local ugsub = mw.ustring.gsub
local format = mw.ustring.format


----------------------------------------------------------------------------
----------------------------------------------------------------------------
-- 辅助函数
-- Helper functions
--
--
-- 这些函数定义为局部函数,但为了测试目的在 p 表中可用。
-- These are defined as local functions, but are made available in the p
-- table for testing purposes.
----------------------------------------------------------------------------
----------------------------------------------------------------------------


local function message(cfgKey, valArray, expectType)
local function message(cfgKey, valArray, expectType)
--[[
--[[
-- 从配置表中获取消息并在适当时格式化。
-- Gets a message from the cfg table and formats it if appropriate.
-- 如果配置表中的值不是 expectType 类型,函数会报错。expectType 的默认类型是 'string'
-- The function raises an error if the value from the cfg table is not
-- 如果存在 valArray 表,消息中的 $1、$2 等字符串会被替换为表中 [1][2] 等键的值。
-- of the type expectType. The default type for expectType is 'string'.
-- 例如,如果消息 "foo-message" 的值为 'Foo $2 bar $1.'
-- If the table valArray is present, strings such as $1, $2 etc. in the
-- message('foo-message', {'baz', 'qux'}) 将返回 "Foo qux bar baz."
-- message are substituted with values from the table keys [1], [2] etc.
-- For example, if the message "foo-message" had the value 'Foo $2 bar $1.',
-- message('foo-message', {'baz', 'qux'}) would return "Foo qux bar baz."
--]]
--]]
if not cfgKey then
error('配置错误:消息键名不能为nil', 2)
end
local msg = cfg[cfgKey]
local msg = cfg[cfgKey]
expectType = expectType or 'string'
expectType = expectType or 'string'
if type(msg) ~= expectType then
if type(msg) ~= expectType then
error(string.format('配置错误:键"%s"的值类型应为%s,但实际为%s', cfgKey, expectType, type(msg)), 2)
error('message: type error in message cfg.' .. cfgKey .. ' (' .. expectType .. ' expected, got ' .. type(msg) .. ')', 2)
end
end
if not valArray then
if not valArray then
第42行: 第41行:
local function getMessageVal(match)
local function getMessageVal(match)
match = tonumber(match)
match = tonumber(match)
if not valArray[match] then
return valArray[match] or error('message: no value found for key $' .. match .. ' in message cfg.' .. cfgKey, 4)
error(string.format('配置错误:消息"%s"中的参数$%s为空', cfgKey, match), 4)
end
return valArray[match]
end
end


local ret = ugsub(msg, '$([1-9][0-9]*)', getMessageVal)
msg = ugsub(msg, '$([1-9][0-9]*)', getMessageVal)
return ret
return msg
end
end


第55行: 第51行:


local function makeWikilink(page, display)
local function makeWikilink(page, display)
-- 创建维基链接
if display then
if display then
return mw.ustring.format('[[%s|%s]]', page, display)
return format('[[%s|%s]]', page, display)
else
else
return mw.ustring.format('[[%s]]', page)
return format('[[%s]]', page)
end
end
end
end
第66行: 第61行:


local function makeCategoryLink(cat, sort)
local function makeCategoryLink(cat, sort)
-- 创建分类链接
local catns = mw.site.namespaces[14].name
local catns = mw.site.namespaces[14].name
return makeWikilink(catns .. ':' .. cat, sort)
return makeWikilink(catns .. ':' .. cat, sort)
第74行: 第68行:


local function makeUrlLink(url, display)
local function makeUrlLink(url, display)
-- 创建URL链接
return format('[%s %s]', url, display)
return mw.ustring.format('[%s %s]', url, display)
end
end


第81行: 第74行:


local function makeToolbar(...)
local function makeToolbar(...)
-- 创建工具栏
local ret = {}
local ret = {}
local lim = select('#', ...)
local lim = select('#', ...)
第90行: 第82行:
ret[#ret + 1] = select(i, ...)
ret[#ret + 1] = select(i, ...)
end
end
return '<small style="font-style: normal;">(' .. table.concat(ret, ' &#124; ') .. ')</small>'
-- 'documentation-toolbar'
return format(
'<span class="%s">(%s)</span>',
message('toolbar-class'),
table.concat(ret, ' &#124; ')
)
end
end


第96行: 第93行:


----------------------------------------------------------------------------
----------------------------------------------------------------------------
-- 参数处理
-- Argument processing
----------------------------------------------------------------------------
----------------------------------------------------------------------------


local function makeInvokeFunc(funcName)
local function makeInvokeFunc(funcName)
-- 创建调用函数
return function (frame)
return function (frame)
local args = getArgs(frame, {
local args = getArgs(frame, {
valueFunc = function (key, value)
valueFunc = function (key, value)
if type(value) == 'string' then
if type(value) == 'string' then
value = value:match('^%s*(.-)%s*$') -- 移除空白字符
value = value:match('^%s*(.-)%s*$') -- Remove whitespace.
if key == 'heading' or value ~= '' then
if key == 'heading' or value ~= '' then
return value
return value
第121行: 第117行:


----------------------------------------------------------------------------
----------------------------------------------------------------------------
-- 加载模板样式
-- Entry points
----------------------------------------------------------------------------
----------------------------------------------------------------------------


p.main = function(frame)
function p.nonexistent(frame)
-- 主函数,处理模板调用
if mw.title.getCurrentTitle().subpageText == 'testcases' then
local parent = frame.getParent(frame)
return frame:expandTemplate{title = 'module test cases notice'}
local output = p._main(parent.args)
else
return frame:extensionTag{ name='templatestyles', args = { src= message('templatestyles-scr') } } .. output
return p.main(frame)
end
end
end


----------------------------------------------------------------------------
p.main = makeInvokeFunc('_main')
-- 主逻辑函数
----------------------------------------------------------------------------


function p._main(args)
function p._main(args)
--[[
--[[
-- 这个函数定义了模块的逻辑流程。
-- This function defines logic flow for the module.
-- @args - 用户传递的参数表
-- @args - table of arguments passed by the user
--
-- 消息:
-- 'main-div-id' --> 'template-documentation'
-- 'main-div-classes' --> 'template-documentation iezoomfix'
--]]
--]]
local env = p.getEnvironment(args)
local env = p.getEnvironment(args)
第148行: 第139行:
root
root
:wikitext(p._getModuleWikitext(args, env))
:wikitext(p._getModuleWikitext(args, env))
:wikitext(p.protectionTemplate(env))
-- :wikitext(p.protectionTemplate(env)) -- 已注释掉保护横幅功能,使用 MediaWiki 自带保护显示
:wikitext(p.sandboxNotice(args, env))
:wikitext(p.sandboxNotice(args, env))
-- 这个 div 标签来自 {{documentation/start box}},但移到这里
:tag('div')
-- 这样我们就不必担心未闭合的标签。
-- 'documentation-container'
:addClass(message('container'))
:attr('role', 'complementary')
:attr('aria-labelledby', args.heading ~= '' and 'documentation-heading' or nil)
:attr('aria-label', args.heading == '' and 'Documentation' or nil)
:newline()
:tag('div')
:tag('div')
:attr('id', message('main-div-id'))
-- 'documentation'
:addClass(message('main-div-class'))
:addClass(message('main-div-classes'))
:newline()
:wikitext(p._startBox(args, env))
:wikitext(p._startBox(args, env))
:wikitext(p._content(args, env))
:wikitext(p._content(args, env))
:tag('div')
-- 'documentation-clear'
:addClass(message('clear'))
:done()
:newline()
:done()
:done()
:wikitext(p._endBox(args, env))
:wikitext(p._endBox(args, env))
:wikitext(p.addTrackingCategories(env))
:done()
return tostring(root)
:wikitext(p.addTrackingCategories(env))
-- 'Module:Documentation/styles.css'
return mw.getCurrentFrame():extensionTag (
'templatestyles', '', {src=cfg['templatestyles']
}) .. tostring(root)
end
end


----------------------------------------------------------------------------
----------------------------------------------------------------------------
-- 环境设置
-- Environment settings
----------------------------------------------------------------------------
----------------------------------------------------------------------------


function p.getEnvironment(args)
function p.getEnvironment(args)
--[[
--[[
-- 返回包含环境信息的表,包括标题对象和其他命名空间或路径相关数据。
-- Returns a table with information about the environment, including title
-- @args - 用户传递的参数表
-- objects and other namespace- or path-related data.
-- @args - table of arguments passed by the user
--
--
-- 标题对象包括:
-- Title objects include:
-- env.title - 我们为其制作文档的页面(通常是当前标题)
-- env.title - the page we are making documentation for (usually the current title)
-- env.templateTitle - 模板(或模块、文件等)
-- env.templateTitle - the template (or module, file, etc.)
-- env.docTitle - /doc 子页面
-- env.docTitle - the /doc subpage.
-- env.sandboxTitle - /sandbox 子页面
-- env.sandboxTitle - the /sandbox subpage.
-- env.testcasesTitle - /testcases 子页面
-- env.testcasesTitle - the /testcases subpage.
-- env.printTitle - 模板的打印版本,位于 /Print 子页面
--
--
-- 数据包括:
-- Data includes:
-- env.protectionLevels - 标题对象的保护级别表
-- env.protectionLevels - the protection levels table of the title object.
-- env.subjectSpace - 标题主题命名空间的编号
-- env.subjectSpace - the number of the title's subject namespace.
-- env.docSpace - 标题放置其文档的命名空间编号
-- env.docSpace - the number of the namespace the title puts its documentation in.
-- env.docpageBase - /doc、/sandbox /testcases 页面的基础页面文本,包含命名空间
-- env.docpageBase - the text of the base page of the /doc, /sandbox and /testcases pages, with namespace.
-- env.compareUrl - 比较沙盒与模板的 Special:ComparePages 页面 URL
-- env.compareUrl - URL of the Special:ComparePages page comparing the sandbox with the template.
--  
--  
-- 所有表查找都通过 pcall 传递,以便捕获错误。如果发生错误,返回的值将为 nil。
-- All table lookups are passed through pcall so that errors are caught. If an error occurs, the value
-- returned will be nil.
--]]
--]]
local env, envFuncs = {}, {}
local env, envFuncs = {}, {}


-- 设置元表。如果触发,我们调用 envFuncs 表中的相应函数。
-- Set up the metatable. If triggered we call the corresponding function in the envFuncs table. The value
-- 该函数返回的值会被缓存在 env 表中,这样我们就不会多次调用任何函数。(nil 不会被缓存。)
-- returned by that function is memoized in the env table so that we don't call any of the functions
-- more than once. (Nils won't be memoized.)
setmetatable(env, {
setmetatable(env, {
__index = function (t, key)
__index = function (t, key)
第200行: 第208行:
local success, val = pcall(envFunc)
local success, val = pcall(envFunc)
if success then
if success then
env[key] = val -- 缓存值
env[key] = val -- Memoise the value.
return val
return val
end
end
第206行: 第214行:
return nil
return nil
end
end
})
})


-- 当前标题
function envFuncs.title()
envFuncs.title = function()
-- The title object for the current page, or a test page passed with args.page.
return mw.title.getCurrentTitle()
local title
local titleArg = args.page
if titleArg then
title = mw.title.new(titleArg)
else
title = mw.title.getCurrentTitle()
end
return title
end
end


-- 模板标题
function envFuncs.templateTitle()
envFuncs.templateTitle = function()
--[[
-- The template (or module, etc.) title object.
-- Messages:
-- 'sandbox-subpage' --> 'sandbox'
-- 'testcases-subpage' --> 'testcases'
--]]
local subjectSpace = env.subjectSpace
local title = env.title
local title = env.title
local argsTitle = args.title
local subpage = title.subpageText
if argsTitle then
if subpage == message('sandbox-subpage') or subpage == message('testcases-subpage') then
return mw.title.new(argsTitle)
return mw.title.makeTitle(subjectSpace, title.baseText)
else
return mw.title.makeTitle(subjectSpace, title.text)
end
end
return title
end
end


-- 文档标题
function envFuncs.docTitle()
envFuncs.docTitle = function()
--[[
local templateTitle = env.templateTitle
-- Title object of the /doc subpage.
local docSubpage = message('doc-subpage')
-- Messages:
return templateTitle:subPageTitle(docSubpage)
-- 'doc-subpage' --> 'doc'
--]]
local title = env.title
local docname = args[1] -- User-specified doc page.
local docpage
if docname then
docpage = docname
else
docpage = env.docpageBase .. '/' .. message('doc-subpage')
end
return mw.title.new(docpage)
end
end
 
-- 沙盒标题
function envFuncs.sandboxTitle()
envFuncs.sandboxTitle = function()
--[[
local templateTitle = env.templateTitle
-- Title object for the /sandbox subpage.
local sandboxSubpage = message('sandbox-subpage')
-- Messages:
return templateTitle:subPageTitle(sandboxSubpage)
-- 'sandbox-subpage' --> 'sandbox'
--]]
return mw.title.new(env.docpageBase .. '/' .. message('sandbox-subpage'))
end
end
 
-- 测试用例标题
function envFuncs.testcasesTitle()
envFuncs.testcasesTitle = function()
--[[
local templateTitle = env.templateTitle
-- Title object for the /testcases subpage.
local testcasesSubpage = message('testcases-subpage')
-- Messages:
return templateTitle:subPageTitle(testcasesSubpage)
-- 'testcases-subpage' --> 'testcases'
--]]
return mw.title.new(env.docpageBase .. '/' .. message('testcases-subpage'))
end
end


-- 打印标题
function envFuncs.protectionLevels()
envFuncs.printTitle = function()
-- The protection levels table of the title object.
local templateTitle = env.templateTitle
return env.title.protectionLevels
local printSubpage = message('print-subpage')
return templateTitle:subPageTitle(printSubpage)
end
end


-- 保护级别
function envFuncs.subjectSpace()
envFuncs.protectionLevels = function()
-- The subject namespace number.
local templateTitle = env.templateTitle
return mw.site.namespaces[env.title.namespace].subject.id
return templateTitle.protectionLevels
end
end


-- 主题命名空间
function envFuncs.docSpace()
envFuncs.subjectSpace = function()
-- The documentation namespace number. For most namespaces this is the
local templateTitle = env.templateTitle
-- same as the subject namespace. However, pages in the Article, File,
return templateTitle.namespace
-- MediaWiki or Category namespaces must have their /doc, /sandbox and
end
-- /testcases pages in talk space.
 
-- 文档命名空间
envFuncs.docSpace = function()
local subjectSpace = env.subjectSpace
local subjectSpace = env.subjectSpace
if subjectSpace == 0 then
if subjectSpace == 0 or subjectSpace == 6 or subjectSpace == 8 or subjectSpace == 14 then
return 10 -- 模板命名空间
return subjectSpace + 1
elseif subjectSpace == 828 then
return 828 -- 模块命名空间
else
else
return subjectSpace
return subjectSpace
第275行: 第303行:
end
end


-- 文档页面基础
function envFuncs.docpageBase()
envFuncs.docpageBase = function()
-- The base page of the /doc, /sandbox, and /testcases subpages.
-- For some namespaces this is the talk page, rather than the template page.
local templateTitle = env.templateTitle
local templateTitle = env.templateTitle
local docSpace = env.docSpace
local docSpace = env.docSpace
local docNsText = mw.site.namespaces[docSpace].name
local docSpaceText = mw.site.namespaces[docSpace].name
return docNsText .. ':' .. templateTitle.text
-- Assemble the link. docSpace is never the main namespace, so we can hardcode the colon.
return docSpaceText .. ':' .. templateTitle.text
end
end
 
-- 比较URL
function envFuncs.compareUrl()
envFuncs.compareUrl = function()
-- Diff link between the sandbox and the main template using [[Special:ComparePages]].
local templateTitle = env.templateTitle
local sandboxTitle = env.sandboxTitle
local sandboxTitle = env.sandboxTitle
local templateTitle = env.templateTitle
if templateTitle.exists and sandboxTitle.exists then
if sandboxTitle and templateTitle then
local compareUrl = mw.uri.canonicalUrl(
return mw.uri.fullUrl('Special:ComparePages', {
'Special:ComparePages',
page1 = templateTitle.fullText,
{ page1 = templateTitle.prefixedText, page2 = sandboxTitle.prefixedText}
page2 = sandboxTitle.fullText
)
})
return tostring(compareUrl)
else
return nil
end
end
return nil
end
end


return env
return env
end
end
 
----------------------------------------------------------------------------
-- Auxiliary templates
----------------------------------------------------------------------------


p.getModuleWikitext = makeInvokeFunc('_getModuleWikitext')
p.getModuleWikitext = makeInvokeFunc('_getModuleWikitext')


function p._getModuleWikitext(args, env)
function p._getModuleWikitext(args, env)
-- 获取模块wikitext
local currentTitle = mw.title.getCurrentTitle()
local currentTitle = mw.title.getCurrentTitle()
if currentTitle.contentModel ~= 'Scribunto' then return end
if currentTitle.contentModel ~= 'Scribunto' then return end
pcall(require, currentTitle.prefixedText) -- 如果失败,我们不关心
pcall(require, currentTitle.prefixedText) -- if it fails, we don't care
local moduleWikitext =  package.loaded["Module:Module wikitext"]
local moduleWikitext =  package.loaded["Module:Module wikitext"]
if moduleWikitext then
if moduleWikitext then
第314行: 第349行:
function p.sandboxNotice(args, env)
function p.sandboxNotice(args, env)
--[=[
--[=[
-- 为沙盒页面生成沙盒通知。
-- Generates a sandbox notice for display above sandbox pages.
-- @args - 用户传递的参数表
-- @args - a table of arguments passed by the user
-- @env - 包含标题对象等的环境表,由 p.getEnvironment 生成
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--  
--  
-- 消息:
-- Messages:
-- 'sandbox-notice-image' --> '[[Image:Sandbox.svg|50px|alt=|link=]]'
-- 'sandbox-notice-image' --> '[[File:Sandbox.svg|50px|alt=|link=]]'
-- 'sandbox-notice-blurb' --> '这是 $2 的 $1。'
-- 'sandbox-notice-blurb' --> 'This is the $1 for $2.'
-- 'sandbox-notice-diff-blurb' --> '这是 $2 的 $1 ($3)'
-- 'sandbox-notice-diff-blurb' --> 'This is the $1 for $2 ($3).'
-- 'sandbox-notice-pagetype-template' --> '[[w:Wikipedia:Template test cases|模板沙盒]]页面'
-- 'sandbox-notice-pagetype-template' --> '[[Wikipedia:Template test cases|template sandbox]] page'
-- 'sandbox-notice-pagetype-module' --> '[[w:Wikipedia:Template test cases|模块沙盒]]页面'
-- 'sandbox-notice-pagetype-module' --> '[[Wikipedia:Template test cases|module sandbox]] page'
-- 'sandbox-notice-pagetype-other' --> '沙盒页面'
-- 'sandbox-notice-pagetype-other' --> 'sandbox page'
-- 'sandbox-notice-compare-link-display' --> '差异'
-- 'sandbox-notice-compare-link-display' --> 'diff'
-- 'sandbox-notice-testcases-blurb' --> '另请参阅 $1 的配套子页面。'
-- 'sandbox-notice-testcases-blurb' --> 'See also the companion subpage for $1.'
-- 'sandbox-notice-testcases-link-display' --> '测试用例'
-- 'sandbox-notice-testcases-link-display' --> 'test cases'
-- 'sandbox-category' --> '模板沙盒'
-- 'sandbox-category' --> 'Template sandboxes'
-- 'module-sandbox-category' --> 'Module sandboxes'
-- 'other-sandbox-category' --> 'Sandboxes outside of template or module namespace'
--]=]
--]=]
local title = env.title
local title = env.title
第334行: 第371行:
local templateTitle = env.templateTitle
local templateTitle = env.templateTitle
local subjectSpace = env.subjectSpace
local subjectSpace = env.subjectSpace
if not (subjectSpace and title and sandboxTitle and templateTitle and mw.title.equals(title, sandboxTitle)) then
if not (subjectSpace and title and sandboxTitle and templateTitle
and mw.title.equals(title, sandboxTitle)) then
return nil
return nil
end
end
-- 构建传递给 {{ombox}} 的参数表。我们只需要两个字段:"image" "text"
-- Build the table of arguments to pass to {{ombox}}. We need just two fields, "image" and "text".
local omargs = {}
local omargs = {}
omargs.image = message('sandbox-notice-image')
omargs.image = message('sandbox-notice-image')
-- 获取文本。我们从开头的说明开始,类似于
-- Get the text. We start with the opening blurb, which is something like
-- "这是 [[Template:Foo]] 的模板沙盒 (差异)"
-- "This is the template sandbox for [[Template:Foo]] (diff)."
local text = ''
local text = '__EXPECTUNUSEDTEMPLATE__'
local frame = mw.getCurrentFrame()
local pagetype, sandboxCat
local isPreviewing = frame:preprocess('{{REVISIONID}}') == '' -- 如果页面正在预览则为真
local pagetype
if subjectSpace == 10 then
if subjectSpace == 10 then
pagetype = message('sandbox-notice-pagetype-template')
pagetype = message('sandbox-notice-pagetype-template')
sandboxCat = message('sandbox-category')
elseif subjectSpace == 828 then
elseif subjectSpace == 828 then
pagetype = message('sandbox-notice-pagetype-module')
pagetype = message('sandbox-notice-pagetype-module')
sandboxCat = message('module-sandbox-category')
else
else
pagetype = message('sandbox-notice-pagetype-other')
pagetype = message('sandbox-notice-pagetype-other')
sandboxCat = message('other-sandbox-category')
end
local pagetypee
if subjectSpace == 10 then
pagetypee = message('template-pagetype')
elseif subjectSpace == 828 then
pagetypee = message('module-pagetype')
else
pagetypee = message('default-pagetype') --message 'other-pagetype' 不存在
end
end
local templateLink = makeWikilink(templateTitle.prefixedText)
local templateLink = makeWikilink(templateTitle.prefixedText)
local compareUrl = env.compareUrl
local compareUrl = env.compareUrl
if isPreviewing or not compareUrl then
if compareUrl then
text = text .. message('sandbox-notice-blurb', {pagetype, templateLink})
else
local compareDisplay = message('sandbox-notice-compare-link-display')
local compareDisplay = message('sandbox-notice-compare-link-display')
local compareLink = makeUrlLink(compareUrl, compareDisplay)
local compareLink = makeUrlLink(compareUrl, compareDisplay)
text = text .. message('sandbox-notice-diff-blurb', {pagetype, templateLink, compareLink})
text = text .. message('sandbox-notice-diff-blurb', {pagetype, templateLink, compareLink})
else
text = text .. message('sandbox-notice-blurb', {pagetype, templateLink})
end
end
-- 如果页面存在,获取测试用例页面说明。类似于
-- Get the test cases page blurb if the page exists. This is something like
-- "另请参阅 [[Template:Foo/testcases|测试用例]] 的配套子页面。"
-- "See also the companion subpage for [[Template:Foo/testcases|test cases]]."
local testcasesTitle = env.testcasesTitle
local testcasesTitle = env.testcasesTitle
if testcasesTitle and testcasesTitle.exists then
if testcasesTitle and testcasesTitle.exists then
第371行: 第418行:
local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
text = text .. '<br />' .. message('sandbox-notice-testcases-run-blurb', {testcasesLink, testcasesRunLink})
text = text .. '<br /><small>' .. message('sandbox-notice-testcases-run-blurb', {pagetypee, testcasesLink, testcasesRunLink}) .. '</small>'
else
else
local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
text = text .. '<br />' .. message('sandbox-notice-testcases-blurb', {testcasesLink})
text = text .. '<br /><small>' .. message('sandbox-notice-testcases-blurb', {pagetypee, testcasesLink}) .. '</small>'
end
end
end
end
-- 将沙盒添加到沙盒分类中。
text = text .. makeCategoryLink(message('sandbox-category'))
-- Add the sandbox to the sandbox category.
omargs.text = text
omargs.text = text .. makeCategoryLink(sandboxCat)
omargs.class = message('sandbox-class')
 
local ret = '<div style="clear: both;"></div>'
-- 'documentation-clear'
ret = ret .. messageBox.main('ombox', omargs)
return '<div class="' .. message('clear') .. '"></div>'
return ret
.. require('Module:Message box').main('ombox', omargs)
end
end


-- 注释掉保护横幅功能,使用 MediaWiki 自带的保护显示
-- 新版 MediaWiki 已自带页面保护显示功能,无需模板模块依赖
--[[
function p.protectionTemplate(env)
function p.protectionTemplate(env)
-- 生成右上角的挂锁图标。
-- Generates the padlock icon in the top right.
-- @env - 包含标题对象等的环境表,由 p.getEnvironment 生成
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- 消息:
-- Messages:
-- 'protection-template' --> 'pp-template'
-- 'protection-template' --> 'pp-template'
-- 'protection-template-args' --> {docusage = 'yes'}
-- 'protection-template-args' --> {docusage = 'yes'}
local title = env.title
local protectionLevels = env.protectionLevels
local protectionLevels
local protectionTemplate = message('protection-template')
local namespace = title.namespace
if not (protectionTemplate and (namespace == 10 or namespace == 828)) then
-- 如果不在模板或模块命名空间中,不显示保护模板。
return nil
end
protectionLevels = env.protectionLevels
if not protectionLevels then
if not protectionLevels then
return nil
return nil
end
end
local editLevels = protectionLevels.edit
local editProt = protectionLevels.edit and protectionLevels.edit[1]
local moveLevels = protectionLevels.move
local moveProt = protectionLevels.move and protectionLevels.move[1]
 
if editProt then
if moveLevels and moveLevels[1] == 'sysop' or editLevels and editLevels[1] then
-- The page is edit-protected.
-- 页面被完全移动保护,或完全、模板或半保护。
return require('Module:Protection banner')._main{
local frame = mw.getCurrentFrame()
message('protection-reason-edit'), small = true
return frame:expandTemplate{title = protectionTemplate, args = message('protection-template-args', nil, 'table')}
}
elseif moveProt and moveProt ~= 'autoconfirmed' then
-- The page is move-protected but not edit-protected. Exclude move
-- protection with the level "autoconfirmed", as this is equivalent to
-- no move protection at all.
return require('Module:Protection banner')._main{
action = 'move', small = true
}
else
else
return nil
return nil
end
end
end
end
--]]


----------------------------------------------------------------------------
----------------------------------------------------------------------------
-- 起始框
-- Start box
----------------------------------------------------------------------------
----------------------------------------------------------------------------


第425行: 第475行:
function p._startBox(args, env)
function p._startBox(args, env)
--[[
--[[
-- 这个函数生成起始框。
-- This function generates the start box.
-- @args - 用户传递的参数表
-- @args - a table of arguments passed by the user
-- @env - 包含标题对象等的环境表,由 p.getEnvironment 生成
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--  
--  
-- 实际工作由 p.makeStartBoxLinksData p.renderStartBoxLinks 完成,它们创建
-- The actual work is done by p.makeStartBoxLinksData and p.renderStartBoxLinks which make
-- [查看] [编辑] [历史] [清除] 链接,以及由 p.makeStartBoxData p.renderStartBox
-- the [view] [edit] [history] [purge] links, and by p.makeStartBoxData and p.renderStartBox
-- 生成框的 HTML。
-- which generate the box HTML.
--]]
--]]
env = env or p.getEnvironment(args)
env = env or p.getEnvironment(args)
local links
local links
local content = args.content
local content = args.content
if not content then
if not content or args[1] then
-- 如果文档在模板页面本身,则不需要包含链接。
-- No need to include the links if the documentation is on the template page itself.
local linksData = p.makeStartBoxLinksData(args, env)
local linksData = p.makeStartBoxLinksData(args, env)
if linksData then
if linksData then
第443行: 第493行:
end
end
end
end
-- 生成起始框的 HTML。
-- Generate the start box html.
local data = p.makeStartBoxData(args, env, links)
local data = p.makeStartBoxData(args, env, links)
if data then
if data then
return p.renderStartBox(data)
return p.renderStartBox(data)
else
else
-- 用户指定了无标题。
-- User specified no heading.
return nil
return nil
end
end
第455行: 第505行:
function p.makeStartBoxLinksData(args, env)
function p.makeStartBoxLinksData(args, env)
--[[
--[[
-- 对数据进行初步处理以创建 [查看] [编辑] [历史] [清除] 链接。
-- Does initial processing of data to make the [view] [edit] [history] [purge] links.
-- @args - 用户传递的参数表
-- @args - a table of arguments passed by the user
-- @env - 包含标题对象等的环境表,由 p.getEnvironment 生成
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--  
--  
-- 消息:
-- Messages:
-- 'view-link-display' --> '查看'
-- 'view-link-display' --> 'view'
-- 'edit-link-display' --> '编辑'
-- 'edit-link-display' --> 'edit'
-- 'history-link-display' --> '历史'
-- 'history-link-display' --> 'history'
-- 'purge-link-display' --> '清除'
-- 'purge-link-display' --> 'purge'
-- 'file-docpage-preload' --> 'Template:Documentation/preload-filespace'
-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
-- 'docpage-preload' --> 'Template:Documentation/preload'
-- 'docpage-preload' --> 'Template:Documentation/preload'
-- 'create-link-display' --> '创建'
-- 'create-link-display' --> 'create'
--]]
--]]
local subjectSpace = env.subjectSpace
local subjectSpace = env.subjectSpace
第479行: 第528行:
end
end


local data = {}
-- Create link if /doc doesn't exist.
data.title = title
data.docTitle = docTitle
-- 如果 /doc 存在,查看、显示、编辑和清除链接。
data.viewLinkDisplay = i18n['view-link-display']
data.editLinkDisplay = i18n['edit-link-display']
data.historyLinkDisplay = i18n['history-link-display']
data.purgeLinkDisplay = i18n['purge-link-display']
-- 如果 /doc 不存在,创建链接。
local preload = args.preload
local preload = args.preload
if not preload then
if not preload then
if subjectSpace == 6 then -- 文件命名空间
if subjectSpace == 828 then -- Module namespace
preload = message('file-docpage-preload')
elseif subjectSpace == 828 then -- 模块命名空间
preload = message('module-preload')
preload = message('module-preload')
else
else
第498行: 第537行:
end
end
end
end
data.preload = preload
data.createLinkDisplay = i18n['create-link-display']
return {
return data
title = title,
docTitle = docTitle,
-- View, display, edit, and purge links if /doc exists.
viewLinkDisplay = message('view-link-display'),
editLinkDisplay = message('edit-link-display'),
historyLinkDisplay = message('history-link-display'),
purgeLinkDisplay = message('purge-link-display'),
preload = preload,
createLinkDisplay = message('create-link-display')
}
end
end


function p.renderStartBoxLinks(data)
function p.renderStartBoxLinks(data)
--[[
--[[
-- 从数据表生成 [查看][编辑][历史][清除] [创建] 链接。
-- Generates the [view][edit][history][purge] or [create][purge] links from the data table.
-- @data - p.makeStartBoxLinksData 生成的数据表
-- @data - a table of data generated by p.makeStartBoxLinksData
--]]
--]]
local docTitle = data.docTitle
-- yes, we do intend to purge the template page on which the documentation appears
local purgeLink = makeWikilink("Special:Purge/" .. data.title.prefixedText, data.purgeLinkDisplay)
local function escapeBrackets(s)
-- 用 HTML 实体转义方括号。
s = s:gsub('%[', '&#91;') -- 用 HTML 实体替换方括号。
s = s:gsub('%]', '&#93;')
return s
end
local ret
local docTitle = data.docTitle
local title = data.title
if docTitle.exists then
if docTitle.exists then
local viewLink = makeWikilink(docTitle.prefixedText, data.viewLinkDisplay)
local viewLink = makeWikilink(docTitle.prefixedText, data.viewLinkDisplay)
local editLink = makeUrlLink(docTitle:fullUrl{action = 'edit'}, data.editLinkDisplay)
local editLink = makeWikilink("Special:EditPage/" .. docTitle.prefixedText, data.editLinkDisplay)
local historyLink = makeUrlLink(docTitle:fullUrl{action = 'history'}, data.historyLinkDisplay)
local historyLink = makeWikilink("Special:PageHistory/" .. docTitle.prefixedText, data.historyLinkDisplay)
local purgeLink = makeUrlLink(title:fullUrl{action = 'purge'}, data.purgeLinkDisplay)
return "&#91;" .. viewLink .. "&#93; &#91;" .. editLink .. "&#93; &#91;" .. historyLink .. "&#93; &#91;" .. purgeLink .. "&#93;"
ret = '[%s] [%s] [%s] [%s]'
ret = escapeBrackets(ret)
ret = mw.ustring.format(ret, viewLink, editLink, historyLink, purgeLink)
else
else
local createLink = makeUrlLink(docTitle:fullUrl{action = 'edit', preload = data.preload}, data.createLinkDisplay)
local createLink = makeUrlLink(docTitle:canonicalUrl{action = 'edit', preload = data.preload}, data.createLinkDisplay)
ret = '[%s]'
return  "&#91;" .. createLink .. "&#93; &#91;" .. purgeLink .. "&#93;"
ret = escapeBrackets(ret)
ret = mw.ustring.format(ret, createLink)
end
end
return ret
return ret
第538行: 第574行:
function p.makeStartBoxData(args, env, links)
function p.makeStartBoxData(args, env, links)
--[=[
--[=[
-- 对数据进行初步处理以传递给起始框渲染函数 p.renderStartBox。
-- Does initial processing of data to pass to the start-box render function, p.renderStartBox.
-- @args - 用户传递的参数表
-- @args - a table of arguments passed by the user
-- @env - 包含标题对象等的环境表,由 p.getEnvironment 生成
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- @links - 包含 [查看][编辑][历史][清除] 链接的字符串 - 如果有错误可能为 nil。
-- @links - a string containing the [view][edit][history][purge] links - could be nil if there's an error.
--
--
-- 消息:
-- Messages:
-- 'documentation-icon-wikitext' --> '[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=Documentation icon]]'
-- 'documentation-icon-wikitext' --> '[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=]]'
-- 'template-namespace-heading' --> '模板文档'
-- 'template-namespace-heading' --> 'Template documentation'
-- 'module-namespace-heading' --> '模块文档'
-- 'module-namespace-heading' --> 'Module documentation'
-- 'file-namespace-heading' --> '摘要'
-- 'file-namespace-heading' --> 'Summary'
-- 'other-namespaces-heading' --> '文档'
-- 'other-namespaces-heading' --> 'Documentation'
-- 'start-box-linkclasses' --> 'mw-editsection-like plainlinks'
-- 'testcases-create-link-display' --> 'create'
-- 'start-box-link-id' --> 'doc_editlinks'
-- 'testcases-create-link-display' --> '创建'
--]=]
--]=]
local subjectSpace = env.subjectSpace
local subjectSpace = env.subjectSpace
if not subjectSpace then
if not subjectSpace then
-- 默认为"其他命名空间",以便在发生错误时至少有一些输出。
-- Default to an "other namespaces" namespace, so that we get at least some output
-- if an error occurs.
subjectSpace = 2
subjectSpace = 2
end
end
local data = {}
local data = {}
-- 标题
-- Heading
local heading = args.heading -- 空值不会被移除。
local heading = args.heading -- Blank values are not removed.
if heading == '' then
if heading == '' then
-- 如果 heading 参数已定义但为空,则不显示起始框。
-- Don't display the start box if the heading arg is defined but blank.
return nil
return nil
end
end
if heading then
if heading then
data.heading = heading
data.heading = heading
elseif subjectSpace == 10 then -- 模板命名空间
elseif subjectSpace == 10 then -- Template namespace
data.heading = i18n['template-namespace-heading']
data.heading = message('documentation-icon-wikitext') .. ' ' .. message('template-namespace-heading')
elseif subjectSpace == 828 then -- 模块命名空间
elseif subjectSpace == 828 then -- Module namespace
data.heading = i18n['module-namespace-heading']
data.heading = message('documentation-icon-wikitext') .. ' ' .. message('module-namespace-heading')
elseif subjectSpace == 6 then -- 文件命名空间
elseif subjectSpace == 6 then -- File namespace
data.heading = i18n['file-namespace-heading']
data.heading = message('file-namespace-heading')
else
data.heading = message('other-namespaces-heading')
end
-- Heading CSS
local headingStyle = args['heading-style']
if headingStyle then
data.headingStyleText = headingStyle
else
else
data.heading = i18n['other-namespaces-heading']
-- 'documentation-heading'
data.headingClass = message('main-div-heading-class')
end
end
-- [查看][编辑][历史][清除] [创建] 链接的数据。
-- Data for the [view][edit][history][purge] or [create] links.
if links then
if links then
data.linksClass = message('start-box-linkclasses')
-- 'mw-editsection-like plainlinks'
data.linksId = message('start-box-link-id')
data.linksClass = message('start-box-link-classes')
data.links = links
data.links = links
end
end
第589行: 第633行:


function p.renderStartBox(data)
function p.renderStartBox(data)
-- 渲染起始框的 HTML。
-- Renders the start box html.
-- @data - p.makeStartBoxData 生成的数据表。
-- @data - a table of data generated by p.makeStartBoxData.
local sbox = mw.html.create('div')
local sbox = mw.html.create('div')
sbox
sbox
:addClass(message('header-div-class'))
-- 'documentation-startbox'
:tag('div')
:addClass(message('start-box-class'))
:addClass(message('heading-div-class'))
:newline()
:tag('span')
:addClass(data.headingClass)
:attr('id', 'documentation-heading')
:cssText(data.headingStyleText)
:wikitext(data.heading)
:wikitext(data.heading)
local links = data.links
local links = data.links
if links then
if links then
sbox
sbox:tag('span')
:tag('div')
:addClass(data.linksClass)
:addClass(data.linksClass)
:attr('id', data.linksId)
:attr('id', data.linksId)
:wikitext(links)
:wikitext(links)
end
end
return tostring(sbox)
return tostring(sbox)
end
end


----------------------------------------------------------------------------
----------------------------------------------------------------------------
-- 文档内容
-- Documentation content
----------------------------------------------------------------------------
----------------------------------------------------------------------------


第616行: 第662行:


function p._content(args, env)
function p._content(args, env)
-- 显示文档内容
-- Displays the documentation contents
-- @args - 用户传递的参数表
-- @args - a table of arguments passed by the user
-- @env - 包含标题对象等的环境表,由 p.getEnvironment 生成
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
env = env or p.getEnvironment(args)
env = env or p.getEnvironment(args)
local docTitle = env.docTitle
local docTitle = env.docTitle
local content = args.content
local content = args.content
if not content and docTitle and docTitle.exists then
if not content and docTitle and docTitle.exists then
content = args._content or mw.getCurrentFrame():expandTemplate{title = docTitle}
content = args._content or mw.getCurrentFrame():expandTemplate{title = docTitle.prefixedText}
end
end
-- 下面的换行符是必要的,以便文档开头和结尾的 "=== 标题 ===" 被正确解释。
-- The line breaks below are necessary so that "=== Headings ===" at the start and end
local cbox = mw.html.create('div')
-- of docs are interpreted correctly.
cbox
return '\n' .. (content or '') .. '\n'  
:addClass(message('content-div-class'))
:wikitext('\n' .. (content or '') .. '\n')
return tostring(cbox)
end
end


第646行: 第689行:


----------------------------------------------------------------------------
----------------------------------------------------------------------------
-- 结束框
-- End box
----------------------------------------------------------------------------
----------------------------------------------------------------------------


第653行: 第696行:
function p._endBox(args, env)
function p._endBox(args, env)
--[=[
--[=[
-- 这个函数生成结束框(也称为链接框)。
-- This function generates the end box (also known as the link box).
-- @args - 用户传递的参数表
-- @args - a table of arguments passed by the user
-- @env - 包含标题对象等的环境表,由 p.getEnvironment 生成
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
--]=]
--]=]
-- 获取环境数据。
-- Get environment data.
env = env or p.getEnvironment(args)
env = env or p.getEnvironment(args)
local subjectSpace = env.subjectSpace
local subjectSpace = env.subjectSpace
第666行: 第710行:
end
end
-- 检查是否应该输出结束框。如果文档存在或者我们在用户、模块或模板命名空间中,默认添加结束框。
-- Check whether we should output the end box at all. Add the end
-- box by default if the documentation exists or if we are in the
-- user, module or template namespaces.
local linkBox = args['link box']
local linkBox = args['link box']
if linkBox == 'off'
if linkBox == 'off'
第679行: 第725行:
end
end


-- 组装页脚文本字段。
-- Assemble the link box.
local text = ''
local text = ''
if linkBox then
if linkBox then
text = text .. linkBox
text = text .. linkBox
else
else
text = text .. (p.makeDocPageBlurb(args, env) or '') -- "此文档是从 [[Foo]] 嵌入的。"  
text = text .. (p.makeDocPageBlurb(args, env) or '') -- "This documentation is transcluded from [[Foo]]."  
if subjectSpace == 2 or subjectSpace == 10 or subjectSpace == 828 then
if subjectSpace == 2 or subjectSpace == 10 or subjectSpace == 828 then
-- 我们在用户、模板或模块命名空间中。
-- We are in the user, template or module namespaces.
-- 添加沙盒和测试用例链接。
-- Add sandbox and testcases links.
-- "编辑者可以在此模板的沙盒和测试用例页面中进行实验。"
-- "Editors can experiment in this template's sandbox and testcases pages."
text = text .. (p.makeExperimentBlurb(args, env) or '')
text = text .. (p.makeExperimentBlurb(args, env) or '') .. '<br />'
text = text .. '<br />'
if not args.content and not args[1] then
if not args.content and not args[1] then
-- "请将分类添加到 /doc 子页面。"
-- "Please add categories to the /doc subpage."
-- 对于内联文档或明确指定的文档页面,不显示此消息,
-- Don't show this message with inline docs or with an explicitly specified doc page,
-- 因为不清楚在哪里添加分类。
-- as then it is unclear where to add the categories.
text = text .. (p.makeCategoriesBlurb(args, env) or '')
text = text .. (p.makeCategoriesBlurb(args, env) or '')
end
end
text = text .. ' ' .. (p.makeSubpagesBlurb(args, env) or '') --"此模板的子页面"
text = text .. ' ' .. (p.makeSubpagesBlurb(args, env) or '') --"Subpages of this template"
local printBlurb = p.makePrintBlurb(args, env) -- 关于模板打印版本的两行说明。
if printBlurb then
text = text .. '<br />' .. printBlurb
end
end
end
end
end
local box = mw.html.create('div')
-- 'documentation-metadata'
box:attr('role', 'note')
:addClass(message('end-box-class'))
-- 'plainlinks'
:addClass(message('end-box-plainlinks'))
:wikitext(text)
:done()


local ebox = mw.html.create('div')
return '\n' .. tostring(box)
ebox
:addClass(message('footer-div-class'))
:wikitext(text)
return tostring(ebox)
end
end


function p.makeDocPageBlurb(args, env)
function p.makeDocPageBlurb(args, env)
--[=[
--[=[
-- 生成说明 "此文档是从 [[Template:Foo]] (编辑, 历史) 嵌入的。"
-- Makes the blurb "This documentation is transcluded from [[Template:Foo]] (edit, history)".
-- @args - 用户传递的参数表
-- @args - a table of arguments passed by the user
-- @env - 包含标题对象等的环境表,由 p.getEnvironment 生成
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--  
--  
-- 消息:
-- Messages:
-- 'edit-link-display' --> '编辑'
-- 'edit-link-display' --> 'edit'
-- 'history-link-display' --> '历史'
-- 'history-link-display' --> 'history'
-- 'transcluded-from-blurb' -->  
-- 'transcluded-from-blurb' -->  
-- '上面的 [[w:Wikipedia:Template documentation|文档]]  
-- 'The above [[Wikipedia:Template documentation|documentation]]  
-- 是从 $1 [[w:Wikipedia:Transclusion|嵌入]] 的。'
-- is [[Help:Transclusion|transcluded]] from $1.'
-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
-- 'create-link-display' --> '创建'
-- 'create-link-display' --> 'create'
-- 'create-module-doc-blurb' -->
-- 'create-module-doc-blurb' -->
-- '您可能想要为此 [[w:Wikipedia:Lua|Scribunto 模块]] $1 一个文档页面。'
-- 'You might want to $1 a documentation page for this [[Wikipedia:Lua|Scribunto module]].'
--]=]
--]=]
local docTitle = env.docTitle
local docTitle = env.docTitle
if not docTitle or args.content then
if not docTitle then
return nil
return nil
end
end
local ret
if docTitle.exists then
if docTitle.exists then
-- /doc 存在;链接到它。
-- /doc exists; link to it.
local docLink = makeWikilink(docTitle.prefixedText)
local docLink = makeWikilink(docTitle.prefixedText)
local editUrl = docTitle:fullUrl{action = 'edit'}
local editDisplay = message('edit-link-display')
local editDisplay = i18n['edit-link-display']
local editLink = makeWikilink("Special:EditPage/" .. docTitle.prefixedText, editDisplay)
local editLink = makeUrlLink(editUrl, editDisplay)
local historyDisplay = message('history-link-display')
local historyUrl = docTitle:fullUrl{action = 'history'}
local historyLink = makeWikilink("Special:PageHistory/" .. docTitle.prefixedText, historyDisplay)
local historyDisplay = i18n['history-link-display']
return message('transcluded-from-blurb', {docLink})
local historyLink = makeUrlLink(historyUrl, historyDisplay)
ret = message('transcluded-from-blurb', {docLink})
.. ' '
.. ' '
.. makeToolbar(editLink, historyLink)
.. makeToolbar(editLink, historyLink)
.. '<br />'
.. '<br />'
elseif env.subjectSpace == 828 then
elseif env.subjectSpace == 828 then
-- /doc 不存在;请求创建它。
-- /doc does not exist; ask to create it.
local createUrl = docTitle:fullUrl{action = 'edit', preload = message('module-preload')}
local createUrl = docTitle:canonicalUrl{action = 'edit', preload = message('module-preload')}
local createDisplay = i18n['create-link-display']
local createDisplay = message('create-link-display')
local createLink = makeUrlLink(createUrl, createDisplay)
local createLink = makeUrlLink(createUrl, createDisplay)
ret = message('create-module-doc-blurb', {createLink})
return message('create-module-doc-blurb', {createLink})
.. '<br />'
.. '<br />'
end
end
return ret
end
end


function p.makeExperimentBlurb(args, env)
function p.makeExperimentBlurb(args, env)
--[[
--[[
-- 渲染文本 "编辑者可以在此模板的沙盒 (编辑 | 差异) 和测试用例 (编辑) 页面中进行实验。"
-- Renders the text "Editors can experiment in this template's sandbox (edit | diff) and testcases (edit) pages."
-- @args - 用户传递的参数表
-- @args - a table of arguments passed by the user
-- @env - 包含标题对象等的环境表,由 p.getEnvironment 生成
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--  
--  
-- 消息:
-- Messages:
-- 'sandbox-link-display' --> '沙盒'
-- 'sandbox-link-display' --> 'sandbox'
-- 'sandbox-edit-link-display' --> '编辑'
-- 'sandbox-edit-link-display' --> 'edit'
-- 'compare-link-display' --> '差异'
-- 'compare-link-display' --> 'diff'
-- 'module-sandbox-preload' --> 'Template:Documentation/preload-module-sandbox'
-- 'module-sandbox-preload' --> 'Template:Documentation/preload-module-sandbox'
-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
-- 'sandbox-create-link-display' --> '创建'
-- 'sandbox-create-link-display' --> 'create'
-- 'mirror-edit-summary' --> '创建 $1 的沙盒版本'
-- 'mirror-edit-summary' --> 'Create sandbox version of $1'
-- 'mirror-link-display' --> '镜像'
-- 'mirror-link-display' --> 'mirror'
-- 'mirror-link-preload' --> 'Template:Documentation/mirror'
-- 'mirror-link-preload' --> 'Template:Documentation/mirror'
-- 'sandbox-link-display' --> '沙盒'
-- 'sandbox-link-display' --> 'sandbox'
-- 'testcases-link-display' --> '测试用例'
-- 'testcases-link-display' --> 'testcases'
-- 'testcases-edit-link-display'--> '编辑'
-- 'testcases-edit-link-display'--> 'edit'
-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
-- 'testcases-create-link-display' --> '创建'
-- 'testcases-create-link-display' --> 'create'
-- 'testcases-link-display' --> '测试用例'
-- 'testcases-link-display' --> 'testcases'
-- 'testcases-edit-link-display' --> '编辑'
-- 'testcases-edit-link-display' --> 'edit'
-- 'module-testcases-preload' --> 'Template:Documentation/preload-module-testcases'
-- 'module-testcases-preload' --> 'Template:Documentation/preload-module-testcases'
-- 'template-testcases-preload' --> 'Template:Documentation/preload-testcases'
-- 'template-testcases-preload' --> 'Template:Documentation/preload-testcases'
-- 'experiment-blurb-module' --> '编辑者可以在此模块的 $1 $2 页面中进行实验。'
-- 'experiment-blurb-module' --> 'Editors can experiment in this module's $1 and $2 pages.'
-- 'experiment-blurb-template' --> '编辑者可以在此模板的 $1 $2 页面中进行实验。'
-- 'experiment-blurb-template' --> 'Editors can experiment in this template's $1 and $2 pages.'
--]]
--]]
local subjectSpace = env.subjectSpace
local subjectSpace = env.subjectSpace
第794行: 第836行:
return nil
return nil
end
end
-- 创建链接。
-- Make links.
local sandboxLinks, testcasesLinks
local sandboxLinks, testcasesLinks
if sandboxTitle.exists then
if sandboxTitle.exists then
第800行: 第842行:
local sandboxDisplay = message('sandbox-link-display')
local sandboxDisplay = message('sandbox-link-display')
local sandboxLink = makeWikilink(sandboxPage, sandboxDisplay)
local sandboxLink = makeWikilink(sandboxPage, sandboxDisplay)
local sandboxEditUrl = sandboxTitle:fullUrl{action = 'edit'}
local sandboxEditDisplay = message('sandbox-edit-link-display')
local sandboxEditDisplay = message('sandbox-edit-link-display')
local sandboxEditLink = makeUrlLink(sandboxEditUrl, sandboxEditDisplay)
local sandboxEditLink = makeWikilink("Special:EditPage/" .. sandboxPage, sandboxEditDisplay)
 
local compareUrl = env.compareUrl
local compareUrl = env.compareUrl
local compareLink
local compareLink
第818行: 第858行:
sandboxPreload = message('template-sandbox-preload')
sandboxPreload = message('template-sandbox-preload')
end
end
local sandboxCreateUrl = sandboxTitle:fullUrl{action = 'edit', preload = sandboxPreload}
local sandboxCreateUrl = sandboxTitle:canonicalUrl{action = 'edit', preload = sandboxPreload}
local sandboxCreateDisplay = message('sandbox-create-link-display')
local sandboxCreateDisplay = message('sandbox-create-link-display')
local sandboxCreateLink = makeUrlLink(sandboxCreateUrl, sandboxCreateDisplay)
local sandboxCreateLink = makeUrlLink(sandboxCreateUrl, sandboxCreateDisplay)
local mirrorSummary = message('mirror-edit-summary', {makeWikilink(templatePage)})
local mirrorSummary = message('mirror-edit-summary', {makeWikilink(templatePage)})
local mirrorPreload = message('mirror-link-preload')
local mirrorPreload = message('mirror-link-preload')
local mirrorUrl = sandboxTitle:fullUrl{action = 'edit', preload = mirrorPreload, summary = mirrorSummary}
local mirrorUrl = sandboxTitle:canonicalUrl{action = 'edit', preload = mirrorPreload, summary = mirrorSummary}
if subjectSpace == 828 then
mirrorUrl = sandboxTitle:canonicalUrl{action = 'edit', preload = templateTitle.prefixedText, summary = mirrorSummary}
end
local mirrorDisplay = message('mirror-link-display')
local mirrorDisplay = message('mirror-link-display')
local mirrorLink = makeUrlLink(mirrorUrl, mirrorDisplay)
local mirrorLink = makeUrlLink(mirrorUrl, mirrorDisplay)
第832行: 第875行:
local testcasesDisplay = message('testcases-link-display')
local testcasesDisplay = message('testcases-link-display')
local testcasesLink = makeWikilink(testcasesPage, testcasesDisplay)
local testcasesLink = makeWikilink(testcasesPage, testcasesDisplay)
local testcasesEditUrl = testcasesTitle:fullUrl{action = 'edit'}
local testcasesEditUrl = testcasesTitle:canonicalUrl{action = 'edit'}
local testcasesEditDisplay = message('testcases-edit-link-display')
local testcasesEditDisplay = message('testcases-edit-link-display')
local testcasesEditLink = makeUrlLink(testcasesEditUrl, testcasesEditDisplay)
local testcasesEditLink = makeWikilink("Special:EditPage/" .. testcasesPage, testcasesEditDisplay)
testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink)
-- for Modules, add testcases run link if exists
if testcasesTitle.contentModel == "Scribunto"  and testcasesTitle.talkPageTitle and testcasesTitle.talkPageTitle.exists then
local testcasesRunLinkDisplay = message('testcases-run-link-display')
local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink, testcasesRunLink)
else
testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink)
end
else
else
local testcasesPreload
local testcasesPreload
第843行: 第893行:
testcasesPreload = message('template-testcases-preload')
testcasesPreload = message('template-testcases-preload')
end
end
local testcasesCreateUrl = testcasesTitle:fullUrl{action = 'edit', preload = testcasesPreload}
local testcasesCreateUrl = testcasesTitle:canonicalUrl{action = 'edit', preload = testcasesPreload}
local testcasesCreateDisplay = message('testcases-create-link-display')
local testcasesCreateDisplay = message('testcases-create-link-display')
local testcasesCreateLink = makeUrlLink(testcasesCreateUrl, testcasesCreateDisplay)
local testcasesCreateLink = makeUrlLink(testcasesCreateUrl, testcasesCreateDisplay)
第859行: 第909行:
function p.makeCategoriesBlurb(args, env)
function p.makeCategoriesBlurb(args, env)
--[[
--[[
-- 生成文本 "请将分类添加到 /doc 子页面。"
-- Generates the text "Please add categories to the /doc subpage."
-- @args - 用户传递的参数表
-- @args - a table of arguments passed by the user
-- @env - 包含标题对象等的环境表,由 p.getEnvironment 生成
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- 消息:
-- Messages:
-- 'doc-link-display' --> '/doc'
-- 'doc-link-display' --> '/doc'
-- 'add-categories-blurb' --> '请将分类添加到 $1 子页面。'
-- 'add-categories-blurb' --> 'Please add categories to the $1 subpage.'
--]]
--]]
local docTitle = env.docTitle
local docTitle = env.docTitle
第876行: 第926行:
function p.makeSubpagesBlurb(args, env)
function p.makeSubpagesBlurb(args, env)
--[[
--[[
-- 生成 "此模板的子页面" 链接。
-- Generates the "Subpages of this template" link.
-- @args - 用户传递的参数表
-- @args - a table of arguments passed by the user
-- @env - 包含标题对象等的环境表,由 p.getEnvironment 生成
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- 消息:
-- Messages:
-- 'template-pagetype' --> '模板'
-- 'template-pagetype' --> 'template'
-- 'module-pagetype' --> '模块'
-- 'module-pagetype' --> 'module'
-- 'default-pagetype' --> '页面'
-- 'default-pagetype' --> 'page'
-- 'subpages-link-display' --> '$1 的子页面'
-- 'subpages-link-display' --> 'Subpages of this $1'
--]]
--]]
local subjectSpace = env.subjectSpace
local subjectSpace = env.subjectSpace
第904行: 第954行:
)
)
return message('subpages-blurb', {subpagesLink})
return message('subpages-blurb', {subpagesLink})
end
function p.makePrintBlurb(args, env)
--[=[
-- 生成当模板有打印版本可用时显示的说明。
-- @args - 用户传递的参数表
-- @env - 包含标题对象等的环境表,由 p.getEnvironment 生成
--
-- 消息:
-- 'print-link-display' --> '/Print'
-- 'print-blurb' --> '此模板的 [[Help:Books/for experts#Improving the book layout|打印版本]]'
-- .. ' 存在于 $1。'
-- .. ' 如果您对此模板进行了更改,请同时更新打印版本。'
-- 'display-print-category' --> true
-- 'print-category' --> '有打印版本的模板'
--]=]
local printTitle = env.printTitle
if not printTitle then
return nil
end
local ret
if printTitle.exists then
local printLink = makeWikilink(printTitle.prefixedText, message('print-link-display'))
ret = message('print-blurb', {printLink})
local displayPrintCategory = message('display-print-category', nil, 'boolean')
if displayPrintCategory then
ret = ret .. makeCategoryLink(message('print-category'))
end
end
return ret
end
end


----------------------------------------------------------------------------
----------------------------------------------------------------------------
-- 跟踪分类
-- Tracking categories
----------------------------------------------------------------------------
----------------------------------------------------------------------------


function p.addTrackingCategories(env)
function p.addTrackingCategories(env)
--[[
--[[
-- 检查 {{documentation}} 是否嵌入在 /doc /testcases 页面上。
-- Check if {{documentation}} is transcluded on a /doc or /testcases page.
-- @env - 包含标题对象等的环境表,由 p.getEnvironment 生成
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- 消息:
-- Messages:
-- 'display-strange-usage-category' --> true
-- 'display-strange-usage-category' --> true
-- 'doc-subpage' --> 'doc'
-- 'doc-subpage' --> 'doc'
-- 'testcases-subpage' --> 'testcases'
-- 'testcases-subpage' --> 'testcases'
-- 'strange-usage-category' --> '使用奇怪的 ((documentation)) 的维基百科页面'
-- 'strange-usage-category' --> 'Wikipedia pages with strange ((documentation)) usage'
--  
--  
-- 模块命名空间中的 /testcases 页面不会被分类,因为它们可能自动嵌入了 {{documentation}}
-- /testcases pages in the module namespace are not categorised, as they may have
-- {{documentation}} transcluded automatically.
--]]
--]]
local title = env.title
local title = env.title
第959行: 第980行:
end
end
local subpage = title.subpageText
local subpage = title.subpageText
local ret = ''
if message('display-strange-usage-category', nil, 'boolean')
if message('display-strange-usage-category', nil, 'boolean')
and (
and (
第966行: 第986行:
)
)
then
then
ret = ret .. makeCategoryLink(message('strange-usage-category'))
return makeCategoryLink(message('strange-usage-category'))
end
end
return ret
return ''
end
end


return p
return p

2025年11月24日 (一) 22:01的最新版本

-- This module implements {{documentation}}.

-- Get required modules.
local getArgs = require('Module:Arguments').getArgs

-- Get the config table.
local cfg = mw.loadData('Module:Documentation/config')

local p = {}

-- Often-used functions.
local ugsub = mw.ustring.gsub
local format = mw.ustring.format

----------------------------------------------------------------------------
-- Helper functions
--
-- These are defined as local functions, but are made available in the p
-- table for testing purposes.
----------------------------------------------------------------------------

local function message(cfgKey, valArray, expectType)
	--[[
	-- Gets a message from the cfg table and formats it if appropriate.
	-- The function raises an error if the value from the cfg table is not
	-- of the type expectType. The default type for expectType is 'string'.
	-- If the table valArray is present, strings such as $1, $2 etc. in the
	-- message are substituted with values from the table keys [1], [2] etc.
	-- For example, if the message "foo-message" had the value 'Foo $2 bar $1.',
	-- message('foo-message', {'baz', 'qux'}) would return "Foo qux bar baz."
	--]]
	local msg = cfg[cfgKey]
	expectType = expectType or 'string'
	if type(msg) ~= expectType then
		error('message: type error in message cfg.' .. cfgKey .. ' (' .. expectType .. ' expected, got ' .. type(msg) .. ')', 2)
	end
	if not valArray then
		return msg
	end

	local function getMessageVal(match)
		match = tonumber(match)
		return valArray[match] or error('message: no value found for key $' .. match .. ' in message cfg.' .. cfgKey, 4)
	end

	msg = ugsub(msg, '$([1-9][0-9]*)', getMessageVal)
	return msg
end

p.message = message

local function makeWikilink(page, display)
	if display then
		return format('[[%s|%s]]', page, display)
	else
		return format('[[%s]]', page)
	end
end

p.makeWikilink = makeWikilink

local function makeCategoryLink(cat, sort)
	local catns = mw.site.namespaces[14].name
	return makeWikilink(catns .. ':' .. cat, sort)
end

p.makeCategoryLink = makeCategoryLink

local function makeUrlLink(url, display)
	return format('[%s %s]', url, display)
end

p.makeUrlLink = makeUrlLink

local function makeToolbar(...)
	local ret = {}
	local lim = select('#', ...)
	if lim < 1 then
		return nil
	end
	for i = 1, lim do
		ret[#ret + 1] = select(i, ...)
	end
	-- 'documentation-toolbar'
	return format(
		'<span class="%s">(%s)</span>',
		message('toolbar-class'),
		table.concat(ret, ' &#124; ')
	)
end	

p.makeToolbar = makeToolbar

----------------------------------------------------------------------------
-- Argument processing
----------------------------------------------------------------------------

local function makeInvokeFunc(funcName)
	return function (frame)
		local args = getArgs(frame, {
			valueFunc = function (key, value)
				if type(value) == 'string' then
					value = value:match('^%s*(.-)%s*$') -- Remove whitespace.
					if key == 'heading' or value ~= '' then
						return value
					else
						return nil
					end
				else
					return value
				end
			end
		})
		return p[funcName](args)
	end
end

----------------------------------------------------------------------------
-- Entry points
----------------------------------------------------------------------------

function p.nonexistent(frame)
	if mw.title.getCurrentTitle().subpageText == 'testcases' then
		return frame:expandTemplate{title = 'module test cases notice'}
	else
		return p.main(frame)
	end
end

p.main = makeInvokeFunc('_main')

function p._main(args)
	--[[
	-- This function defines logic flow for the module.
	-- @args - table of arguments passed by the user
	--]]
	local env = p.getEnvironment(args)
	local root = mw.html.create()
	root
		:wikitext(p._getModuleWikitext(args, env))
		-- :wikitext(p.protectionTemplate(env))  -- 已注释掉保护横幅功能,使用 MediaWiki 自带保护显示
		:wikitext(p.sandboxNotice(args, env))
		:tag('div')
			-- 'documentation-container'
			:addClass(message('container'))
			:attr('role', 'complementary')
			:attr('aria-labelledby', args.heading ~= '' and 'documentation-heading' or nil)
			:attr('aria-label', args.heading == '' and 'Documentation' or nil)
			:newline()
			:tag('div')
				-- 'documentation'
				:addClass(message('main-div-classes'))
				:newline()
				:wikitext(p._startBox(args, env))
				:wikitext(p._content(args, env))
				:tag('div')
					-- 'documentation-clear'
					:addClass(message('clear'))
					:done()
				:newline()
				:done()
			:wikitext(p._endBox(args, env))
			:done()
		:wikitext(p.addTrackingCategories(env))
	-- 'Module:Documentation/styles.css'
	return mw.getCurrentFrame():extensionTag (
		'templatestyles', '', {src=cfg['templatestyles']
	}) .. tostring(root)
end

----------------------------------------------------------------------------
-- Environment settings
----------------------------------------------------------------------------

function p.getEnvironment(args)
	--[[
	-- Returns a table with information about the environment, including title
	-- objects and other namespace- or path-related data.
	-- @args - table of arguments passed by the user
	--
	-- Title objects include:
	-- env.title - the page we are making documentation for (usually the current title)
	-- env.templateTitle - the template (or module, file, etc.)
	-- env.docTitle - the /doc subpage.
	-- env.sandboxTitle - the /sandbox subpage.
	-- env.testcasesTitle - the /testcases subpage.
	--
	-- Data includes:
	-- env.protectionLevels - the protection levels table of the title object.
	-- env.subjectSpace - the number of the title's subject namespace.
	-- env.docSpace - the number of the namespace the title puts its documentation in.
	-- env.docpageBase - the text of the base page of the /doc, /sandbox and /testcases pages, with namespace.
	-- env.compareUrl - URL of the Special:ComparePages page comparing the sandbox with the template.
	-- 
	-- All table lookups are passed through pcall so that errors are caught. If an error occurs, the value
	-- returned will be nil.
	--]]
	
	local env, envFuncs = {}, {}

	-- Set up the metatable. If triggered we call the corresponding function in the envFuncs table. The value
	-- returned by that function is memoized in the env table so that we don't call any of the functions
	-- more than once. (Nils won't be memoized.)
	setmetatable(env, {
		__index = function (t, key)
			local envFunc = envFuncs[key]
			if envFunc then
				local success, val = pcall(envFunc)
				if success then
					env[key] = val -- Memoise the value.
					return val
				end
			end
			return nil
		end
	})	

	function envFuncs.title()
		-- The title object for the current page, or a test page passed with args.page.
		local title
		local titleArg = args.page
		if titleArg then
			title = mw.title.new(titleArg)
		else
			title = mw.title.getCurrentTitle()
		end
		return title
	end

	function envFuncs.templateTitle()
		--[[
		-- The template (or module, etc.) title object.
		-- Messages:
		-- 'sandbox-subpage' --> 'sandbox'
		-- 'testcases-subpage' --> 'testcases'
		--]]
		local subjectSpace = env.subjectSpace
		local title = env.title
		local subpage = title.subpageText
		if subpage == message('sandbox-subpage') or subpage == message('testcases-subpage') then
			return mw.title.makeTitle(subjectSpace, title.baseText)
		else
			return mw.title.makeTitle(subjectSpace, title.text)
		end
	end

	function envFuncs.docTitle()
		--[[
		-- Title object of the /doc subpage.
		-- Messages:
		-- 'doc-subpage' --> 'doc'
		--]]
		local title = env.title
		local docname = args[1] -- User-specified doc page.
		local docpage
		if docname then
			docpage = docname
		else
			docpage = env.docpageBase .. '/' .. message('doc-subpage')
		end
		return mw.title.new(docpage)
	end
	
	function envFuncs.sandboxTitle()
		--[[
		-- Title object for the /sandbox subpage.
		-- Messages:
		-- 'sandbox-subpage' --> 'sandbox'
		--]]
		return mw.title.new(env.docpageBase .. '/' .. message('sandbox-subpage'))
	end
	
	function envFuncs.testcasesTitle()
		--[[
		-- Title object for the /testcases subpage.
		-- Messages:
		-- 'testcases-subpage' --> 'testcases'
		--]]
		return mw.title.new(env.docpageBase .. '/' .. message('testcases-subpage'))
	end

	function envFuncs.protectionLevels()
		-- The protection levels table of the title object.
		return env.title.protectionLevels
	end

	function envFuncs.subjectSpace()
		-- The subject namespace number.
		return mw.site.namespaces[env.title.namespace].subject.id
	end

	function envFuncs.docSpace()
		-- The documentation namespace number. For most namespaces this is the
		-- same as the subject namespace. However, pages in the Article, File,
		-- MediaWiki or Category namespaces must have their /doc, /sandbox and
		-- /testcases pages in talk space.
		local subjectSpace = env.subjectSpace
		if subjectSpace == 0 or subjectSpace == 6 or subjectSpace == 8 or subjectSpace == 14 then
			return subjectSpace + 1
		else
			return subjectSpace
		end
	end

	function envFuncs.docpageBase()
		-- The base page of the /doc, /sandbox, and /testcases subpages.
		-- For some namespaces this is the talk page, rather than the template page.
		local templateTitle = env.templateTitle
		local docSpace = env.docSpace
		local docSpaceText = mw.site.namespaces[docSpace].name
		-- Assemble the link. docSpace is never the main namespace, so we can hardcode the colon.
		return docSpaceText .. ':' .. templateTitle.text
	end
	
	function envFuncs.compareUrl()
		-- Diff link between the sandbox and the main template using [[Special:ComparePages]].
		local templateTitle = env.templateTitle
		local sandboxTitle = env.sandboxTitle
		if templateTitle.exists and sandboxTitle.exists then
			local compareUrl = mw.uri.canonicalUrl(
				'Special:ComparePages',
				{ page1 = templateTitle.prefixedText, page2 = sandboxTitle.prefixedText}
			)
			return tostring(compareUrl)
		else
			return nil
		end
	end		

	return env
end	

----------------------------------------------------------------------------
-- Auxiliary templates
----------------------------------------------------------------------------

p.getModuleWikitext = makeInvokeFunc('_getModuleWikitext')

function p._getModuleWikitext(args, env)
	local currentTitle = mw.title.getCurrentTitle()
	if currentTitle.contentModel ~= 'Scribunto' then return end
	pcall(require, currentTitle.prefixedText) -- if it fails, we don't care
	local moduleWikitext =  package.loaded["Module:Module wikitext"]
	if moduleWikitext then
		return moduleWikitext.main()
	end
end

function p.sandboxNotice(args, env)
	--[=[
	-- Generates a sandbox notice for display above sandbox pages.
	-- @args - a table of arguments passed by the user
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment
	-- 
	-- Messages:
	-- 'sandbox-notice-image' --> '[[File:Sandbox.svg|50px|alt=|link=]]'
	-- 'sandbox-notice-blurb' --> 'This is the $1 for $2.'
	-- 'sandbox-notice-diff-blurb' --> 'This is the $1 for $2 ($3).'
	-- 'sandbox-notice-pagetype-template' --> '[[Wikipedia:Template test cases|template sandbox]] page'
	-- 'sandbox-notice-pagetype-module' --> '[[Wikipedia:Template test cases|module sandbox]] page'
	-- 'sandbox-notice-pagetype-other' --> 'sandbox page'
	-- 'sandbox-notice-compare-link-display' --> 'diff'
	-- 'sandbox-notice-testcases-blurb' --> 'See also the companion subpage for $1.'
	-- 'sandbox-notice-testcases-link-display' --> 'test cases'
	-- 'sandbox-category' --> 'Template sandboxes'
	-- 'module-sandbox-category' --> 'Module sandboxes'
	-- 'other-sandbox-category' --> 'Sandboxes outside of template or module namespace'
	--]=]
	local title = env.title
	local sandboxTitle = env.sandboxTitle
	local templateTitle = env.templateTitle
	local subjectSpace = env.subjectSpace
	if not (subjectSpace and title and sandboxTitle and templateTitle
		and mw.title.equals(title, sandboxTitle)) then
		return nil
	end
	-- Build the table of arguments to pass to {{ombox}}. We need just two fields, "image" and "text".
	local omargs = {}
	omargs.image = message('sandbox-notice-image')
	-- Get the text. We start with the opening blurb, which is something like
	-- "This is the template sandbox for [[Template:Foo]] (diff)."
	local text = '__EXPECTUNUSEDTEMPLATE__'
	local pagetype, sandboxCat
	if subjectSpace == 10 then
		pagetype = message('sandbox-notice-pagetype-template')
		sandboxCat = message('sandbox-category')
	elseif subjectSpace == 828 then
		pagetype = message('sandbox-notice-pagetype-module')
		sandboxCat = message('module-sandbox-category')
	else
		pagetype = message('sandbox-notice-pagetype-other')
		sandboxCat = message('other-sandbox-category')
	end
	local pagetypee
	if subjectSpace == 10 then
		pagetypee = message('template-pagetype')
	elseif subjectSpace == 828 then
		pagetypee = message('module-pagetype')
	else
		pagetypee = message('default-pagetype') --message 'other-pagetype' 不存在
	end
	local templateLink = makeWikilink(templateTitle.prefixedText)
	local compareUrl = env.compareUrl
	if compareUrl then
		local compareDisplay = message('sandbox-notice-compare-link-display')
		local compareLink = makeUrlLink(compareUrl, compareDisplay)
		text = text .. message('sandbox-notice-diff-blurb', {pagetype, templateLink, compareLink})
	else
		text = text .. message('sandbox-notice-blurb', {pagetype, templateLink})
	end
	-- Get the test cases page blurb if the page exists. This is something like
	-- "See also the companion subpage for [[Template:Foo/testcases|test cases]]."
	local testcasesTitle = env.testcasesTitle
	if testcasesTitle and testcasesTitle.exists then
		if testcasesTitle.contentModel == "Scribunto" then
			local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
			local testcasesRunLinkDisplay = message('sandbox-notice-testcases-run-link-display')
			local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
			local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
			text = text .. '<br /><small>' .. message('sandbox-notice-testcases-run-blurb', {pagetypee, testcasesLink, testcasesRunLink}) .. '</small>'
		else
			local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
			local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
			text = text .. '<br /><small>' .. message('sandbox-notice-testcases-blurb', {pagetypee, testcasesLink}) .. '</small>'
		end
	end
	
	-- Add the sandbox to the sandbox category.
	omargs.text = text .. makeCategoryLink(sandboxCat)

	-- 'documentation-clear'
	return '<div class="' .. message('clear') .. '"></div>'
		.. require('Module:Message box').main('ombox', omargs)
end

-- 注释掉保护横幅功能,使用 MediaWiki 自带的保护显示
-- 新版 MediaWiki 已自带页面保护显示功能,无需模板模块依赖
--[[
function p.protectionTemplate(env)
	-- Generates the padlock icon in the top right.
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment
	-- Messages:
	-- 'protection-template' --> 'pp-template'
	-- 'protection-template-args' --> {docusage = 'yes'}
	local protectionLevels = env.protectionLevels
	if not protectionLevels then
		return nil
	end
	local editProt = protectionLevels.edit and protectionLevels.edit[1]
	local moveProt = protectionLevels.move and protectionLevels.move[1]
	if editProt then
		-- The page is edit-protected.
		return require('Module:Protection banner')._main{
			message('protection-reason-edit'), small = true
		}
	elseif moveProt and moveProt ~= 'autoconfirmed' then
		-- The page is move-protected but not edit-protected. Exclude move
		-- protection with the level "autoconfirmed", as this is equivalent to
		-- no move protection at all.
		return require('Module:Protection banner')._main{
			action = 'move', small = true
		}
	else
		return nil
	end
end
--]]

----------------------------------------------------------------------------
-- Start box
----------------------------------------------------------------------------

p.startBox = makeInvokeFunc('_startBox')

function p._startBox(args, env)
	--[[
	-- This function generates the start box.
	-- @args - a table of arguments passed by the user
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment
	-- 
	-- The actual work is done by p.makeStartBoxLinksData and p.renderStartBoxLinks which make
	-- the [view] [edit] [history] [purge] links, and by p.makeStartBoxData and p.renderStartBox
	-- which generate the box HTML.
	--]]
	env = env or p.getEnvironment(args)
	local links
	local content = args.content
	if not content or args[1] then
		-- No need to include the links if the documentation is on the template page itself.
		local linksData = p.makeStartBoxLinksData(args, env)
		if linksData then
			links = p.renderStartBoxLinks(linksData)
		end
	end
	-- Generate the start box html.
	local data = p.makeStartBoxData(args, env, links)
	if data then
		return p.renderStartBox(data)
	else
		-- User specified no heading.
		return nil
	end
end

function p.makeStartBoxLinksData(args, env)
	--[[
	-- Does initial processing of data to make the [view] [edit] [history] [purge] links.
	-- @args - a table of arguments passed by the user
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment
	-- 
	-- Messages:
	-- 'view-link-display' --> 'view'
	-- 'edit-link-display' --> 'edit'
	-- 'history-link-display' --> 'history'
	-- 'purge-link-display' --> 'purge'
	-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
	-- 'docpage-preload' --> 'Template:Documentation/preload'
	-- 'create-link-display' --> 'create'
	--]]
	local subjectSpace = env.subjectSpace
	local title = env.title
	local docTitle = env.docTitle
	if not title or not docTitle then
		return nil
	end
	if docTitle.isRedirect then 
		docTitle = docTitle.redirectTarget
	end

	-- Create link if /doc doesn't exist.
	local preload = args.preload
	if not preload then
		if subjectSpace == 828 then -- Module namespace
			preload = message('module-preload')
		else
			preload = message('docpage-preload')
		end
	end
	
	return {
		title = title,
		docTitle = docTitle,
		-- View, display, edit, and purge links if /doc exists.
		viewLinkDisplay = message('view-link-display'),
		editLinkDisplay = message('edit-link-display'),
		historyLinkDisplay = message('history-link-display'),
		purgeLinkDisplay = message('purge-link-display'),
		preload = preload,
		createLinkDisplay = message('create-link-display')
	}
end

function p.renderStartBoxLinks(data)
	--[[
	-- Generates the [view][edit][history][purge] or [create][purge] links from the data table.
	-- @data - a table of data generated by p.makeStartBoxLinksData
	--]]
	local docTitle = data.docTitle
	-- yes, we do intend to purge the template page on which the documentation appears
	local purgeLink = makeWikilink("Special:Purge/" .. data.title.prefixedText, data.purgeLinkDisplay)
	
	if docTitle.exists then
		local viewLink = makeWikilink(docTitle.prefixedText, data.viewLinkDisplay)
		local editLink = makeWikilink("Special:EditPage/" .. docTitle.prefixedText, data.editLinkDisplay)
		local historyLink = makeWikilink("Special:PageHistory/" .. docTitle.prefixedText, data.historyLinkDisplay)
		return "&#91;" .. viewLink .. "&#93; &#91;" .. editLink .. "&#93; &#91;" .. historyLink .. "&#93; &#91;" .. purgeLink .. "&#93;"
	else
		local createLink = makeUrlLink(docTitle:canonicalUrl{action = 'edit', preload = data.preload}, data.createLinkDisplay)
		return  "&#91;" .. createLink .. "&#93; &#91;" .. purgeLink .. "&#93;"
	end
	return ret
end

function p.makeStartBoxData(args, env, links)
	--[=[
	-- Does initial processing of data to pass to the start-box render function, p.renderStartBox.
	-- @args - a table of arguments passed by the user
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment
	-- @links - a string containing the [view][edit][history][purge] links - could be nil if there's an error.
	--
	-- Messages:
	-- 'documentation-icon-wikitext' --> '[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=]]'
	-- 'template-namespace-heading' --> 'Template documentation'
	-- 'module-namespace-heading' --> 'Module documentation'
	-- 'file-namespace-heading' --> 'Summary'
	-- 'other-namespaces-heading' --> 'Documentation'
	-- 'testcases-create-link-display' --> 'create'
	--]=]
	local subjectSpace = env.subjectSpace
	if not subjectSpace then
		-- Default to an "other namespaces" namespace, so that we get at least some output
		-- if an error occurs.
		subjectSpace = 2
	end
	local data = {}
	
	-- Heading
	local heading = args.heading -- Blank values are not removed.
	if heading == '' then
		-- Don't display the start box if the heading arg is defined but blank.
		return nil
	end
	if heading then
		data.heading = heading
	elseif subjectSpace == 10 then -- Template namespace
		data.heading = message('documentation-icon-wikitext') .. ' ' .. message('template-namespace-heading')
	elseif subjectSpace == 828 then -- Module namespace
		data.heading = message('documentation-icon-wikitext') .. ' ' .. message('module-namespace-heading')
	elseif subjectSpace == 6 then -- File namespace
		data.heading = message('file-namespace-heading')
	else
		data.heading = message('other-namespaces-heading')
	end
	
	-- Heading CSS
	local headingStyle = args['heading-style']
	if headingStyle then
		data.headingStyleText = headingStyle
	else
		-- 'documentation-heading'
		data.headingClass = message('main-div-heading-class')
	end
	
	-- Data for the [view][edit][history][purge] or [create] links.
	if links then
		-- 'mw-editsection-like plainlinks'
		data.linksClass = message('start-box-link-classes')
		data.links = links
	end
	
	return data
end

function p.renderStartBox(data)
	-- Renders the start box html.
	-- @data - a table of data generated by p.makeStartBoxData.
	local sbox = mw.html.create('div')
	sbox
		-- 'documentation-startbox'
		:addClass(message('start-box-class'))
		:newline()
		:tag('span')
			:addClass(data.headingClass)
			:attr('id', 'documentation-heading')
			:cssText(data.headingStyleText)
			:wikitext(data.heading)
	local links = data.links
	if links then
		sbox:tag('span')
			:addClass(data.linksClass)
			:attr('id', data.linksId)
			:wikitext(links)
	end
	return tostring(sbox)
end

----------------------------------------------------------------------------
-- Documentation content
----------------------------------------------------------------------------

p.content = makeInvokeFunc('_content')

function p._content(args, env)
	-- Displays the documentation contents
	-- @args - a table of arguments passed by the user
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment
	env = env or p.getEnvironment(args)
	local docTitle = env.docTitle
	local content = args.content
	if not content and docTitle and docTitle.exists then
		content = args._content or mw.getCurrentFrame():expandTemplate{title = docTitle.prefixedText}
	end
	-- The line breaks below are necessary so that "=== Headings ===" at the start and end
	-- of docs are interpreted correctly.
	return '\n' .. (content or '') .. '\n' 
end

p.contentTitle = makeInvokeFunc('_contentTitle')

function p._contentTitle(args, env)
	env = env or p.getEnvironment(args)
	local docTitle = env.docTitle
	if not args.content and docTitle and docTitle.exists then
		return docTitle.prefixedText
	else
		return ''
	end
end

----------------------------------------------------------------------------
-- End box
----------------------------------------------------------------------------

p.endBox = makeInvokeFunc('_endBox')

function p._endBox(args, env)
	--[=[
	-- This function generates the end box (also known as the link box).
	-- @args - a table of arguments passed by the user
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment
	-- 
	--]=]
	
	-- Get environment data.
	env = env or p.getEnvironment(args)
	local subjectSpace = env.subjectSpace
	local docTitle = env.docTitle
	if not subjectSpace or not docTitle then
		return nil
	end
		
	-- Check whether we should output the end box at all. Add the end
	-- box by default if the documentation exists or if we are in the
	-- user, module or template namespaces.
	local linkBox = args['link box']
	if linkBox == 'off'
		or not (
			docTitle.exists
			or subjectSpace == 2
			or subjectSpace == 828
			or subjectSpace == 10
		)
	then
		return nil
	end

	-- Assemble the link box.
	local text = ''
	if linkBox then
		text = text .. linkBox
	else
		text = text .. (p.makeDocPageBlurb(args, env) or '') -- "This documentation is transcluded from [[Foo]]." 
		if subjectSpace == 2 or subjectSpace == 10 or subjectSpace == 828 then
			-- We are in the user, template or module namespaces.
			-- Add sandbox and testcases links.
			-- "Editors can experiment in this template's sandbox and testcases pages."
			text = text .. (p.makeExperimentBlurb(args, env) or '') .. '<br />'
			if not args.content and not args[1] then
				-- "Please add categories to the /doc subpage."
				-- Don't show this message with inline docs or with an explicitly specified doc page,
				-- as then it is unclear where to add the categories.
				text = text .. (p.makeCategoriesBlurb(args, env) or '')
			end
			text = text .. ' ' .. (p.makeSubpagesBlurb(args, env) or '') --"Subpages of this template"
		end
	end
	
	local box = mw.html.create('div')
	-- 'documentation-metadata'
	box:attr('role', 'note')
		:addClass(message('end-box-class'))
		-- 'plainlinks'
		:addClass(message('end-box-plainlinks'))
		:wikitext(text)
		:done()

	return '\n' .. tostring(box)
end

function p.makeDocPageBlurb(args, env)
	--[=[
	-- Makes the blurb "This documentation is transcluded from [[Template:Foo]] (edit, history)".
	-- @args - a table of arguments passed by the user
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment
	-- 
	-- Messages:
	-- 'edit-link-display' --> 'edit'
	-- 'history-link-display' --> 'history'
	-- 'transcluded-from-blurb' --> 
	-- 'The above [[Wikipedia:Template documentation|documentation]] 
	-- is [[Help:Transclusion|transcluded]] from $1.'
	-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
	-- 'create-link-display' --> 'create'
	-- 'create-module-doc-blurb' -->
	-- 'You might want to $1 a documentation page for this [[Wikipedia:Lua|Scribunto module]].'
	--]=]
	local docTitle = env.docTitle
	if not docTitle then
		return nil
	end
	if docTitle.exists then
		-- /doc exists; link to it.
		local docLink = makeWikilink(docTitle.prefixedText)
		local editDisplay = message('edit-link-display')
		local editLink = makeWikilink("Special:EditPage/" .. docTitle.prefixedText, editDisplay)
		local historyDisplay = message('history-link-display')
		local historyLink = makeWikilink("Special:PageHistory/" .. docTitle.prefixedText, historyDisplay)
		return message('transcluded-from-blurb', {docLink})
			.. ' '
			.. makeToolbar(editLink, historyLink)
			.. '<br />'
	elseif env.subjectSpace == 828 then
		-- /doc does not exist; ask to create it.
		local createUrl = docTitle:canonicalUrl{action = 'edit', preload = message('module-preload')}
		local createDisplay = message('create-link-display')
		local createLink = makeUrlLink(createUrl, createDisplay)
		return message('create-module-doc-blurb', {createLink})
			.. '<br />'
	end
end

function p.makeExperimentBlurb(args, env)
	--[[
	-- Renders the text "Editors can experiment in this template's sandbox (edit | diff) and testcases (edit) pages."
	-- @args - a table of arguments passed by the user
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment
	-- 
	-- Messages:
	-- 'sandbox-link-display' --> 'sandbox'
	-- 'sandbox-edit-link-display' --> 'edit'
	-- 'compare-link-display' --> 'diff'
	-- 'module-sandbox-preload' --> 'Template:Documentation/preload-module-sandbox'
	-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
	-- 'sandbox-create-link-display' --> 'create'
	-- 'mirror-edit-summary' --> 'Create sandbox version of $1'
	-- 'mirror-link-display' --> 'mirror'
	-- 'mirror-link-preload' --> 'Template:Documentation/mirror'
	-- 'sandbox-link-display' --> 'sandbox'
	-- 'testcases-link-display' --> 'testcases'
	-- 'testcases-edit-link-display'--> 'edit'
	-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
	-- 'testcases-create-link-display' --> 'create'
	-- 'testcases-link-display' --> 'testcases'
	-- 'testcases-edit-link-display' --> 'edit'
	-- 'module-testcases-preload' --> 'Template:Documentation/preload-module-testcases'
	-- 'template-testcases-preload' --> 'Template:Documentation/preload-testcases'
	-- 'experiment-blurb-module' --> 'Editors can experiment in this module's $1 and $2 pages.'
	-- 'experiment-blurb-template' --> 'Editors can experiment in this template's $1 and $2 pages.'
	--]]
	local subjectSpace = env.subjectSpace
	local templateTitle = env.templateTitle
	local sandboxTitle = env.sandboxTitle
	local testcasesTitle = env.testcasesTitle
	local templatePage = templateTitle.prefixedText
	if not subjectSpace or not templateTitle or not sandboxTitle or not testcasesTitle then
		return nil
	end
	-- Make links.
	local sandboxLinks, testcasesLinks
	if sandboxTitle.exists then
		local sandboxPage = sandboxTitle.prefixedText
		local sandboxDisplay = message('sandbox-link-display')
		local sandboxLink = makeWikilink(sandboxPage, sandboxDisplay)
		local sandboxEditDisplay = message('sandbox-edit-link-display')
		local sandboxEditLink = makeWikilink("Special:EditPage/" .. sandboxPage, sandboxEditDisplay)
		local compareUrl = env.compareUrl
		local compareLink
		if compareUrl then
			local compareDisplay = message('compare-link-display')
			compareLink = makeUrlLink(compareUrl, compareDisplay)
		end
		sandboxLinks = sandboxLink .. ' ' .. makeToolbar(sandboxEditLink, compareLink)
	else
		local sandboxPreload
		if subjectSpace == 828 then
			sandboxPreload = message('module-sandbox-preload')
		else
			sandboxPreload = message('template-sandbox-preload')
		end
		local sandboxCreateUrl = sandboxTitle:canonicalUrl{action = 'edit', preload = sandboxPreload}
		local sandboxCreateDisplay = message('sandbox-create-link-display')
		local sandboxCreateLink = makeUrlLink(sandboxCreateUrl, sandboxCreateDisplay)
		local mirrorSummary = message('mirror-edit-summary', {makeWikilink(templatePage)})
		local mirrorPreload = message('mirror-link-preload')
		local mirrorUrl = sandboxTitle:canonicalUrl{action = 'edit', preload = mirrorPreload, summary = mirrorSummary}
		if subjectSpace == 828 then
			mirrorUrl = sandboxTitle:canonicalUrl{action = 'edit', preload = templateTitle.prefixedText, summary = mirrorSummary}
		end
		local mirrorDisplay = message('mirror-link-display')
		local mirrorLink = makeUrlLink(mirrorUrl, mirrorDisplay)
		sandboxLinks = message('sandbox-link-display') .. ' ' .. makeToolbar(sandboxCreateLink, mirrorLink)
	end
	if testcasesTitle.exists then
		local testcasesPage = testcasesTitle.prefixedText
		local testcasesDisplay = message('testcases-link-display')
		local testcasesLink = makeWikilink(testcasesPage, testcasesDisplay)
		local testcasesEditUrl = testcasesTitle:canonicalUrl{action = 'edit'}
		local testcasesEditDisplay = message('testcases-edit-link-display')
		local testcasesEditLink = makeWikilink("Special:EditPage/" .. testcasesPage, testcasesEditDisplay)
		-- for Modules, add testcases run link if exists
		if testcasesTitle.contentModel == "Scribunto"  and testcasesTitle.talkPageTitle and testcasesTitle.talkPageTitle.exists then
			local testcasesRunLinkDisplay = message('testcases-run-link-display')
			local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
			testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink, testcasesRunLink)
		else
			testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink)
		end
	else
		local testcasesPreload
		if subjectSpace == 828 then
			testcasesPreload = message('module-testcases-preload')
		else
			testcasesPreload = message('template-testcases-preload')
		end
		local testcasesCreateUrl = testcasesTitle:canonicalUrl{action = 'edit', preload = testcasesPreload}
		local testcasesCreateDisplay = message('testcases-create-link-display')
		local testcasesCreateLink = makeUrlLink(testcasesCreateUrl, testcasesCreateDisplay)
		testcasesLinks = message('testcases-link-display') .. ' ' .. makeToolbar(testcasesCreateLink)
	end
	local messageName
	if subjectSpace == 828 then
		messageName = 'experiment-blurb-module'
	else
		messageName = 'experiment-blurb-template'
	end
	return message(messageName, {sandboxLinks, testcasesLinks})
end

function p.makeCategoriesBlurb(args, env)
	--[[
	-- Generates the text "Please add categories to the /doc subpage."
	-- @args - a table of arguments passed by the user
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment
	-- Messages:
	-- 'doc-link-display' --> '/doc'
	-- 'add-categories-blurb' --> 'Please add categories to the $1 subpage.'
	--]]
	local docTitle = env.docTitle
	if not docTitle then
		return nil
	end
	local docPathLink = makeWikilink(docTitle.prefixedText, message('doc-link-display'))
	return message('add-categories-blurb', {docPathLink})
end

function p.makeSubpagesBlurb(args, env)
	--[[
	-- Generates the "Subpages of this template" link.
	-- @args - a table of arguments passed by the user
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment
	
	-- Messages:
	-- 'template-pagetype' --> 'template'
	-- 'module-pagetype' --> 'module'
	-- 'default-pagetype' --> 'page'
	-- 'subpages-link-display' --> 'Subpages of this $1'
	--]]
	local subjectSpace = env.subjectSpace
	local templateTitle = env.templateTitle
	if not subjectSpace or not templateTitle then
		return nil
	end
	local pagetype
	if subjectSpace == 10 then
		pagetype = message('template-pagetype')
	elseif subjectSpace == 828 then
		pagetype = message('module-pagetype')
	else
		pagetype = message('default-pagetype')
	end
	local subpagesLink = makeWikilink(
		'Special:PrefixIndex/' .. templateTitle.prefixedText .. '/',
		message('subpages-link-display', {pagetype})
	)
	return message('subpages-blurb', {subpagesLink})
end

----------------------------------------------------------------------------
-- Tracking categories
----------------------------------------------------------------------------

function p.addTrackingCategories(env)
	--[[
	-- Check if {{documentation}} is transcluded on a /doc or /testcases page.
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment
	
	-- Messages:
	-- 'display-strange-usage-category' --> true
	-- 'doc-subpage' --> 'doc'
	-- 'testcases-subpage' --> 'testcases'
	-- 'strange-usage-category' --> 'Wikipedia pages with strange ((documentation)) usage'
	-- 
	-- /testcases pages in the module namespace are not categorised, as they may have
	-- {{documentation}} transcluded automatically.
	--]]
	local title = env.title
	local subjectSpace = env.subjectSpace
	if not title or not subjectSpace then
		return nil
	end
	local subpage = title.subpageText
	if message('display-strange-usage-category', nil, 'boolean')
		and (
			subpage == message('doc-subpage')
			or subjectSpace ~= 828 and subpage == message('testcases-subpage')
		)
	then
		return makeCategoryLink(message('strange-usage-category'))
	end
	return ''
end

return p