Module:documentation
Appearance
Documentation for this module may be created at Module:documentation/doc
local export = {}
-- it is either here, or in [[Module:ugly hacks]], and it is not in ugly hacks.
function export.CONTENTMODEL()
return mw.title.getCurrentTitle().contentModel
end
local skins = {
["common" ] = "";
["vector" ] = "Vector";
["monobook" ] = "Monobook";
["cologneblue"] = "Cologne Blue";
["modern" ] = "Modern";
}
local Array = require "Module:array"
local function link_lang_cat(lang)
return ("[[:Category:%s|%s]]")
:format(lang:getCategoryName(), lang:getCanonicalName())
end
local function compare_pages(page1, page2, text)
return "[" .. tostring(
mw.uri.fullUrl("Special:ComparePages", "page1=" .. page1 .. "&page2=" .. page2))
.. " " .. text .. "]"
end
local function page_exists(title)
local success, title_obj = pcall(mw.title.new, title)
return success and title_obj.exists
end
local langs = require "Module:languages/cache"
local function zh_link(word)
return require("Module:links").full_link{
lang = langs.zh,
term = word
}
end
local function make_zh_data_documentation(title, cats)
local output = Array()
local zh_data_subpage, lang_code, reconstruction, character =
mw.ustring.match(title.fullText,
"^Module:zh/data/((%l%l%l)%-pron%-?([^/]-))/(.+)$")
if zh_data_subpage == "ltc-pron" or zh_data_subpage == "och-pron-BS"
or zh_data_subpage == "och-pron-ZS" then
require('Module:zh-track').track_data_module(title.fullText)
local lang = langs[lang_code]
output:insert(('This module contains data on the pronunciation of %s')
:format(zh_link(character)))
local see_also_link
if reconstruction == "BS" then
see_also_link = 'Wiktionary:About Proto-Sino-Tibetan#Reconstruction by Baxter-Sagart (2014)'
elseif reconstruction == "ZS" then
see_also_link = 'Wiktionary:About Proto-Sino-Tibetan#Reconstruction by Zhengzhang (2003)'
else
reconstruction = nil
end
local lang_link = link_lang_cat(lang)
if reconstruction then
output:insert(("in the reconstruction of %s by %s.")
:format(lang_link, reconstruction == "BS" and "Baxter-Sagart" or "Zhengzhang"))
else
output:insert(("in %s."):format(lang_link))
end
if see_also_link then
output:insert("See " .. require("Module:links").section_link(see_also_link)
.. " for more information.")
end
return output:concat(" ")
end
end
local function make_zh_dial_or_syn_documentation(title, cats)
local type_of_data, character = title.fullText:match("^Module:zh/data/dial%-(%l+)/(.+)$")
if character then
local what, where
if type_of_data == "pron" then
what = "the pronunciation"
where = "dialects"
elseif type_of_data == "syn" then
what = "synonyms"
where = "dialects and varieties"
end
if what then
return ("This module contains data on %s of %s in %s of Chinese.")
:format(what, zh_link(character), where)
end
end
end
local function make_zh_glyph_data_documentation(title, cats)
local character = title.fullText:match("^Module:zh/data/glyph%-data/(.+)")
if character then
return ("This module contains data on historical forms of the Chinese character %s.")
:format(zh_link(character))
end
end
local function make_accel_documentation(title, cats)
local doc_content
local lang_code = title.subpageText
local lang = langs[lang_code]
if lang then
cats:insert(lang:getCanonicalName() .. " modules|accel")
cats:insert(("Accel submodules|%s"):format(lang:getCanonicalName()))
return ("This module contains new entry creation rules for %s; see [[WT:ACCEL]].")
:format(link_lang_cat(lang))
end
return doc_content
end
local function make_Unicode_data_documentation(title, cats)
local subpage, first_three_of_code_point
= title.fullText:match("^Module:Unicode data/([^/]+)/(%x%x%x)$")
if subpage == "names" or subpage == "images" then
local low, high =
tonumber(first_three_of_code_point .. "000", 16),
tonumber(first_three_of_code_point .. "FFF", 16)
return string.format(
"This data module contains the %s of " ..
"[[Appendix:Unicode|Unicode]] code points within the range U+%04X to U+%04X.",
subpage == "images" and "titles of images" or "names",
low, high)
end
end
-- This provides categories and documentation for various data modules, so that
-- [[Category:Uncategorized modules]] isn't unnecessarily cluttered.
local module_regex = {
["^Module:languages/.+$"] = "Modules dealing with languages and scripts",
["^Module:scripts/.+$"] = "Modules dealing with languages and scripts",
["^Module:data tables/data..?.?.?$"] = "Reference module sharded data tables",
["^Module:Quotations/...?.?.?.?.?.?$"] = "Quotation data modules",
-- capture submodules of zh/data that do not end with a hanzi in the title
["^Module:zh/data/.+[a-zA-z0-9]$"] = "Chinese data modules",
["^Module:zh/data/dial%-pron/.+"] = {
cat = "Chinese dialectal pronunciation data modules",
doc = make_zh_dial_or_syn_documentation,
},
["^Module:zh/data/dial%-syn/.+"] = {
cat = "Chinese dialectal synonyms data modules",
doc = make_zh_dial_or_syn_documentation,
},
["^Module:zh/data/glyph%-data/.+"] = {
cat = "Chinese historical character forms data modules",
doc = make_zh_glyph_data_documentation,
},
["^Module:zh/data/ltc%-pron/.+"] = {
cat = "Middle Chinese pronunciation data modules",
doc = make_zh_data_documentation,
},
["^Module:zh/data/och%-pron%-BS/.+"] = {
cat = "Old Chinese (Baxter-Sagart) pronunciation data modules",
doc = make_zh_data_documentation,
},
["^Module:zh/data/och%-pron%-ZS/.+"] = {
cat = "Old Chinese (Zhengzhang) pronunciation data modules",
doc = make_zh_data_documentation,
},
["^Module:mul/guoxue%-data/cjk%-?(.*)"] = {
cat = nil,
doc = function (title, cats)
local suffix = title.fullText:match("^Module:mul/guoxue%-data/cjk%-?(.*)$")
local block
if suffix == "" then
block = "CJK Unified Ideographs"
elseif suffix:find("^%l$") then
block = "CJK Unified Ideographs Extension " .. suffix:upper()
elseif suffix == "compat" then
block = "CJK Compatibility Ideographs"
elseif suffix == "compat-sup" then
block = "CJK Compatibility Ideographs Supplement"
else
mw.log("Unicode block for " .. title.fullText " not found.")
return
end
local block_link = ("[[Appendix:Unicode/%s|%s]]"):format(block, block)
local start, ending = require("Module:Unicode data").get_block_range(block)
if not start then
mw.log("Code point range for the Unicode block " .. tostring(block) .. " not found.")
return
end
local sortkey = "|guoxue, " .. suffix
cats:insert("Data modules" .. sortkey)
cats:insert("Han script" .. sortkey)
cats:insert("Translingual modules" .. sortkey)
return ("This module contains data on CJK characters in "
.. "the Unicode block %s (U+%04X–U+%04X) from [https://guoxuedashi.com guoxuedashi.com].")
:format(block_link, start, ending)
end,
},
["^Module:Unicode data/(.+)"] = {
cat = "Unicode data modules|%1",
doc = make_Unicode_data_documentation,
},
["^Module:number list/data/(.+)"] = {
cat = nil,
doc = function (title, cats)
local lang_code = title.fullText:match("^Module:number list/data/(.+)")
local lang = langs[lang_code]
if lang then
local canonical_name = lang:getCanonicalName()
local language_data_modules = canonical_name .. " data modules"
cats:insert((page_exists("Category:" .. language_data_modules)
and language_data_modules or canonical_name .. " modules")
.. "|number list")
cats:insert("Number data modules|" .. canonical_name)
return ("This module contains data on various types of numbers in %s.")
:format(link_lang_cat(lang))
end
end,
},
["^Module:es%-conj/data/(.+)"] = "Spanish data modules|%1",
["^Module:accel/(.+)$"] = {
cat = nil,
doc = make_accel_documentation,
},
["^Module:inc%-ash.+$"] = {
cat = "Ashokan Prakrit modules",
doc = function (title, cats)
local word = title.fullText:match("^Module:inc%-ash/dial/data/(.+)$")
if word then
local lang = langs["inc-ash"]
return ("This module contains data on the pronunciation of %s in dialects of %s.")
:format(require("Module:links").full_link({ term = word, lang = lang }, "term"),
link_lang_cat(lang))
end
end,
},
["^Module:[%l-]+:Dialects$"] = {
cat = nil,
doc = function (title, cats)
local content = title:getContent()
local has_aliases = content:find("aliases") and true or false
return mw.getCurrentFrame():expandTemplate {
title = "dialectal data module",
args = { ["labels-aliases"] = has_aliases },
}
end,
},
["^.+%-translit$"] = {
cat = nil,
doc = function (title, cats)
-- Check that the title begins in a language or script code.
-- If so, expand {{translit module documentation}} with that code
-- as the first parameter.
local code = title.text:match("^([%l-]+)-")
if not (code and require("Module:languages").getByCode(code)) then
code = title.text:match("^(%u%l%l%l)%-")
if not require("Module:scripts").getByCode(code) then
return
end
end
return mw.getCurrentFrame():expandTemplate {
title = "translit module documentation",
args = { code },
}
end,
},
}
function export.show(frame)
local params = {
["hr"] = {},
["for"] = {},
["from"] = {},
["notsubpage"] = { type = "boolean", default = false },
["nodoc"] = { type = "boolean", default = false },
}
local args = require("Module:parameters").process(frame.args, params)
local output = Array('\n<div class="documentation" style="display:block; clear:both">\n')
local cats = Array()
local nodoc = args.nodoc
if (not args.hr) or (args.hr == "above") then
output:insert("----\n")
end
local title = ((args['for'] ~= "") and args['for']) and mw.title.new(args['for'])
or mw.title.getCurrentTitle()
local doc_title = mw.title.new((args['from'] ~= "") and args['from']
or (title.fullText .. '/documentation'))
local contentModel = title.contentModel
local pagetype = mw.getContentLanguage():lcfirst(title.nsText) .. " page"
local preload, fallback_docs, doc_content, old_doc_title, user_name,
skin_name, needs_doc
if contentModel == "javascript" then
pagetype = "script"
preload = 'Template:documentation/preloadTemplate' -- XXX
if title.nsText == 'User' then
user_name = title.rootText
end
elseif contentModel == "css" then
pagetype = "style sheet"
preload = 'Template:documentation/preloadTemplate' -- XXX
if title.nsText == 'User' then
user_name = title.rootText
end
elseif contentModel == "Scribunto" then
pagetype = "module"
user_name = title.rootText:match("^[Uu]ser:(.+)")
if user_name then
preload = 'Template:documentation/preloadModuleSandbox'
else
preload = 'Template:documentation/preloadModule'
end
elseif title.nsText == "Template" then
pagetype = "template"
preload = 'Template:documentation/preloadTemplate'
elseif title.nsText == "Wiktionary" then
pagetype = "project page"
preload = 'Template:documentation/preloadTemplate' -- XXX
end
if doc_title.isRedirect then
old_doc_title = doc_title
doc_title = mw.title.new(string.match(doc_title:getContent(),
"^#[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]%s*:?%s*%[%[([^%[%]]-)%]%]"))
end
output:insert("<dl class=\"plainlinks\" style=\"font-size: smaller;\">")
if doc_title.exists then
output:insert(
"<dd><i style=\"font-size: larger;\">The following " ..
"[[Help:Documenting templates and modules|documentation]] is located at [[" ..
doc_title.fullText .. "]]. " ..
"<sup>[[" .. doc_title:fullUrl { action = 'edit' } .. " edit]]</sup> </i></dd>")
else
if contentModel == "Scribunto" then
local automatic_cat
if user_name then
fallback_docs = 'documentation/fallback/user module'
automatic_cat = "User sandbox modules"
else
for r, data in pairs(module_regex) do
if mw.ustring.find(title.fullText, r) then
local cat
if type(data) == "table" then
doc_content = data.doc(title, cats)
cat = data.cat
else
cat = data
end
if cat then
automatic_cat = mw.ustring.gsub(title.fullText, r, cat)
-- If the documentation function (cat.doc) manages to
-- generate documentation, it should add a category.
elseif doc_content then
automatic_cat = nil
end
break
end
end
end
if not automatic_cat then
local success, auto_cats =
pcall(require("Module:module categorization").categorize, frame, true)
if success then
for _, category in ipairs(auto_cats) do
cats:insert(category)
end
end
end
if title.subpageText == "templates" then
cats:insert("Template interface modules")
end
cats:insert(automatic_cat)
-- meaning module is not in user's sandbox or one of many datamodule boring series
needs_doc = not (automatic_cat or fallback_docs)
elseif title.nsText == "Template" then
--cats:insert("Uncategorized templates")
needs_doc = not (fallback_docs or nodoc)
elseif (contentModel == "css") or (contentModel == "javascript") then
if user_name then
skin_name = skins[title.text:sub(#title.rootText + 1):match("^/([a-z]+)%.[jc]ss?$")]
if skin_name then
fallback_docs = 'documentation/fallback/user ' .. contentModel
end
end
end
if doc_content then
output:insert(
"<dd><i style=\"font-size: larger;\">The following " ..
"[[Help:Documenting templates and modules|documentation]] is " ..
"generated by [[Module:documentation]]. <sup>[[" ..
mw.title.new("Module:documentation"):fullUrl { action = 'edit' } ..
" edit]]</sup> </i></dd>")
elseif not nodoc then
output:insert(
"<dd><i style=\"font-size: larger;\">This " .. pagetype ..
" lacks a [[Help:Documenting templates and modules|documentation subpage]]. " ..
(fallback_docs and "You may " or "Please ") ..
"[" .. doc_title:fullUrl { action = 'edit', preload = preload }
.. " create it].</i></dd>\n")
end
end
if title.fullText:match("^MediaWiki:Gadget%-") then
local is_gadget = false
local gadget_list = mw.title.new("MediaWiki:Gadgets-definition"):getContent()
for line in mw.text.gsplit(gadget_list, "\n") do
local gadget, opts, items = line:match("^%*%s*([A-Za-z][A-Za-z0-9_%-]*)%[(.-)%]|(.+)$") -- opts is unused
if not gadget then
gadget, items = line:match("^%*%s*([A-Za-z][A-Za-z0-9_%-]*)|(.+)$")
end
if gadget then
items = Array(mw.text.split(items, "|"))
for i, item in ipairs(items) do
if title.fullText == ("MediaWiki:Gadget-" .. item) then
is_gadget = true
output:insert("<dd> ''This script is a part of the <code>")
output:insert(gadget)
output:insert("</code> gadget ([")
output:insert(tostring(mw.uri.fullUrl('MediaWiki:Gadgets-definition', 'action=edit')))
output:insert(" edit definitions])'' <dl>")
output:insert("<dd> ''Description ([")
output:insert(tostring(mw.uri.fullUrl('MediaWiki:Gadget-' .. gadget, 'action=edit')))
output:insert(" edit])'': ")
output:insert(mw.message.new('Gadget-' .. gadget):plain())
output:insert(" </dd>")
items:remove(i)
if #items > 0 then
for j, item in ipairs(items) do
items[j] = '[[MediaWiki:Gadget-' .. item .. '|' .. item .. ']]'
end
output:insert("<dd> ''Other parts'': ")
output:insert(mw.text.listToText(items))
output:insert("</dd>")
end
output:insert("</dl></dd>")
break
end
end
end
end
if not is_gadget then
output:insert("<dd> ''This script is not a part of any [")
output:insert(tostring(mw.uri.fullUrl('Special:Gadgets', 'uselang=en')))
output:insert(' gadget] ([')
output:insert(tostring(mw.uri.fullUrl('MediaWiki:Gadgets-definition', 'action=edit')))
output:insert(' edit definitions]).</dd>')
--else
-- cats:insert("Wiktionary gadgets")
end
end
if old_doc_title then
output:insert("<dd> ''Redirected from'' [")
output:insert(old_doc_title:fullUrl { redirect = 'no' })
output:insert(" ")
output:insert(old_doc_title.fullText)
output:insert("] ([")
output:insert(old_doc_title:fullUrl { action = 'edit' })
output:insert(" edit]).</dd>\n")
end
local links = Array()
if title.isSubpage and not args.notsubpage then
links:insert("[[:" .. title.nsText .. ":" .. title.rootText .. "|root page]]")
links:insert("[[Special:PrefixIndex/" .. title.nsText .. ":" .. title.rootText .. "/|root page's subpages]]")
else
links:insert("[[Special:PrefixIndex/" .. title.fullText .. "/|subpage list]]")
end
if (contentModel == "javascript") or (contentModel == "css") then
links:insert("[[Special:WhatLinksHere/" .. title.fullText .. "|what links here]]")
if user_name then
links:insert("[[Special:MyPage" .. title.text:sub(#title.rootText + 1) .. "|your own]]")
end
else
links:insert(
'[' .. tostring(mw.uri.fullUrl('Special:WhatLinksHere/' .. title.fullText,
'hidelinks=1&hideredirs=1')) .. ' transclusions]')
if contentModel ~= "Scribunto" then
links:insert(
'[' .. tostring(mw.uri.fullUrl('Special:WhatLinksHere/' .. title.fullText,
'hidelinks=1&hidetrans=1')) .. ' redirects]')
end
end
if contentModel == "Scribunto" then
local is_testcases = title.isSubpage and title.subpageText == "testcases"
local without_subpage = title.nsText .. ":" .. title.baseText
if is_testcases then
links:insert("[[:" .. without_subpage .. "|tested module]]")
else
links:insert("[[" .. title.fullText .. "/testcases|testcases]]")
end
if user_name then
links:insert("[[User:" .. user_name .. "|user page]]")
links:insert("[[User talk:" .. user_name .. "|user talk page]]")
links:insert("[[Special:PrefixIndex/User:" .. user_name .. "/|userspace]]")
else
-- If sandbox module, add a link to the module that this is a sandbox of.
-- Exclude user sandbox modules like [[User:Dine2016/sandbox]].
if title.text:find("/sandbox%d*%f[/%z]") then
cats:insert("Sandbox modules")
-- Sandbox modules don't really need documentation.
needs_doc = false
-- Will behave badly if "/sandbox" occurs twice in title!
local sandbox_of = title.fullText:gsub("/sandbox%d*%f[/%z]", "")
local diff
if page_exists(sandbox_of) then
diff = " (" .. compare_pages(title.fullText, sandbox_of, "diff") .. ")"
else
require("Module:debug").track("documentation/no sandbox of")
end
links:insert("[[:" .. sandbox_of .. "|sandbox of]]" .. (diff or ""))
-- If not a sandbox module, add link to sandbox module.
-- Sometimes there are multiple sandboxes for a single module:
-- [[Module:sa-pronunc/sandbox]], [[Module:sa-pronunc/sandbox2]].
-- Occasionally sandbox modules have their own subpages that are also
-- sandboxes: [[Module:grc-decl/sandbox/decl]].
else
local sandbox_title
if title.fullText:find("^Module:grc%-decl/") then
sandbox_title = title.fullText:gsub("^Module:grc%-decl/", "Module:grc-decl/sandbox/")
elseif is_testcases then
sandbox_title = title.fullText:gsub("/testcases", "/sandbox/testcases")
else
sandbox_title = title.fullText .. "/sandbox"
end
local sandbox_link = "[[:" .. sandbox_title .. "|sandbox]]"
local diff
if page_exists(sandbox_title) then
diff = " (" .. compare_pages(title.fullText, sandbox_title, "diff") .. ")"
end
links:insert(sandbox_link .. (diff or ""))
end
end
end
if title.nsText == "Template" then
if title.isSubpage and title.text:find("/sandbox%d*%f[/%z]") then -- This is a sandbox template.
-- At the moment there are no user sandbox templates with subpage
-- "/sandbox".
cats:insert("Sandbox templates")
-- Sandbox templates don't really need documentation.
needs_doc = false
-- Will behave badly if "/sandbox" occurs twice in title!
local sandbox_of = title.fullText:gsub("/sandbox%d*%f[/%z]", "")
local diff
if page_exists(sandbox_of) then
diff = " (" .. compare_pages(title.fullText, sandbox_of, "diff") .. ")"
else
require("Module:debug").track("documentation/no sandbox of")
end
links:insert("[[:" .. sandbox_of .. "|sandbox of]]" .. (diff or ""))
else -- This is a template that can have a sandbox.
local sandbox_title = title.fullText .. "/sandbox"
local diff
if page_exists(sandbox_title) then
diff = " (" .. compare_pages(title.fullText, sandbox_title, "diff") .. ")"
end
links:insert("[[:" .. sandbox_title .. "|sandbox]]" .. (diff or ""))
end
end
if #links > 0 then
output:insert("<dd> ''Useful links'': " .. links:concat(" • ") .. "</dd>")
end
output:insert("</dl>\n")
if doc_title.exists then
-- Override automatic documentation, if present.
doc_content = frame:expandTemplate { title = doc_title.fullText }
elseif not doc_content and fallback_docs then
doc_content = frame:expandTemplate {
title = fallback_docs;
args = {
['user'] = user_name;
['page'] = title.fullText;
['skin name'] = skin_name;
}
}
end
if doc_content then
output:insert(doc_content)
end
output:insert(('\n<%s style="clear: both;" />'):format(args.hr == "below" and "hr" or "br"))
if not cats[1] and not doc_content then
if contentModel == "Scribunto" then
cats:insert("Uncategorized modules")
-- elseif title.nsText == "Template" then
-- cats:insert("Uncategorized templates")
end
end
if needs_doc then
cats:insert("Templates and modules needing documentation")
end
for _, cat in ipairs(cats) do
output:insert("[[Category:" .. cat .. "]]")
end
output:insert("</div>\n")
return output:concat()
end
-- Used by {{translit module documentation}}.
function export.translitModuleLangList(frame)
local pagename, subpage
if frame.args[1] then
pagename = frame.args[1]
else
local title = mw.title.getCurrentTitle()
subpage = title.subpageText
pagename = title.text
if subpage ~= pagename then
pagename = title.rootText
end
end
local translitModule = pagename
local languageObjects = require("Module:languages/byTranslitModule")(translitModule)
local codeInPagename = pagename:match("^([%l-]+)%-.*translit$")
local categories = require("Module:array")()
if codeInPagename then
local langs = {}
local codeInPagenameInList = false
if languageObjects[1] and subpage ~= "documentation" then
local agreement = languageObjects[2] and "s" or ""
categories:insert("[[Category:Transliteration modules used by " ..
#languageObjects .. " language" .. agreement .. "]]")
end
for i, lang in ipairs(languageObjects) do
if lang:getCode() == codeInPagename then
table.remove(languageObjects, i)
codeInPagenameInList = true
break
end
end
end
for script_code in pagename:gmatch("%f[^-%z]%u%l%l%l%f[-]") do
local script = require "Module:scripts".getByCode(script_code)
if script then
categories:insert("[[Category:" .. script:getCategoryName() .. "]]")
end
end
-- TODO: Use serialCommaJoin in [[Module:table]].
if not languageObjects[1] then
return categories:concat()
end
table.sort(languageObjects,
function(lang1, lang2)
return lang1:getCode() < lang2:getCode()
end)
if languageObjects[3] then
for i, lang in ipairs(languageObjects) do
table.insert(langs, link_lang_cat(lang))
if languageObjects[i + 2] then
table.insert(langs, ", ")
elseif languageObjects[i + 1] then
table.insert(langs, '<span class="serial-comma">,</span> and ')
end
end
else
for i, lang in ipairs(languageObjects) do
table.insert(langs, link_lang_cat(lang))
if languageObjects[i + 1] then
table.insert(langs, " and ")
end
end
end
langs = table.concat(langs)
return "It is " .. ( codeInPagenameInList and "also" or "" ) ..
" used to transliterate " .. langs .. "." .. categories:concat()
end
return export