Module:Documentation: Difference between revisions
From Roses, Tulips, & Liberty
Content deleted Content added
No edit summary |
replace content with a port of English Wikipedia's Template:Documentation |
||
Line 1: | Line 1: | ||
--This module implements {{ |
-- This module implements {{documentation}}. |
||
-- Get required modules. |
|||
local getArgs = require('Module:Arguments').getArgs |
|||
local htmlBuilder = require('Module:HtmlBuilder') |
|||
local messageBox = require('Module:Message box') |
|||
local p = {} |
local p = {} |
||
-- Constants. |
|||
function p.corps(frame) |
|||
local currentTitle = mw.title.getCurrentTitle() |
|||
args = frame:getParent().args |
|||
local subjectSpace = mw.site.namespaces[currentTitle.namespace].subject.id |
|||
local page = mw.title.getCurrentTitle() |
|||
doc = p.docname(page) |
|||
---------------------------------------------------------------------------- |
|||
local corps = {} |
|||
-- Helper functions |
|||
---------------------------------------------------------------------------- |
|||
if page.subpageText == 'sandbox' then |
|||
table.insert(corps, '<div style="clear:both />') |
|||
local function makeWikilink(page, display) |
|||
table.insert(corps, frame:preprocess('{{Template sandbox notice}}')) |
|||
if display then |
|||
end |
|||
return mw.ustring.format('[[%s|%s]]', page, display) |
|||
else |
|||
table.insert(corps, p.header(page)) |
|||
return mw.ustring.format('[[%s]]', page) |
|||
table.insert(corps, p.content(frame, page)) |
|||
end |
|||
table.insert(corps, p.footer(page)) |
|||
if args.raw then |
|||
return frame:preprocess('<nowiki>' .. table.concat(corps) .. '</nowiki>\n:' .. os.clock()) |
|||
end |
|||
return table.concat(corps) |
|||
end |
end |
||
function |
local function makeUrlLink(url, display) |
||
return mw.ustring.format('[%s %s]', url, display) |
|||
if not page.isSubpage then return page.subjectNsText .. ":" .. page.text .. "/doc" end |
|||
if page.subpageText == 'doc' |
|||
or page.subpageText == 'sandbox' |
|||
or page.subpageText == 'testcases' then |
|||
return page.subjectNsText .. ":" .. page.baseText .. "/doc" |
|||
else |
|||
return page.subjectNsText .. ":" .. page.text .. "/doc" |
|||
end |
|||
end |
end |
||
---------------------------------------------------------------------------- |
|||
function p.ifexist(page) |
|||
-- Main functions |
|||
if not page then return false end |
|||
---------------------------------------------------------------------------- |
|||
if mw.title.new(page).exists then return true end |
|||
return false |
|||
function p.main(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._main(args) |
|||
end |
end |
||
function p. |
function p._main(args) |
||
local root = htmlBuilder.create() |
|||
local header = {'<div class="template-documentation"'} |
|||
root |
|||
.wikitext(p.protectionTemplate()) |
|||
if args.color then |
|||
.wikitext(p.sandboxNotice(args)) |
|||
table.insert(header, ' style="background:') |
|||
-- This div tag is from {{documentation/start box}}, but moving it here so that we don't have to worry about unclosed tags. |
|||
table.insert(header, args.color .. '"') |
|||
.tag('div') |
|||
end |
|||
.attr('id', 'template-documentation') |
|||
.addClass('template-documentation iezoomfix') |
|||
table.insert(header, '><div style="margin-bottom:1ex; border-bottom:1px solid #aaa; padding-bottom:3px;">') |
|||
.wikitext(p.startBox(args)) |
|||
table.insert(header, '[[File:Template-info.png|50px|alt=Template documentation|link=]]') |
|||
.wikitext(p.content(args)) |
|||
table.insert(header, '<span style="font-weight:bold; font-size:125%"> ') |
|||
.tag('div') |
|||
.css('clear', 'both') -- So right or left floating items don't stick out of the doc box. |
|||
if args.heading then table.insert(header, args.heading) |
|||
.done() |
|||
else table.insert(header, 'Template documentation') end |
|||
.done() |
|||
table.insert(header, '</span>') |
|||
.wikitext(p.endBox(args)) |
|||
.wikitext(p.addTrackingCategories()) |
|||
if not args.content then |
|||
return tostring(root) |
|||
table.insert(header, '<span class="mw-editsection plainlinks">[[') |
|||
local arg = mw.title.new(args[1] or doc) |
|||
if args[1] and p.ifexist(args[1]) or p.ifexist(doc) then |
|||
table.insert(header, arg:fullUrl('action=view') .. ' view]') |
|||
table.insert(header, '] [[') |
|||
table.insert(header, arg:fullUrl('action=edit') .. ' edit]') |
|||
table.insert(header, '] [[') |
|||
table.insert(header, arg:fullUrl('action=history') .. ' history]') |
|||
table.insert(header, '] [[') |
|||
table.insert(header, page:fullUrl('action=purge') .. ' purge]') |
|||
else |
|||
table.insert(header, arg:fullUrl({["action"]="edit", ["preload"]="Template:Documentation/preload"})) |
|||
table.insert(header, ' create]') |
|||
end |
|||
table.insert(header, ']</span>') |
|||
end |
|||
table.insert(header, '</div>') |
|||
return table.concat(header) |
|||
end |
end |
||
function p. |
function p.sandboxNotice(args) |
||
if currentTitle.subpageText == 'sandbox' then |
|||
local content = {} |
|||
local frame = mw.getCurrentFrame() |
|||
local root = htmlBuilder.create() |
|||
if args.content then |
|||
root |
|||
table.insert(content, '\n') |
|||
.tag('div') |
|||
table.insert(content, args.content) |
|||
.css('clear', 'both') |
|||
else |
|||
.done() |
|||
table.insert(content, frame:preprocess('<nowiki />')) |
|||
.wikitext(frame:expandTemplate{title = 'template sandbox notice', args = {args.livepage}}) |
|||
table.insert(content, '\n') |
|||
return tostring(root) |
|||
if args[1] and p.ifexist(args[1]) or p.ifexist(doc) then |
|||
else |
|||
table.insert(content, frame:preprocess('{{' .. arg .. '}}')) |
|||
return nil |
|||
end |
|||
end |
|||
table.insert(content, '\n') |
|||
table.insert(content, frame:preprocess('<nowiki />')) |
|||
table.insert(content, '<div style="clear:both" />\n') |
|||
return table.concat(content) |
|||
end |
end |
||
function p. |
function p.protectionTemplate() |
||
if currentTitle.namespace == 10 then -- We are in the template namespace. |
|||
local footer = {} |
|||
local frame = mw.getCurrentFrame() |
|||
local function getProtectionLevel(protectionType) |
|||
table.insert(footer, '</div><div class="template-documentation plainlinks" ') |
|||
-- Gets the protection level for the current page. |
|||
table.insert(footer, 'style="font-style:italic; margin:2px 0px 0px; padding: 0.35em 0.9em') |
|||
local level = frame:callParserFunction('PROTECTIONLEVEL', protectionType) |
|||
if level ~= '' then |
|||
return level |
|||
table.insert(footer, '; background:') |
|||
else |
|||
table.insert(footer, args.color) |
|||
return nil -- The parser function returns the blank string if there is no match. |
|||
end |
|||
end |
|||
table.insert(footer, ';">\n') |
|||
end |
|||
if args.content then |
|||
if getProtectionLevel('move') == 'sysop' or getProtectionLevel('edit') then |
|||
if args["link box"] then |
|||
-- The page is full-move protected, or full, template, or semi-protected. |
|||
table.insert(footer, args["link box"]) |
|||
return frame:expandTemplate{title = 'pp-template', args = {docusage = 'yes'}} |
|||
else |
|||
end |
|||
table.insert(footer, 'This documentation is directly included in this page.') |
|||
end |
|||
return nil |
|||
else |
|||
if args[1] and p.ifexist(args[1]) or p.ifexist(doc) then |
|||
table.insert(footer, 'The above [[Wikipedia:Template documentation|documentation]] is ') |
|||
table.insert(footer, '[[Wikipedia:Transclusion|transcluded]] from [[') |
|||
table.insert(footer, tostring(arg)) |
|||
table.insert(footer, ']] <span style="font-size:89%; font-style:normal;">([') |
|||
table.insert(footer, arg:fullUrl('action=edit')) |
|||
table.insert(footer, ' edit] | [') |
|||
table.insert(footer, arg:fullUrl('action=history') .. ' history])</span>.<br />') |
|||
end |
|||
table.insert(footer, 'Editors can experiment in this templates ') |
|||
local sandbox = arg.subjectNsText .. ":" .. arg.baseText .. "/sandbox" |
|||
local argsandbox = mw.title.new(sandbox) |
|||
if p.ifexist(sandbox) then |
|||
table.insert(footer, '[[' .. sandbox .. '|sandbox]]') |
|||
table.insert(footer, ' <span style="font-size:89%; font-style:normal;">([') |
|||
table.insert(footer, argsandbox:fullUrl('action=edit')) |
|||
table.insert(footer, ' edit])</span>') |
|||
else |
|||
table.insert(footer, 'sandbox <span style="font-size:89%; font-style:normal;">([') |
|||
table.insert(footer, argsandbox:fullUrl({["action"]="edit", ["preload"]="Template:Documentation/preload-sandbox"})) |
|||
table.insert(footer, ' create])</span>') |
|||
end |
|||
table.insert(footer, ' and ') |
|||
local test = arg.subjectNsText .. ":" .. arg.baseText .. "/testcases" |
|||
local argtest = mw.title.new(test) |
|||
if p.ifexist(test) then |
|||
table.insert(footer, '[[' .. test .. '|testcases]]') |
|||
table.insert(footer, ' <span style="font-size:89%; font-style:normal;">([') |
|||
table.insert(footer, argtest:fullUrl('action=edit')) |
|||
table.insert(footer, ' edit])</span>') |
|||
else |
|||
table.insert(footer, 'testcases <span style="font-size:89%; font-style:normal;">([') |
|||
table.insert(footer, argtest:fullUrl({["action"]="edit", ["preload"]="Template:Documentation/preload-testcases"})) |
|||
table.insert(footer, ' create])</span>') |
|||
end |
|||
table.insert(footer, ' pages.<br />Please add categories to the ') |
|||
table.insert(footer, '<span class="plainlinks">[') |
|||
if args[1] and p.ifexist(args[1]) or p.ifexist(doc) then |
|||
table.insert(footer, arg:fullUrl('action=edit')) |
|||
else |
|||
table.insert(footer, arg:fullUrl({["action"]="edit", ["preload"]="Template:Documentation/preload"})) |
|||
end |
|||
table.insert(footer, ' /doc] subpage.') |
|||
end |
|||
table.insert(footer, '</div>') |
|||
return table.concat(footer) |
|||
end |
end |
||
function p.startBox(args) |
|||
-- Arg processing from {{documentation}}. |
|||
local preload = args.preload -- Allow custom preloads. |
|||
local heading = args.heading -- Blank values are not removed. |
|||
local headingStyle = args['heading-style'] |
|||
local content = args.content |
|||
local docspace = p.docspace() |
|||
local docname = args[1] -- Other docname, if fed. |
|||
local templatePage = p.templatePage() |
|||
-- Arg processing from {{documentation/start box2}}. |
|||
local docpage |
|||
if docname then |
|||
docpage = docname |
|||
else |
|||
local namespace = docspace or currentTitle.nsText |
|||
local pagename = templatePage or currentTitle.text |
|||
docpage = namespace .. ':' .. pagename .. '/doc' |
|||
end |
|||
local docTitle = mw.title.new(docpage) |
|||
local docExist = docTitle.exists |
|||
-- Output from {{documentation/start box}}. |
|||
-- First, check the heading parameter. |
|||
if heading == '' then |
|||
-- Heading is defined but blank, so do nothing. |
|||
return nil |
|||
end |
|||
-- Build the start box div. |
|||
local sbox = htmlBuilder.create('div') |
|||
sbox |
|||
.css('padding-bottom', '3px') |
|||
.css('border-bottom', '1px solid #aaa') |
|||
.css('margin-bottom', '1ex') |
|||
-- Make the heading. |
|||
local hspan = sbox.tag('span') |
|||
if headingStyle then |
|||
hspan.cssText(headingStyle) |
|||
elseif subjectSpace == 10 then |
|||
-- We are in the template or template talk namespaces. |
|||
hspan |
|||
.css('font-weight', 'bold') |
|||
.css('fond-size', '125%') |
|||
else |
|||
hspan.css('font-size', '150%') |
|||
end |
|||
if heading then |
|||
-- "heading" has data. |
|||
hspan.wikitext(heading) |
|||
elseif subjectSpace == 10 then -- Template namespace |
|||
hspan.wikitext('[[File:Template-info.png|50px|link=|alt=Documentation icon]] Template documentation') |
|||
elseif subjectSpace == 828 then -- Module namespace |
|||
hspan.wikitext('[[File:Template-info.png|50px|link=|alt=Documentation icon]] Module documentation') |
|||
elseif subjectSpace == 6 then -- File namespace |
|||
hspan.wikitext('Summary') |
|||
else |
|||
hspan.wikitext('Documentation') |
|||
end |
|||
-- Add the [view][edit][history][purge] or [create] links. |
|||
-- Check for the content parameter first, as we don't need the links if the documentation |
|||
-- content is being entered directly onto the template page. |
|||
if not content then |
|||
local lspan = sbox.tag('span') -- lspan is short for "link span". |
|||
lspan |
|||
.addClass('mw-editsection plainlinks') |
|||
.attr('id', 'doc_editlinks') |
|||
if docExist then |
|||
local viewLink = makeWikilink(docpage, 'view') |
|||
local editLink = makeUrlLink(docTitle:fullUrl{action = 'edit'}, 'edit') |
|||
local historyLink = makeUrlLink(docTitle:fullUrl{action = 'history'}, 'history') |
|||
local purgeLink = makeUrlLink(docTitle:fullUrl{action = 'purge'}, 'purge') |
|||
local text = '[%s] [%s] [%s] [%s]' |
|||
text = text:gsub('%[', '[') -- Replace square brackets with HTML entities. |
|||
text = text:gsub('%]', ']') |
|||
lspan.wikitext(mw.ustring.format(text, viewLink, editLink, historyLink, purgeLink)) |
|||
else |
|||
if preload then |
|||
preload = mw.uri.encode(preload) |
|||
elseif subjectSpace == 6 then -- File namespace |
|||
preload = 'Template:Documentation/preload-filespace' |
|||
else |
|||
preload = 'Template:Documentation/preload' |
|||
end |
|||
lspan.wikitext(makeUrlLink(docTitle:fullUrl{action = 'edit', preload = preload}, 'create')) |
|||
end |
|||
end |
|||
return tostring(sbox) |
|||
end |
|||
function p.content(args) |
|||
local content = args.content |
|||
if not content then |
|||
local docpage = args[1] |
|||
if docpage and mw.title.new(docpage).exists then |
|||
local frame = mw.getCurrentFrame() |
|||
content = frame:preprocess('{{ ' .. docpage .. ' }}') |
|||
else |
|||
docpage = p.docspace() .. ':' .. p.templatePage() .. '/doc' |
|||
if mw.title.new(docpage).exists then |
|||
local frame = mw.getCurrentFrame() |
|||
content = frame:preprocess('{{ ' .. docpage .. ' }}') |
|||
end |
|||
end |
|||
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 |
|||
function p.endBox(args) |
|||
-- Argument processing in {{documentation}}. |
|||
local preload = args.preload -- Allow custom preloads. |
|||
local content = args.content |
|||
local linkBox = args['link box'] -- So "link box=off" works. |
|||
local docspace = p.docspace() |
|||
local docname = args[1] -- Other docname, if fed. |
|||
local templatePage = p.templatePage() |
|||
-- Argument processing in {{documentation/end box2}}. |
|||
local docpageRoot = (docspace or currentTitle.nsText) .. ':' .. (templatePage or currentTitle.text) |
|||
local docpage |
|||
if docname then |
|||
docpage = docname |
|||
else |
|||
docpage = docpageRoot .. '/doc' |
|||
end |
|||
local docTitle = mw.title.new(docpage) |
|||
local docExist = docTitle.exists |
|||
local docnameFed = args[1] and true |
|||
local sandbox = docpageRoot .. '/sandbox' |
|||
local testcases = docpageRoot .. '/testcases' |
|||
templatePage = currentTitle.nsText .. ':' .. templatePage |
|||
-- Output from {{documentation/end box}} |
|||
-- First, 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. |
|||
if linkBox == 'off' or not (docExist or subjectSpace == 2 or subjectSpace == 828 or subjectSpace == 10) then |
|||
return nil |
|||
end |
|||
-- Assemble the arguments for {{fmbox}}. |
|||
local fmargs = {} |
|||
fmargs.id = 'documentation-meta-data' |
|||
fmargs.image = 'none' |
|||
fmargs.style = 'background-color: #ecfcf4' |
|||
fmargs.textstyle = 'font-style: italic;' |
|||
-- Assemble the fmbox text field. |
|||
local text = '' |
|||
if linkBox then |
|||
-- Use custom link box content if it is defined. |
|||
text = text .. linkBox |
|||
else |
|||
if docExist then |
|||
-- /doc exists; link to it. |
|||
local docLink = makeWikilink(docpage) |
|||
local editLink = makeUrlLink(docTitle:fullUrl{action = 'edit'}, 'edit') |
|||
local historyLink = makeUrlLink(docTitle:fullUrl{action = 'history'}, 'history') |
|||
text = text .. 'The above [[Wikipedia:Template documentation|documentation]] is [[Wikipedia:Transclusion|transcluded]] from ' .. docLink .. '.' |
|||
.. ' <small style="font-style: normal;">(' .. editLink .. ' | ' .. historyLink .. ')</small> <br />' |
|||
elseif subjectSpace == 828 then |
|||
-- /doc does not exist; ask to create it. |
|||
local createLink = makeUrlLink(docTitle:fullUrl{action = 'edit', preload = 'Template:Documentation/preload-module-doc'}, 'create') |
|||
text = text .. 'You might want to ' .. createLink .. ' a documentation page for this [[Wikipedia:Lua|Scribunto module]].<br />' |
|||
end |
|||
-- Add links to /sandbox and /testcases when appropriate. |
|||
if subjectSpace == 2 or subjectSpace == 828 or subjectSpace == 10 then |
|||
-- We are in the user, module or template namespaces. |
|||
local pagePossessive = subjectSpace == 828 and "module's" or "template's" |
|||
text = text .. 'Editors can experiment in this ' .. pagePossessive .. ' ' |
|||
local sandboxTitle = mw.title.new(sandbox) |
|||
if sandboxTitle.exists then |
|||
local sandboxLink = makeWikilink(sandbox, 'sandbox') |
|||
local sandboxEditLink = makeUrlLink(sandboxTitle:fullUrl{action = 'edit'}, 'edit') |
|||
local compareLink = makeUrlLink(mw.title.new('Special:ComparePages'):fullUrl{page1 = mw.uri.encode(templatePage), page2 = mw.uri.encode(sandbox)}, 'diff') |
|||
text = text .. sandboxLink .. ' <small style="font-style: normal">(' .. sandboxEditLink .. ' | ' .. compareLink .. ')</small>' |
|||
else |
|||
local sandboxPreload = 'Template:Documentation/preload-' .. (subjectSpace == 828 and 'module-' or '') .. 'sandbox' |
|||
local sandboxCreateLink = makeUrlLink(sandboxTitle:fullUrl{action = 'edit', preload = sandboxPreload}, 'create') |
|||
local mirrorPreload = mw.uri.encode(templatePage) |
|||
local mirrorSummary = mw.uri.encode('Create sandbox version of ' .. makeWikilink(templatePage)) |
|||
local mirrorLink = makeUrlLink(sandboxTitle:fullUrl{action = 'edit', preload = mirrorPreload, summary = mirrorSummary}, 'mirror') |
|||
text = text .. 'sandbox <small style="font-style: normal">(' .. sandboxCreateLink .. ' | ' .. mirrorLink .. ')</small>' |
|||
end |
|||
text = text .. ' and ' |
|||
local testcaseTitle = mw.title.new(testcases) |
|||
if testcaseTitle.exists then |
|||
local testcasesLink = makeWikilink(testcases, 'testcases') |
|||
local testcasesEditLink = makeUrlLink(testcaseTitle:fullUrl{action = 'edit'}, 'edit') |
|||
text = text .. testcasesLink .. ' <small style="font-style: normal">(' .. testcasesEditLink .. ')</small>' |
|||
else |
|||
local testcasesPreload = 'Template:Documentation/preload-' .. (subjectSpace == 828 and 'module-' or '') .. 'testcases' |
|||
local testcasesCreateLink = makeUrlLink(testcaseTitle:fullUrl{action = 'edit', preload = testcasesPreload}, 'create') |
|||
text = text .. 'testcases <small style="font-style: normal">(' .. testcasesCreateLink .. ')</small>' |
|||
end |
|||
text = text .. ' pages. <br />' |
|||
-- Show the categories text, but not if "content" fed or "docname fed" since then it is unclear where to add the categories. |
|||
if not content and not docnameFed then |
|||
text = text .. 'Please add categories to the ' .. makeWikilink(docpage, '/doc') .. ' subpage.' |
|||
end |
|||
-- Show the "subpages" link. |
|||
if subjectSpace == 828 then -- Module space. |
|||
text = text .. ' ' .. makeWikilink('Special:PrefixIndex/' .. templatePage .. '/', 'Subpages of this module') |
|||
elseif subjectSpace == 10 then -- Template space. |
|||
text = text .. ' ' .. makeWikilink('Special:PrefixIndex/' .. templatePage .. '/', 'Subpages of this template') |
|||
elseif subjectSpace ~= 6 then -- Don't show the link in file space. |
|||
text = text .. ' ' .. makeWikilink('Special:PrefixIndex/' .. templatePage .. '/', 'Subpages of this page') |
|||
end |
|||
-- Show the "print" link if it exists. |
|||
local printPage = templatePage .. '/Print' |
|||
local printTitle = mw.title.new(printPage) |
|||
if printTitle.exists then |
|||
text = text .. '<br />A [[Help:Books/for experts#Improving the book layout|print version]] of this template exists at ' .. makeWikilink(printPage, '/Print') .. '.' |
|||
.. 'If you make a change to this template, please update the print version as well.[[Category:Templates with print versions]]' |
|||
end |
|||
end |
|||
end |
|||
fmargs.text = text |
|||
-- Return the fmbox output. |
|||
return messageBox.main('fmbox', fmargs) |
|||
end |
|||
function p.addTrackingCategories() |
|||
-- Check if {{documentation}} is transcluded on a /doc or /testcases page. |
|||
local ret = '' |
|||
local subpage = currentTitle.subpageText |
|||
if subpage == 'doc' or subpage == 'testcases' then |
|||
local sort = (currentTitle.namespace == 0 and 'Main:' or '') .. currentTitle.prefixedText -- Sort on namespace. |
|||
ret = ret .. makeWikilink('Category:Wikipedia pages with strange ((documentation)) usage', sort) |
|||
end |
|||
return ret |
|||
end |
|||
function p.docspace() |
|||
-- Determines the namespace of the documentation. |
|||
if subjectSpace == 0 or subjectSpace == 6 or subjectSpace == 8 or subjectSpace == 14 then |
|||
-- Pages in the Article, File, MediaWiki or Category namespaces must have their |
|||
-- /doc, /sandbox and /testcases pages in talk space. |
|||
return mw.site.namespaces[subjectSpace].talk.name |
|||
else |
|||
return currentTitle.subjectNsText |
|||
end |
|||
end |
|||
function p.templatePage() |
|||
-- Determines the template page. No namespace or interwiki prefixes are included. |
|||
local subpage = currentTitle.subpageText |
|||
if subpage == 'sandbox' or subpage == 'testcases' then |
|||
return currentTitle.baseText |
|||
else |
|||
return currentTitle.text |
|||
end |
|||
end |
|||
return p |
return p |