Module:Documentation: Difference between revisions
Changed the categories "No/bad doc" and "Doc page" to not be added on user pages, as the former should only be changed by the owner (making the categoryuseless), and the latter is not very relevant to the category anyways |
m 1 revision imported Tags: Mobile edit Mobile web edit |
||
| (123 intermediate revisions by 21 users not shown) | |||
| Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
local | -- Load modules (language wikis exclusive) | ||
local pageType = 'template' | -- ... | ||
-- Customizable strings | |||
local i18n = { | |||
-- default settings, change when necessary | |||
defaultDocPage = 'doc', -- documentation page suffix | |||
defaultSandboxPage = 'sandbox', -- sandbox page suffix | |||
defaultTestCasePage = 'testcases', -- testcases page suffix | |||
defaultPreload = 'Template:Documentation/preload', -- page that stores qualified documentation page contents | |||
defaultStyles = 'Module:Documentation/styles.css', -- stylesheet for this module when using TemplateStyles, remove or set to nil if your wiki not use this | |||
-- format strings, should not be translated | |||
commonInternalLink = '[[%s]]', | |||
commonInternalLinkPipe = '[[%s|%s]]', | |||
commonExternalLink = '[%s]', | |||
commonExternalLinkWithName = '[%s %s]', | |||
commonNamespacedPage = '%s:%s', | |||
commonNamespacedPageWithSub = '%s:%s/%s', | |||
-- namespace names, translate if your language prefers localized namespace name, although remain it untouched most likely not affect anything | |||
namespaceCategory = 'Category', | |||
namespaceSpecial = 'Special', | |||
namespaceUser = 'User', | |||
-- names of special pages, translate if your language prefers localized namespace name, although remain it untouched will still correctly linked to target page | |||
specialPurge = 'Purge', | |||
specialEdit = 'EditPage', | |||
specialHistory = 'PageHistory', | |||
-- translate following types if your language displays differ | |||
pageType_page = 'page', | |||
pageType_template = 'template', | |||
pageType_module = 'module', | |||
pageType_stylesheet = 'stylesheet', | |||
pageType_script = 'script', | |||
pageType_json = 'JSON', | |||
pageType_message = 'message', | |||
-- modify them if your wiki use different style to displaying links | |||
linkBar = '%s', -- format used for whole link bar | |||
linkFormat = mw.text.nowiki( '[' ) .. '%s' .. mw.text.nowiki( ']' ), -- format used for each individual links | |||
linkSeparator = ' ', -- separator between links | |||
-- name of different type of links, change them if necessary | |||
linkTextPurge = mw.message.new( 'smw_purge' ):plain():lower(), | |||
linkTextView = mw.message.new( 'view' ):plain():lower(), | |||
linkTextEdit = mw.message.new( 'edit' ):plain():lower(), | |||
linkTextHistory = mw.message.new( 'history_short' ):plain():lower(), | |||
linkTextCreate = mw.message.new( 'create' ):plain():lower(), | |||
-- strings used in p.create(): contents shown when using {{docc}} or {{subst:docc}} | |||
createOutputFormat = '%s%s', -- overall format | |||
createSplitDocPagePrompt = '\n<!-- Put categories/interwikis on the documentation page -->', -- this string is shown when a separate documentation page is created | |||
createNoSubstCategory = 'Pages with templates requiring substitution', -- tracking category for using {{docc}} without substitution | |||
-- strings used in p.docPage(): contents shown in documentation page | |||
docPagePrompt = 'This is the documentation page. It %s transcluded into %s. See [[Template:Documentation]] for more information.', -- message shown as documentation header in documentation pages. Params: word used when page is a module or not; code page's type | |||
docPagePromptWill = 'is', -- word used when code page is a module page | |||
docPagePromptShould = 'should be', -- word used when code is not a module page | |||
docPageBadDocPrompt = "<br>'''This %s's documentation needs improving or additional information.'''", -- additional message if a documentation page marked as baddoc | |||
docPageCategory = 'Documentation pages', -- tracking category for documentation pages | |||
-- strings used in p.page(): contents shown in code page | |||
pageNoDocPrompt = "'''This %s has no documentation. If you know how to use this %s, please create it.'''", -- message shown when a separate documentation page is not exist, both parameters refers to page type | |||
pageNoDocCategory = '%ss with no documentation', -- tracking category for pages without documentation, parameters refers to page type | |||
pageNoDocCategoryDefault = 'Pages with no documentation', -- fallback tracking category for pages without documentation | |||
pageBadDocPrompt = "'''This %s's documentation needs improving or additional information.'''\n", -- message shown when a documentation page marked as baddoc, both parameters refers to page type | |||
pageBadDocCategory = '%ss with bad documentation', -- tracking category for pages marked as baddoc, parameters refers to page type | |||
pageBadDocCategoryDefault = 'Pages with bad documentation', -- fallback tracking category for pages marked as baddoc | |||
pageDocHeaderTitle = 'Documentation', -- message shown as the title of the documentation header | |||
pageDocJumpToCode = 'Jump to code ↴', -- text of the link to jump to the code | |||
pageDocHeaderBottom = 'The above documentation is transcluded from %s.', -- message shown as the bottom line of the documentation header | |||
} | |||
-- Customizable functions | |||
local function pageCategoryHandler( category ) | |||
return mw.getCurrentFrame():expandTemplate{ title = 'translation category', args = { category, project = '0' } } | |||
end | |||
-- Load modules | |||
local loadStyles = require( 'Module:TSLoader' ).call | |||
local static = require( 'Module:Static' ) | |||
if not static.Documentation then | |||
static.Documentation = {} | |||
end | |||
-- Internal functions | |||
local function getType( namespace, page ) | |||
local pageType = 'page' | |||
if namespace == 'Template' then | |||
pageType = 'template' | |||
elseif namespace == 'Module' then | |||
pageType = 'module' | pageType = 'module' | ||
elseif page.fullText:gsub( '/ | elseif page.fullText:gsub( '/' .. i18n.defaultDocPage .. '$', '' ):find( '%.css$' ) then | ||
pageType = 'stylesheet' | pageType = 'stylesheet' | ||
elseif page.fullText:gsub( '/ | elseif page.fullText:gsub( '/' .. i18n.defaultDocPage .. '$', '' ):find( '%.js$' ) then | ||
pageType = 'script' | pageType = 'script' | ||
elseif page.fullText:gsub( '/' .. i18n.defaultDocPage .. '$', '' ):find( '%.json$' ) then | |||
pageType = 'json' | |||
elseif namespace == 'MediaWiki' then | elseif namespace == 'MediaWiki' then | ||
pageType = 'message' | pageType = 'message' | ||
end | end | ||
return pageType | return pageType | ||
end | end | ||
-- Creating a documentation page or | local function getDisplayType( pageType ) | ||
return i18n[ 'pageType_' .. pageType ] or i18n.pageType_page | |||
end | |||
-- Exported functions | |||
function p.create( f ) -- Creating a documentation page or transclusion through {{subst:docc}} | |||
local args = require( 'Module:ProcessArgs' ).norm() | local args = require( 'Module:ProcessArgs' ).norm() | ||
local page = mw.title.getCurrentTitle() | local page = mw.title.getCurrentTitle() | ||
local docPage = args.page or page.nsText | local docPage = args.page or i18n.commonNamespacedPageWithSub:format( page.nsText, page.baseText, i18n.defaultDocPage ) | ||
local out | local out | ||
if not args.content and tostring( page ) == docPage then | if not args.content and tostring( page ) == docPage then | ||
out = f:preprocess( | local pageType = mw.ustring.lower( args.type or getType( page.nsText, page ) ) | ||
local pageTypeDisplay = getDisplayType( pageType ) | |||
out = f:preprocess( mw.title.new( i18n.defaultPreload ):getContent():gsub( '$1' , pageTypeDisplay ) ) | |||
else | else | ||
local templateArgs = {} | local templateArgs = {} | ||
for _, key in ipairs{ 'type', 'page', 'content' } do | for _, key in ipairs{ 'type', 'page', 'content', 'nodoc', 'baddoc' } do | ||
local val = args[key] | local val = args[ key ] | ||
if val then | if val then | ||
if key == 'content' then val = '\n' .. val .. '\n' end | if key == 'content' then val = '\n' .. val .. '\n' end | ||
| Line 34: | Line 132: | ||
end | end | ||
end | end | ||
out = '{{documentation|' .. table.concat( templateArgs, '|' ) .. '}}' | out = '{{documentation|' .. table.concat( templateArgs, '|' ) .. '}}' | ||
out = out:gsub( '|}}', '}}' ) | out = out:gsub( '|}}', '}}' ) | ||
out = i18n.createOutputFormat:format( out, args.content and '' or i18n.createSplitDocPagePrompt ) | |||
end | end | ||
if not mw.isSubsting() then | if not mw.isSubsting() then | ||
out = f:preprocess( out ) | out = f:preprocess( out ) | ||
if not args.nocat then | if not args.nocat then | ||
out = out .. | out = out .. i18n.commonInternalLink:format( i18n.commonNamespacedPage:format( i18n.namespaceCategory, i18n.createNoSubstCategory ) ) | ||
end | end | ||
end | end | ||
return out | return out | ||
end | end | ||
-- Header on the documentation page | function p.docPage( f ) -- Header on the documentation page | ||
local args = require( 'Module:ProcessArgs' ).merge( true ) | local args = require( 'Module:ProcessArgs' ).merge( true ) | ||
local badDoc = args.baddoc | local badDoc = args.baddoc | ||
if | |||
if badDoc then | |||
static.Documentation.badDoc = '1' | |||
end | end | ||
local page = mw.title.getCurrentTitle() | local page = mw.title.getCurrentTitle() | ||
local subpage = page.subpageText | |||
if subpage == i18n.defaultSandboxPage or subpage == i18n.defaultTestCasePage then | |||
page = page.basePageTitle | |||
end | |||
local docPage = mw.title.new( args.page or i18n.commonNamespacedPageWithSub:format( page.nsText, page.baseText, i18n.defaultDocPage ) ) | |||
if docPage ~= page then return end | |||
local namespace = page.nsText | local namespace = page.nsText | ||
local pageType = mw.ustring.lower( args.type or getType( namespace, page ) ) | local pageType = mw.ustring.lower( args.type or getType( namespace, page ) ) | ||
local pageTypeDisplay = getDisplayType( pageType ) | |||
local body = mw.html.create( 'div' ) | |||
local body = mw.html.create( 'div' ):addClass( 'documentation' ) | |||
body | body | ||
: | :addClass( badDoc and 'documentation-badDoc' or '' ) | ||
:tag( 'div' ):addClass( 'documentation-header-tools' ) | |||
:wikitext( i18n.linkBar:format( i18n.linkFormat:format( i18n.commonInternalLinkPipe:format( i18n.commonNamespacedPageWithSub:format( i18n.namespaceSpecial, i18n.specialPurge, page.fullText ), i18n.linkTextPurge ) ) ) ) | |||
:tag( 'div' ) | |||
:wikitext( | |||
:done() | :done() | ||
:wikitext( | :wikitext( i18n.docPagePrompt:format( pageType == 'module' and i18n.docPagePromptWill or i18n.docPagePromptShould, i18n.commonInternalLink:format( i18n.commonNamespacedPage:format( namespace, page.baseText ) ) ) ) | ||
if badDoc then | if badDoc then | ||
body:wikitext( | body:wikitext( i18n.docPageBadDocPrompt:format( pageTypeDisplay ) ) | ||
end | end | ||
if not ( args.nocat or namespace == | if not ( args.nocat or namespace == i18n.namespaceUser ) then | ||
body:wikitext( | body:wikitext( i18n.commonInternalLink:format( i18n.commonNamespacedPage:format( i18n.namespaceCategory, i18n.docPageCategory ) ) ) | ||
end | end | ||
return body | return loadStyles( i18n.defaultStyles ) .. tostring( body ) | ||
end | end | ||
-- Wrapper around the documentation on the main page | function p.page( f ) -- Wrapper around the documentation on the main page | ||
function | -- mw.text.trim uses mw.ustring.gsub, which silently fails on large strings | ||
local function trim( s ) | |||
return ( s:gsub( '^[\t\r\n\f ]+', '' ):gsub( '[\t\r\n\f ]+$', '' ) ) | |||
--return string.gsub( s, '^[\t\r\n\f ]*(.-)[\t\r\n\f ]*$', '%1' ) | |||
end | |||
local args = require( 'Module:ProcessArgs' ).merge( true ) | local args = require( 'Module:ProcessArgs' ).merge( true ) | ||
local page = mw.title.getCurrentTitle() | local page = mw.title.getCurrentTitle() | ||
local subpage = page.subpageText | |||
if subpage == i18n.defaultSandboxPage or subpage == i18n.defaultTestCasePage then | |||
page = page.basePageTitle | |||
end | |||
local namespace = page.nsText | local namespace = page.nsText | ||
local docText = | local docText = trim( args.content or '' ) | ||
if docText == '' then docText = nil end | if docText == '' then docText = nil end | ||
local docPage | local docPage | ||
local noDoc | local noDoc | ||
| Line 109: | Line 207: | ||
docPage = page | docPage = page | ||
else | else | ||
docPage = mw.title.new( args.page or | docPage = mw.title.new( args.page or i18n.commonNamespacedPageWithSub:format( namespace, page.text, i18n.defaultDocPage ) ) | ||
noDoc = args.nodoc or not docPage.exists | noDoc = args.nodoc or not docPage.exists | ||
end | end | ||
local badDoc = args.baddoc | local badDoc = args.baddoc | ||
local pageType = mw.ustring.lower( args.type or getType( namespace, page ) ) | local pageType = mw.ustring.lower( args.type or getType( namespace, page ) ) | ||
local pageTypeDisplay = getDisplayType( pageType ) | |||
if not docText and not noDoc then | if not docText and not noDoc then | ||
docText = trim( f:expandTemplate{ title = ':' .. docPage.fullText } ) | |||
docText = | if static.Documentation.badDoc and static.Documentation.badDoc == '1' then | ||
if | |||
badDoc = 1 | badDoc = 1 | ||
end | end | ||
if docText == '' then | if docText == '' then | ||
docText = nil | docText = nil | ||
| Line 130: | Line 228: | ||
docText = '\n' .. docText .. '\n' | docText = '\n' .. docText .. '\n' | ||
end | end | ||
local docClass = '' | |||
local | |||
local message | local message | ||
local category | local category | ||
if noDoc then | if noDoc then | ||
docClass = 'documentation-noDoc' | |||
message = i18n.pageNoDocPrompt:format( pageTypeDisplay, pageTypeDisplay ) | |||
if not ( args.nocat or namespace == i18n.namespaceUser ) then | |||
message = | category = i18n.pageNoDocCategory:format( pageTypeDisplay ) | ||
if not mw.title.new( i18n.commonNamespacedPage:format( i18n.namespaceCategory, category ) ).exists then | |||
if not ( args.nocat or namespace == | category = i18n.pageNoDocCategoryDefault | ||
category = | |||
if not mw.title.new( category ).exists then | |||
category = | |||
end | end | ||
end | end | ||
elseif badDoc then | elseif badDoc then | ||
docClass = 'documentation-badDoc' | |||
message = | message = i18n.pageBadDocPrompt:format( pageTypeDisplay ) | ||
if not ( args.nocat or namespace == | if not ( args.nocat or namespace == i18n.namespaceUser ) then | ||
category = | category = i18n.pageBadDocCategory:format( pageTypeDisplay ) | ||
if not mw.title.new( category ).exists then | if not mw.title.new( i18n.commonNamespacedPage:format( i18n.namespaceCategory, category ) ).exists then | ||
category = | category = i18n.pageBadDocCategoryDefault | ||
end | end | ||
end | end | ||
end | end | ||
local links = | -- Generates the link bar | ||
local links = mw.html.create( 'span' ):addClass( 'documentation-header-tools' ) | |||
} | local linkList = {} | ||
if not noDoc | if not noDoc then | ||
table.insert( | if page ~= docPage then | ||
table.insert( linkList, i18n.linkFormat:format( i18n.commonInternalLinkPipe:format( docPage.fullText, i18n.linkTextView ) ) ) | |||
end | |||
table.insert( linkList, i18n.linkFormat:format( i18n.commonInternalLinkPipe:format( i18n.commonNamespacedPageWithSub:format( i18n.namespaceSpecial, i18n.specialEdit, docPage.fullText ), i18n.linkTextEdit ) ) ) | |||
table.insert( linkList, i18n.linkFormat:format( i18n.commonInternalLinkPipe:format( i18n.commonNamespacedPageWithSub:format( i18n.namespaceSpecial, i18n.specialHistory, docPage.fullText ), i18n.linkTextHistory ) ) ) | |||
else | |||
table.insert( linkList, i18n.linkFormat:format( i18n.commonExternalLinkWithName:format( docPage:canonicalUrl{ action = 'edit', preload = i18n.defaultPreload, preloadparams = pageTypeDisplay }, i18n.linkTextCreate ) ) ) | |||
end | end | ||
table.insert( linkList, i18n.linkFormat:format( i18n.commonInternalLinkPipe:format( i18n.commonNamespacedPageWithSub:format( i18n.namespaceSpecial, i18n.specialPurge, docPage.fullText ), i18n.linkTextPurge ) ) ) | |||
links:wikitext( i18n.linkBar:format( table.concat( linkList, i18n.linkSeparator ) ) ) | |||
local body = mw.html.create( 'div' ):addClass( 'documentation' ) | |||
local body = mw.html.create( 'div' ) | body | ||
:addClass( docClass ) | |||
local header = mw.html.create( 'div' ) | local header = mw.html.create( 'div' ) | ||
: | :addClass( 'documentation-header-top' ) | ||
header | header | ||
:tag( 'span' ) | :tag( 'span' ) | ||
: | :addClass( 'documentation-header-title' ) | ||
:wikitext( i18n.pageDocHeaderTitle ) | |||
header | |||
:node( links ) | |||
local codePages = { | |||
module = true, | |||
stylesheet = true, | |||
if not noDoc and pageType | script = true, | ||
} | |||
if not noDoc and codePages[ pageType ] then | |||
header | header | ||
:tag( 'span' ) | :tag( 'span' ) | ||
: | :attr( 'id', 'documentation-jump-to-code' ) | ||
:wikitext( ' | :wikitext( i18n.commonInternalLinkPipe:format( '#the-code', i18n.pageDocJumpToCode ) ) | ||
end | end | ||
body | body | ||
:node( header ):done() | :node( header ):done() | ||
:wikitext( message ) | :wikitext( message ) | ||
:wikitext( docText ) | :wikitext( docText ) | ||
if not noDoc and page ~= docPage then | if not noDoc and page ~= docPage then | ||
body | body | ||
:tag( 'div' ) | :tag( 'div' ) | ||
: | :addClass( 'documentation-header-bottom' ) | ||
:node( links ) | :node( links ) | ||
:wikitext( | :wikitext( i18n.pageDocHeaderBottom:format( i18n.commonInternalLink:format( docPage.fullText ) ) ) | ||
end | end | ||
if category then | if category then | ||
body:wikitext( | body:wikitext( pageCategoryHandler( category ) ) | ||
end | end | ||
local anchor = '' | local anchor = '' | ||
if not noDoc and pageType ~= 'template' and pageType ~= 'message' then | if not noDoc and pageType ~= 'template' and pageType ~= 'message' then | ||
anchor = mw.html.create( 'div' ):attr( 'id', 'the-code' ) | anchor = mw.html.create( 'div' ):attr( 'id', 'the-code' ) | ||
end | end | ||
return tostring( body ) .. tostring( anchor ) | return loadStyles( i18n.defaultStyles ) .. tostring( body ) .. tostring( anchor ) | ||
end | end | ||
return p | return p | ||