Module:documentation: Difference between revisions

m
1 revision imported
No edit summary
m (1 revision imported)
 
(3 intermediate revisions by 2 users not shown)
Line 1: Line 1:
local export = {}
local export = {}


local array_module = "Module:array"
local debug_track_module = "Module:debug/track"
local frame_module = "Module:frame"
local fun_is_callable_module = "Module:fun/isCallable"
local languages_module = "Module:languages"
local links_module = "Module:links"
local load_module = "Module:load"
local module_categorization_module = "Module:module categorization"
local number_list_show_module = "Module:number list/show"
local pages_module = "Module:pages"
local pages_module = "Module:pages"
local parameters_module = "Module:parameters"
local scripts_module = "Module:scripts"
local string_endswith_module = "Module:string/endswith"
local string_gline_module = "Module:string/gline"
local string_insert_module = "Module:string/insert"
local string_startswith_module = "Module:string/startswith"
local string_utilities_module = "Module:string utilities"
local template_parser_module = "Module:template parser"
local title_exists_module = "Module:title/exists"
local title_new_title_module = "Module:title/newTitle"


local m_pages = require(pages_module)
local concat = table.concat
local error = error
local full_url = mw.uri.fullUrl
local get_current_title = mw.title.getCurrentTitle
local insert = table.insert
local ipairs = ipairs
local list_to_text = mw.text.listToText
local new_message = mw.message.new
local pcall = pcall
local require = require
local tonumber = tonumber
local tostring = tostring
local type = type
local unpack = unpack or table.unpack -- Lua 5.2 compatibility


local get_pagetype = m_pages.get_pagetype
local function Array(...)
local is_documentation = m_pages.is_documentation
Array = require(array_module)
local is_sandbox = m_pages.is_sandbox
return Array(...)
end
 
local function categorize_module(...)
categorize_module = require(module_categorization_module).categorize
return categorize_module(...)
end
 
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
 
local function endswith(...)
endswith = require(string_endswith_module)
return endswith(...)
end
 
local function expand_template(...)
expand_template = require(frame_module).expandTemplate
return expand_template(...)
end
 
local function find_templates(...)
find_templates = require(template_parser_module).find_templates
return find_templates(...)
end
 
local function full_link(...)
full_link = require(links_module).full_link
return full_link(...)
end
 
local function get_lang(...)
get_lang = require(languages_module).getByCode
return get_lang(...)
end
 
local function get_pagetype(...)
get_pagetype = require(pages_module).get_pagetype
return get_pagetype(...)
end
 
local function get_script(...)
get_script = require(scripts_module).getByCode
return get_script(...)
end
 
local function gline(...)
gline = require(string_gline_module)
return gline(...)
end
 
local function is_callable(...)
is_callable = require(fun_is_callable_module)
return is_callable(...)
end
 
local function is_documentation(...)
is_documentation = require(pages_module).is_documentation
return is_documentation(...)
end
 
local function is_sandbox(...)
is_sandbox = require(pages_module).is_sandbox
return is_sandbox(...)
end
 
local function new_title(...)
new_title = require(title_new_title_module)
return new_title(...)
end
 
local function number_list_show_table(...)
number_list_show_table = require(number_list_show_module).table
return number_list_show_table(...)
end
 
local function preprocess(...)
preprocess = require(frame_module).preprocess
return preprocess(...)
end
 
local function process_params(...)
process_params = require(parameters_module).process
return process_params(...)
end
 
local function safe_load_data(...)
safe_load_data = require(load_module).safe_load_data
return safe_load_data(...)
end
 
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
 
local function startswith(...)
startswith = require(string_startswith_module)
return startswith(...)
end
 
local function string_insert(...)
string_insert = require(string_insert_module)
return string_insert(...)
end
 
local function title_exists(...)
title_exists = require(title_exists_module)
return title_exists(...)
end
 
local function ugsub(...)
ugsub = require(string_utilities_module).gsub
return ugsub(...)
end


-- it is either here, or in [[Module:ugly hacks]], and it is not in ugly hacks.
local function umatch(...)
function export.CONTENTMODEL()
umatch = require(string_utilities_module).match
return mw.title.getCurrentTitle().contentModel
return umatch(...)
end
end


Line 22: Line 170:
}
}


local Array = require "Module:array"
local function track(page)
debug_track("documentation/" .. page)
return true
end


local function compare_pages(page1, page2, text)
local function compare_pages(page1, page2, text)
return "[" .. tostring(
return "[" .. tostring(
mw.uri.fullUrl("Special:ComparePages", {page1 = page1, page2 = page2}))
full_url("Special:ComparePages", {page1 = page1, page2 = page2}))
.. " " .. text .. "]"
.. " " .. text .. "]"
end
local function page_exists(title)
local success, title_obj = pcall(mw.title.new, title)
return success and title_obj.exists
end
end


-- Avoid transcluding [[Module:languages/cache]] everywhere.
-- Avoid transcluding [[Module:languages/cache]] everywhere.
local lang_cache = setmetatable({}, { __index = function (self, k)
local lang_cache = setmetatable({}, { __index = function (self, k)
return require "Module:languages/cache"[k]
return require("Module:languages/cache")[k]
end })
end })


local function zh_link(word)
local function zh_link(word)
return require("Module:links").full_link{
return full_link{
lang = lang_cache.zh,
lang = lang_cache.zh,
term = word
term = word
Line 49: Line 195:
local function make_languages_data_documentation(title, cats, division)
local function make_languages_data_documentation(title, cats, division)
local doc_template, module_cat
local doc_template, module_cat
if division:find("/extra$") then
if endswith(division, "/extra") then
division = division:gsub("/extra$", "")
division = division:sub(1, -7)
doc_template = "language extradata documentation"
doc_template = "language extradata documentation"
module_cat = "Language extra data modules"
module_cat = "Language extra data modules"
Line 88: Line 234:
"[[Appendix:Unicode|Unicode]] code points within the range U+%04X to U+%04X.",
"[[Appendix:Unicode|Unicode]] code points within the range U+%04X to U+%04X.",
low, high)
low, high)
if subpage == "images" and pcall(mw.loadData, "Module:Unicode data/emoji images/" .. first_three_of_code_point) then
if subpage == "images" and safe_load_data("Module:Unicode data/emoji images/" .. first_three_of_code_point) then
text = text .. " This list includes the text variants of emojis. For the list of emoji variants of those characters, see [[Module:Unicode data/emoji images/" .. first_three_of_code_point .. "]]."
text = text .. " This list includes the text variants of emojis. For the list of emoji variants of those characters, see [[Module:Unicode data/emoji images/" .. first_three_of_code_point .. "]]."
elseif subpage == "emoji images" then
elseif subpage == "emoji images" then
Line 100: Line 246:
local lang = lang_cache[langcode]
local lang = lang_cache[langcode]
if lang then
if lang then
local langname = lang:getCanonicalName()
local langname
if lang._fullCode then
langname = lang_cache[lang._fullCode]:getCanonicalName()
else
langname = lang:getCanonicalName()
end
cats:insert(overall_data_module_cat .. "|" .. langname)
cats:insert(overall_data_module_cat .. "|" .. langname)
cats:insert(langname .. " modules")
cats:insert(langname .. " modules")
Line 147: Line 298:
local module_regex = {
local module_regex = {
{
{
regex = "^Module:languages/data/(3/[a-z]/extra)$",
regex = "^Module:languages/data/(3/%l/extra)$",
process = make_languages_data_documentation,
process = make_languages_data_documentation,
},
},
{
{
regex = "^Module:languages/data/(3/[a-z])$",
regex = "^Module:languages/data/(3/%l)$",
process = make_languages_data_documentation,
process = make_languages_data_documentation,
},
},
Line 235: Line 386:
regex = "^Module:number list/data/(.+)$",
regex = "^Module:number list/data/(.+)$",
process = function(title, cats, lang_code)
process = function(title, cats, lang_code)
local lang, langname = insert_lang_data_module_cats(cats, lang_code, "Number data modules")
local lang = insert_lang_data_module_cats(cats, lang_code, "Number data modules")
if lang then
if lang then
return ("This module contains data on various types of numbers in %s.\n%s")
return ("This module contains data on various types of numbers in %s.\n%s")
:format(lang:makeCategoryLink(), require("Module:number list/show").table() or "")
:format(lang:makeCategoryLink(), number_list_show_table() or "")
end
end
end,
end,
Line 263: Line 414:
local lang = lang_cache["inc-ash"]
local lang = lang_cache["inc-ash"]
return ("This module contains data on the pronunciation of %s in dialects of %s.")
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"),
:format(full_link({ term = word, lang = lang }, "term"),
lang:makeCategoryLink())
lang:makeCategoryLink())
end
end
Line 286: Line 437:
regex = "^Module:labels/data/lang/(.+)$",
regex = "^Module:labels/data/lang/(.+)$",
process = function(title, cats, lang_code)
process = function(title, cats, lang_code)
local lang, langname = insert_lang_data_module_cats(cats, lang_code, "Language-specific label data modules")
local lang = insert_lang_data_module_cats(cats, lang_code, "Language-specific label data modules")
if lang then
if lang then
return {
return {
Line 296: Line 447:
},
},
{
{
regex = "^Module:category tree/poscatboiler/data/lang%-specific/(.+)$",
regex = "^Module:category tree/lang/(.+)$",
process = function(title, cats, lang_code)
process = function(title, cats, lang_code)
local lang, langname = insert_lang_data_module_cats(cats, lang_code, "Category tree data modules/poscatboiler")
local lang, langname = insert_lang_data_module_cats(cats, lang_code, "Category tree data modules/lang")
if lang then
if lang then
return "This module handles generating the descriptions and categorization for " .. langname .. " category pages "
return "This module handles generating the descriptions and categorization for " .. langname .. " category pages "
.. "of the format \"" .. langname .. " LABEL\" where LABEL can be any text. Examples are "
.. "of the format \"" .. langname .. " LABEL\" where LABEL can be any text. Examples are "
.. "[[:Category:Bulgarian conjugation 2.1 verbs]] and [[:Category:Russian velar-stem neuter-form nouns]]. "
.. "[[:Category:Bulgarian conjugation 2.1 verbs]] and [[:Category:Russian velar-stem neuter-form nouns]]. "
.. "This module is part of the poscatboiler system, which is a general framework for generating the "
.. "This module is part of the category tree system, which is a general framework for generating the "
.. "descriptions and categorization of category pages.\n\n"
.. "descriptions and categorization of category pages.\n\n"
.. "For more information, see [[Module:category tree/poscatboiler/data/lang-specific/documentation]].\n\n"
.. "For more information, see [[Module:category tree/lang/documentation]].\n\n"
.. "'''NOTE:''' If you add a new language-specific module, you must add the language code to the "
.. "'''NOTE:''' If you add a new language-specific module, you must add the language code to the "
.. "list at the top of [[Module:category tree/poscatboiler/data/lang-specific]] in order for the module to be "
.. "list at the top of [[Module:category tree/lang]] in order for the module to be recognized."
.. "recognized."
end
end
end
end
},
},
{
{
regex = "^Module:category tree/poscatboiler/data/(.+)$",
regex = "^Module:category tree/topic/(.+)$",
process = function(title, cats, submodule)
process = function(title, cats, submodule)
cats:insert("Category tree data modules/poscatboiler| ")
cats:insert("Category tree data modules/topic| ")
return {
return {
title = "poscatboiler data submodule documentation"
title = "topic cat data submodule documentation"
}
}
end
end
},
},
{
{
regex = "^Module:category tree/topic cat/data/(.+)$",
regex = "^Module:category tree/(.+)$",
process = function(title, cats, submodule)
process = function(title, cats, submodule)
cats:insert("Category tree data modules/topic cat| ")
cats:insert("Category tree data modules| ")
return {
return {
title = "topic cat data submodule documentation"
title = "category tree data submodule documentation"
}
}
end
end
Line 353: Line 503:
},
},
{
{
regex = "^Module:Swadesh/data/([a-z-]+)$",
regex = "^Module:Swadesh/data/([%l-]+)$",
process = function(title, cats, lang_code)
process = function(title, cats, lang_code)
local lang, langname = insert_lang_data_module_cats(cats, lang_code, "Swadesh modules")
local lang, langname = insert_lang_data_module_cats(cats, lang_code, "Swadesh modules")
Line 362: Line 512:
},
},
{
{
regex = "^Module:Swadesh/data/([a-z-]+)/([^/]*)$",
regex = "^Module:Swadesh/data/([%l-]+)/([^/]*)$",
process = function(title, cats, lang_code, variety)
process = function(title, cats, lang_code, variety)
local lang, langname = insert_lang_data_module_cats(cats, lang_code, "Swadesh modules")
local lang, langname = insert_lang_data_module_cats(cats, lang_code, "Swadesh modules")
if lang then
if lang then
local prefix = "This module contains the [[Swadesh list]] of basic vocabulary in the "
local prefix = "This module contains the [[Swadesh list]] of basic vocabulary in the "
local etym_lang = require("Module:languages").getByCode(variety, nil, "allow etym")
local etym_lang = get_lang(variety, nil, "allow etym")
if etym_lang then
if etym_lang then
return ("%s %s variety of %s."):format(prefix, etym_lang:getCanonicalName(), langname)
return ("%s %s variety of %s."):format(prefix, etym_lang:getCanonicalName(), langname)
end
end
local script = require("Module:scripts").getByCode(variety)
local script = get_script(variety)
if script then
if script then
return ("%s %s %s script."):format(prefix, langname, script:getCanonicalName())
return ("%s %s %s script."):format(prefix, langname, script:getCanonicalName())
Line 386: Line 536:
if data_suffix then
if data_suffix then
if data_suffix:find "^[%l-]+$" then
if data_suffix:find "^[%l-]+$" then
local lang = require("Module:languages").getByCode(data_suffix)
local lang = get_lang(data_suffix)
if lang then
if lang then
sortkey = lang:getCanonicalName()
sortkey = lang:getCanonicalName()
Line 392: Line 542:
end
end
elseif data_suffix:find "^%u%l%l%l$" then
elseif data_suffix:find "^%u%l%l%l$" then
local script = require("Module:scripts").getByCode(data_suffix)
local script = get_script(data_suffix)
if script then
if script then
sortkey = script:getCanonicalName()
sortkey = script:getCanonicalName()
Line 403: Line 553:
},
},
{
{
regex = "^Module:R:([a-z%-]+):(.+)$",
regex = "^Module:R:([%l-]+):(.+)$",
process = function(title, cats, lang_code, refname)
process = function(title, cats, lang_code, refname)
local lang = lang_cache[lang_code]
local lang = lang_cache[lang_code]
Line 414: Line 564:
},
},
{
{
regex = "^Module:Quotations/([a-z-]+)/?(.*)",
regex = "^Module:Quotations/([%l-]+)/?(.*)",
process = "Quotation",
process = "Quotation",
},
},
{
{
regex = "^Module:affix/lang%-data/([a-z-]+)",
regex = "^Module:affix/lang%-data/([%l-]+)",
process = "affix lang-data",
process = "affix lang-data",
},
},
{
{
regex = "^Module:dialect synonyms/([a-z-]+)$",
regex = "^Module:dialect synonyms/([%l-]+)$",
process = function(title, cats, lang_code)
process = function(title, cats, lang_code)
local lang = lang_cache[lang_code]
local lang = lang_cache[lang_code]
Line 430: Line 580:
cats:insert(langname .. " dialect synonyms data modules| ")
cats:insert(langname .. " dialect synonyms data modules| ")
return "This module contains data on specific varieties of " .. langname .. ", for use by " ..
return "This module contains data on specific varieties of " .. langname .. ", for use by " ..
"{{tl|dialect synonyms}}. The actual synonyms themselves are contained in submodules."
"{{tl|dialect synonyms}}. The actual synonyms themselves are contained in submodules.\n\n" ..
expand_template({ title = 'dial syn', args = { lang_code, ["demo mode"] = "y" } })
end
end
end,
end,
},
},
{
{
regex = "^Module:dialect synonyms/([a-z-]+)/(.+)$",
regex = "^Module:dialect synonyms/([%l-]+)/(.+)$",
process = function(title, cats, lang_code, term)
process = function(title, cats, lang_code, term)
local lang = lang_cache[lang_code]
local lang = lang_cache[lang_code]
Line 442: Line 593:
cats:insert("Dialect synonyms data modules|" .. langname)
cats:insert("Dialect synonyms data modules|" .. langname)
cats:insert(langname .. " dialect synonyms data modules|" .. term)
cats:insert(langname .. " dialect synonyms data modules|" .. term)
return ("This module contains dialectal %s synonyms for {{m|%s|%s}}."):format(langname, lang_code, term)
return ("This module contains dialectal %s synonyms for {{m|%s|%s}}.\n\n%s"):format(langname, lang_code, term, expand_template({ title = 'dial syn', args = { lang_code, term } }))
end
end,
},
{
regex = "^Module:bibliography/data/([%l-]+)$",
process = function(title, cats, lang_code)
if lang_code == "preload" then
return 'Used as a base model for other languages when the button "create new language submodule" is clicked.'
end
end
local page = require(title.fullText).bib_page
if not page then
page = lang_cache[lang_code]:getCanonicalName()
if page then
cats:insert(page.." modules")
end
end
cats:insert("Reference modules")
return "This module holds bibliographical data for "..page..". For the formatted bibliography see '''[[Appendix:Bibliography/"..page.."]]'''."
end,
end,
},
},
Line 450: Line 618:
function export.show(frame)
function export.show(frame)
local boolean_default_false = {type = "boolean", default = false}
local boolean_default_false = {type = "boolean", default = false}
local args = require("Module:parameters").process(frame.args, {
local args = process_params(frame.args, {
["hr"] = true,
["hr"] = true,
["for"] = true,
["for"] = true,
Line 470: Line 638:
end
end
local title = args["for"] and mw.title.new(args["for"]) or mw.title.getCurrentTitle()
local title = args["for"] and new_title(args["for"]) or get_current_title()
local doc_title = args.from ~= "-" and mw.title.new(args.from or title.fullText .. '/documentation') or nil
local doc_title = args.from ~= "-" and new_title(args.from or title.fullText .. '/documentation') or nil
local contentModel = title.contentModel
local contentModel = title.contentModel
local pagetype, is_script_or_stylesheet = get_pagetype(title)
local pagetype, is_script_or_stylesheet = get_pagetype(title)
Line 527: Line 695:
else
else
for _, data in ipairs(module_regex) do
for _, data in ipairs(module_regex) do
local captures = {mw.ustring.match(title.fullText, data.regex)}
local captures = {umatch(title.fullText, data.regex)}
if #captures > 0 then
if #captures > 0 then
local cat
local cat, process_function
local process_function
if is_callable(data.process) then
if type(data.process) == "function" then
process_function = data.process
process_function = data.process
elseif type(data.process) == "string" then
elseif type(data.process) == "string" then
Line 543: Line 710:
if type(doc_content) == "table" then
if type(doc_content) == "table" then
doc_content_source = doc_content.title and "Template:" .. doc_content.title or doc_content_source
doc_content_source = doc_content.title and "Template:" .. doc_content.title or doc_content_source
doc_content = mw.getCurrentFrame():expandTemplate(doc_content)
doc_content = expand_template(doc_content)
elseif doc_content and doc_content:find("{{") then
elseif doc_content ~= nil then
doc_content = mw.getCurrentFrame():preprocess(doc_content)
doc_content = preprocess(doc_content)
end
end
cat = data.cat
cat = data.cat
Line 554: Line 721:
end
end
for _, c in ipairs(cat) do
for _, c in ipairs(cat) do
-- gsub() and Lua :gsub() return two arguments, which causes all sorts of problems.
insert(cats, (ugsub(title.fullText, data.regex, c)))
-- Terrible design, there should have been a separate two-argument function.
local gsub_sucks = mw.ustring.gsub(title.fullText, data.regex, c)
table.insert(cats, gsub_sucks)
end
end
end
end
Line 576: Line 740:
if #cats == 0 then
if #cats == 0 then
local auto_cats = require("Module:module categorization").categorize(frame, "return raw", "noerror")
local auto_cats = categorize_module(frame, "return raw", "noerror")
if #auto_cats > 0 then
if #auto_cats > 0 then
auto_generated_cat_source = "Module:module categorization"
auto_generated_cat_source = "Module:module categorization"
Line 593: Line 757:
local cats_auto_generated_text = ""
local cats_auto_generated_text = ""
if contentModel == "Scribunto" then
if contentModel == "Scribunto" then
local doc_page_content = doc_title:getContent()
local doc_page_content = doc_title.content
-- Track then do nothing if there are uses of includeonly. The
-- Track then do nothing if there are uses of includeonly. The
-- pattern is slightly too permissive, but any false-positives are
-- pattern is slightly too permissive, but any false-positives are
-- obvious typos that should be corrected.
-- obvious typos that should be corrected.
if doc_page_content:lower():match("</?includeonly%f[%s/>][^>]*>") then
if doc_page_content:lower():match("</?includeonly%f[%s/>][^>]*>") then
track("module-includeonly")
else
else
-- Check for uses of {{module cat}}. find_templates treats the
-- Check for uses of {{module cat}}. find_templates treats the
Line 603: Line 768:
-- which will be transcluded through to the module page).
-- which will be transcluded through to the module page).
local module_cat
local module_cat
for template in require("Module:template parser").find_templates(doc_page_content) do
for template in find_templates(doc_page_content) do
if template:get_name() == "module cat" then
if template:get_name() == "module cat" then
module_cat = true
module_cat = true
Line 613: Line 778:
auto_generated_cat_source = auto_generated_cat_source or doc_content_source
auto_generated_cat_source = auto_generated_cat_source or doc_content_source
cats_auto_generated_text = " Categories were auto-generated by [[" .. auto_generated_cat_source .. "]]. <sup>[[" ..
cats_auto_generated_text = " Categories were auto-generated by [[" .. auto_generated_cat_source .. "]]. <sup>[[" ..
mw.title.new(auto_generated_cat_source):fullUrl{action = "edit"} ..  " edit]]</sup>"
new_title(auto_generated_cat_source):fullUrl{action = "edit"} ..  " edit]]</sup>"
end
end
end
end
Line 620: Line 785:
output:insert(
output:insert(
"<dd><i style=\"font-size: larger;\">The following " ..
"<dd><i style=\"font-size: larger;\">The following " ..
"[[wikt:Help:Documenting templates and modules|documentation]] is located at [[" ..
"[[Help:Documenting templates and modules|documentation]] is located at [[" ..
doc_title.fullText .. "]]. " .. "<sup>[[" .. doc_title:fullUrl{action = "edit"} .. " edit]]</sup>" ..
doc_title.fullText .. "]]. " .. "<sup>[[" .. doc_title:fullUrl{action = "edit"} .. " edit]]</sup>" ..
cats_auto_generated_text .. "</i></dd>")
cats_auto_generated_text .. "</i></dd>")
Line 630: Line 795:
needs_doc = not (fallback_docs or nodoc)
needs_doc = not (fallback_docs or nodoc)
elseif user_name and is_script_or_stylesheet then
elseif user_name and is_script_or_stylesheet then
skin_name = skins[title.text:sub(#title.rootText + 1):match("^/([a-z]+)%.[jc]ss?$")]
skin_name = skins[title.text:sub(#title.rootText + 1):match("^/(%l+)%.[jc]ss?$")]
if skin_name then
if skin_name then
fallback_docs = "documentation/fallback/user " .. contentModel
fallback_docs = "documentation/fallback/user " .. contentModel
Line 639: Line 804:
output:insert(
output:insert(
"<dd><i style=\"font-size: larger;\">The following " ..
"<dd><i style=\"font-size: larger;\">The following " ..
"[[wikt:Help:Documenting templates and modules|documentation]] is " ..
"[[Help:Documenting templates and modules|documentation]] is " ..
"generated by [[" .. doc_content_source .. "]]. <sup>[[" ..
"generated by [[" .. doc_content_source .. "]]. <sup>[[" ..
mw.title.new(doc_content_source):fullUrl{action = "edit"} ..
new_title(doc_content_source):fullUrl{action = "edit"} ..
" edit]]</sup> </i></dd>")
" edit]]</sup> </i></dd>")
elseif not nodoc then
elseif not nodoc then
Line 647: Line 812:
output:insert(
output:insert(
"<dd><i style=\"font-size: larger;\">This " .. pagetype ..
"<dd><i style=\"font-size: larger;\">This " .. pagetype ..
" lacks a [[wikt:Help:Documenting templates and modules|documentation subpage]]. " ..
" lacks a [[Help:Documenting templates and modules|documentation subpage]]. " ..
(fallback_docs and "You may " or "Please ") ..
(fallback_docs and "You may " or "Please ") ..
"[" .. doc_title:fullUrl{action = "edit", preload = preload}
"[" .. doc_title:fullUrl{action = "edit", preload = preload}
Line 653: Line 818:
else
else
output:insert(
output:insert(
"<dd><i style=\"font-size: larger; color: #FF0000;\">Unable to auto-generate " ..
"<dd><i style=\"font-size: larger; color: var(--wikt-palette-red-9,#FF0000);\">Unable to auto-generate " ..
"documentation for this " .. pagetype ..".</i></dd>\n")
"documentation for this " .. pagetype ..".</i></dd>\n")
end
end
Line 659: Line 824:
end
end
if title.fullText:match("^MediaWiki:Gadget%-") then
if startswith(title.fullText, "MediaWiki:Gadget-") then
local is_gadget = false
local is_gadget = false
local gadget_list = mw.title.new("MediaWiki:Gadgets-definition"):getContent()
for line in gline(new_title("MediaWiki:Gadgets-definition").content) do
local gadget, items = line:match("^%*%s*(%a[%w_-]*)%[.-%]|(.+)$")
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
if not gadget then
gadget, items = line:match("^%*%s*([A-Za-z][A-Za-z0-9_%-]*)|(.+)$")
gadget, items = line:match("^%*%s*(%a[%w_-]*)|(.+)$")
end
end
if gadget then
if gadget then
items = Array(mw.text.split(items, "|"))
items = Array(split(items, "|"))
for i, item in ipairs(items) do
for i, item in ipairs(items) do
if title.fullText == ("MediaWiki:Gadget-" .. item) then
if title.fullText == ("MediaWiki:Gadget-" .. item) then
Line 678: Line 840:
output:insert(gadget)
output:insert(gadget)
output:insert("</code> gadget ([")
output:insert("</code> gadget ([")
output:insert(tostring(mw.uri.fullUrl("MediaWiki:Gadgets-definition", {action = "edit"})))
output:insert(tostring(full_url("MediaWiki:Gadgets-definition", {action = "edit"})))
output:insert(" edit definitions])'' <dl>")
output:insert(" edit definitions])'' <dl>")
output:insert("<dd> ''Description ([")
output:insert("<dd> ''Description ([")
output:insert(tostring(mw.uri.fullUrl("MediaWiki:Gadget-" .. gadget, {action = "edit"})))
output:insert(tostring(full_url("MediaWiki:Gadget-" .. gadget, {action = "edit"})))
output:insert(" edit])'': ")
output:insert(" edit])'': ")
local gadget_description = mw.message.new('Gadget-' .. gadget):plain()
output:insert(preprocess(new_message('Gadget-' .. gadget):plain()))
gadget_description = frame:preprocess(gadget_description)
output:insert(gadget_description)
output:insert(" </dd>")
output:insert(" </dd>")


Line 696: Line 856:
end
end
output:insert("<dd> ''Other parts'': ")
output:insert("<dd> ''Other parts'': ")
output:insert(mw.text.listToText(items))
output:insert(list_to_text(items))
output:insert("</dd>")
output:insert("</dd>")
end
end
Line 710: Line 870:
if not is_gadget then
if not is_gadget then
output:insert("<dd> ''This script is not a part of any [")
output:insert("<dd> ''This script is not a part of any [")
output:insert(tostring(mw.uri.fullUrl("Special:Gadgets", {uselang = "en"})))
output:insert(tostring(full_url("Special:Gadgets", {uselang = "en"})))
output:insert(' gadget] ([')
output:insert(' gadget] ([')
output:insert(tostring(mw.uri.fullUrl("MediaWiki:Gadgets-definition", {action = "edit"})))
output:insert(tostring(full_url("MediaWiki:Gadgets-definition", {action = "edit"})))
output:insert(' edit definitions]).</dd>')
output:insert(' edit definitions]).</dd>')
-- else
-- else
Line 740: Line 900:
links:insert(
links:insert(
"[" .. tostring(mw.uri.fullUrl("Special:WhatLinksHere/" .. title.fullText, {hidetrans = true, hideredirs = true})) .. " links]")
"[" .. tostring(full_url("Special:WhatLinksHere/" .. title.fullText, {hidetrans = true, hideredirs = true})) .. " links]")
if contentModel ~= "Scribunto" then
if contentModel ~= "Scribunto" then
links:insert(
links:insert(
"[" .. tostring(mw.uri.fullUrl("Special:WhatLinksHere/" .. title.fullText, {hidelinks = true, hidetrans = true})) .. " redirects]")
"[" .. tostring(full_url("Special:WhatLinksHere/" .. title.fullText, {hidelinks = true, hidetrans = true})) .. " redirects]")
end
end
Line 753: Line 913:
else
else
links:insert(
links:insert(
"[" .. tostring(mw.uri.fullUrl("Special:WhatLinksHere/" .. title.fullText, {hidelinks = true, hideredirs = true})) .. " transclusions]")
"[" .. tostring(full_url("Special:WhatLinksHere/" .. title.fullText, {hidelinks = true, hideredirs = true})) .. " transclusions]")
end
end
Line 769: Line 929:
links:insert("[[User talk:" .. user_name .. "|user talk page]]")
links:insert("[[User talk:" .. user_name .. "|user talk page]]")
links:insert("[[Special:PrefixIndex/User:" .. user_name .. "/|userspace]]")
links:insert("[[Special:PrefixIndex/User:" .. user_name .. "/|userspace]]")
else
-- If sandbox module, add a link to the module that this is a sandbox of.
-- If sandbox module, add a link to the module that this is a sandbox of.
-- Exclude user sandbox modules like [[User:Dine2016/sandbox]].
-- Exclude user sandbox modules like [[User:Dine2016/sandbox]].
elseif title.text:find("/sandbox%d*%f[/%z]") then
if title.text:find("/sandbox%d*%f[/%z]") then
cats:insert("Sandbox modules")
cats:insert("Sandbox modules")
-- Sandbox modules don’t really need documentation.
needs_doc = false
-- Don't track user sandbox modules.
local text_title = new_title(title.text)
if not (text_title and text_title.namespace == 2) then
track("sandbox to be moved")
-- Sandbox modules don’t really need documentation.
local sandbox_of, diff = title.baseText
needs_doc = false
if title_exists(sandbox_of) then
-- 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") .. ")"
diff = " (" .. compare_pages(title.fullText, sandbox_of, "diff") .. ")"
else
track("no sandbox of")
end
end
links:insert("[[:" .. sandbox_of .. "|sandbox of]]" .. (diff or ""))
links:insert("[[:" .. sandbox_of .. "|sandbox of]]" .. (diff or ""))
end
-- 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.rootText == "grc-decl" then
sandbox_title = string_insert(title.fullText, 16, "/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]]"
-- If not a sandbox module, add link to sandbox module.
local diff
-- Sometimes there are multiple sandboxes for a single module:
if title_exists(sandbox_title) then
-- [[Module:sa-pronunc/sandbox]],  [[Module:sa-pronunc/sandbox2]].
diff = " (" .. compare_pages(title.fullText, sandbox_title, "diff") .. ")"
-- 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
links:insert(sandbox_link .. (diff or ""))
end
end
end
end
Line 821: Line 983:
links:insert(
links:insert(
'[' .. tostring(mw.uri.fullUrl('Special:Search', errorq..eincategory )) .. ' errors]'
'[' .. tostring(full_url('Special:Search', errorq..eincategory )) .. ' errors]'
.. ' (' ..
.. ' (' ..
'[' .. tostring(mw.uri.fullUrl('Special:Search', errorq..'ParserFunction_errors' )) .. ' parser]'
'[' .. tostring(full_url('Special:Search', errorq..'ParserFunction_errors' )) .. ' parser]'
.. '/' ..
.. '/' ..
'[' .. tostring(mw.uri.fullUrl('Special:Search', errorq..'Pages_with_module_errors' )) .. ' module]'
'[' .. tostring(full_url('Special:Search', errorq..'Pages_with_module_errors' )) .. ' module]'
.. ')'
.. ')'
)
)
Line 841: Line 1,003:
local diff
local diff
if page_exists(sandbox_of) then
if title_exists(sandbox_of) then
diff = " (" .. compare_pages(title.fullText, sandbox_of, "diff") .. ")"
diff = " (" .. compare_pages(title.fullText, sandbox_of, "diff") .. ")"
else
track("no sandbox of")
end
end
Line 851: Line 1,015:
local diff
local diff
if page_exists(sandbox_title) then
if title_exists(sandbox_title) then
diff = " (" .. compare_pages(title.fullText, sandbox_title, "diff") .. ")"
diff = " (" .. compare_pages(title.fullText, sandbox_title, "diff") .. ")"
end
end
Line 868: Line 1,032:
-- Show error from [[Module:category tree/topic cat/data]] on its submodules'
-- Show error from [[Module:category tree/topic cat/data]] on its submodules'
-- documentation to, for instance, warn about duplicate labels.
-- documentation to, for instance, warn about duplicate labels.
if title.fullText:find("Module:category tree/topic cat/data", 1, true) == 1 then
if startswith(title.fullText, "Module:category tree/topic/") then
local ok, err = pcall(require, "Module:category tree/topic cat/data")
local ok, err = pcall(require, "Module:category tree/topic/data")
if not ok then
if not ok then
output:insert('<span class="error">' .. err .. '</span>\n\n')
output:insert('<span class="error">' .. err .. '</span>\n\n')
Line 877: Line 1,041:
if doc_title and doc_title.exists then
if doc_title and doc_title.exists then
-- Override automatic documentation, if present.
-- Override automatic documentation, if present.
doc_content = frame:expandTemplate { title = doc_title.fullText }
doc_content = expand_template{ title = doc_title.fullText }
elseif not doc_content and fallback_docs then
elseif not doc_content and fallback_docs then
doc_content = frame:expandTemplate {
doc_content = expand_template{
title = fallback_docs,
title = fallback_docs,
args = {
args = {
Line 893: Line 1,057:
end
end


output:insert(('\n<%s style="clear: both;" />'):format(args.hr == "below" and "hr" or "br"))
output:insert(('\n<%s style="clear: both;" />'):format(args.hr == "below" and "hr" or "span"))
if cats_auto_generated and not cats[1] and (not doc_content or not doc_content:find("%[%[Category:")) then
if cats_auto_generated and not cats[1] and (not doc_content or not doc_content:find("%[%[Category:")) then
Line 919: Line 1,083:
local parts = {}
local parts = {}
local function ins(text)
local function ins(text)
table.insert(parts, text)
insert(parts, text)
end
end
ins('{|class="wikitable"')
ins('{|class="wikitable"')
Line 932: Line 1,096:
end
end
for _, cat in ipairs(cats) do
for _, cat in ipairs(cats) do
table.insert(cat_parts, ("<code>%s</code>"):format((cat:gsub("|", "&#124;"))))
insert(cat_parts, ("<code>%s</code>"):format((cat:gsub("|", "&#124;"))))
end
end
cat_text = table.concat(cat_parts, ", ")
cat_text = concat(cat_parts, ", ")
else
else
cat_text = "''(unspecified)''"
cat_text = "''(unspecified)''"
Line 940: Line 1,104:
ins("|-")
ins("|-")
ins(("| <code>%s</code> || %s || %s"):format(spec.regex, cat_text,
ins(("| <code>%s</code> || %s || %s"):format(spec.regex, cat_text,
type(spec.process) == "function" and "''(handled internally)''" or
is_callable(spec.process) and "''(handled internally)''" or
type(spec.process) == "string" and ("[[Module:documentation/functions/%s]]"):format(spec.process) or
type(spec.process) == "string" and ("[[Module:documentation/functions/%s]]"):format(spec.process) or
"''(no documentation generator)''"))
"''(no documentation generator)''"))
end
end
ins("|}")
ins("|}")
return table.concat(parts, "\n")
return concat(parts, "\n")
end
end


Line 955: Line 1,119:
pagename = frame.args[1]
pagename = frame.args[1]
else
else
local title = mw.title.getCurrentTitle()
local title = get_current_title()
subpage = title.subpageText
subpage = title.subpageText
pagename = title.text
pagename = title.text
Line 989: Line 1,153:
if subpage ~= "documentation" then
if subpage ~= "documentation" then
for script_code in pagename:gmatch("%f[^-%z]%u%l%l%l%f[-]") do
for script_code in pagename:gmatch("%f[^-%z]%u%l%l%l%f[-]") do
local script = require "Module:scripts".getByCode(script_code)
local script = get_script(script_code)
if script then
if script then
categories:insert("[[Category:" .. script:getCategoryName() .. "]]")
categories:insert("[[Category:" .. script:getCategoryName() .. "]]")
Line 996: Line 1,160:
end
end
if subpage ~= "documentation" and not page_exists("Module:" .. pagename .. "/testcases") then
if subpage ~= "documentation" and not title_exists("Module:" .. pagename .. "/testcases") then
categories:insert("[[Category:Transliteration modules without a testcases subpage]]")
categories:insert("[[Category:Transliteration modules without a testcases subpage]]")
end
end
Line 1,024: Line 1,188:
pagename = frame.args[1]
pagename = frame.args[1]
else
else
local title = mw.title.getCurrentTitle()
local title = get_current_title()
subpage = title.subpageText
subpage = title.subpageText
pagename = title.text
pagename = title.text
Line 1,058: Line 1,222:
if subpage ~= "documentation" then
if subpage ~= "documentation" then
for script_code in pagename:gmatch("%f[^-%z]%u%l%l%l%f[-]") do
for script_code in pagename:gmatch("%f[^-%z]%u%l%l%l%f[-]") do
local script = require "Module:scripts".getByCode(script_code)
local script = get_script(script_code)
if script then
if script then
categories:insert("[[Category:" .. script:getCategoryName() .. "]]")
categories:insert("[[Category:" .. script:getCategoryName() .. "]]")
Line 1,065: Line 1,229:
end
end
if subpage ~= "documentation" and not page_exists("Module:" .. pagename .. "/testcases") then
if subpage ~= "documentation" and not title_exists("Module:" .. pagename .. "/testcases") then
categories:insert("[[Category:Entry name-generating modules without a testcases subpage]]")
categories:insert("[[Category:Entry name-generating modules without a testcases subpage]]")
end
end
Line 1,093: Line 1,257:
pagename = frame.args[1]
pagename = frame.args[1]
else
else
local title = mw.title.getCurrentTitle()
local title = get_current_title()
subpage = title.subpageText
subpage = title.subpageText
pagename = title.text
pagename = title.text
Line 1,127: Line 1,291:
if subpage ~= "documentation" then
if subpage ~= "documentation" then
for script_code in pagename:gmatch("%f[^-%z]%u%l%l%l%f[-]") do
for script_code in pagename:gmatch("%f[^-%z]%u%l%l%l%f[-]") do
local script = require "Module:scripts".getByCode(script_code)
local script = get_script(script_code)
if script then
if script then
categories:insert("[[Category:" .. script:getCategoryName() .. "]]")
categories:insert("[[Category:" .. script:getCategoryName() .. "]]")
Line 1,134: Line 1,298:
end
end
if subpage ~= "documentation" and not page_exists("Module:" .. pagename .. "/testcases") then
if subpage ~= "documentation" and not title_exists("Module:" .. pagename .. "/testcases") then
categories:insert("[[Category:Sortkey-generating modules without a testcases subpage]]")
categories:insert("[[Category:Sortkey-generating modules without a testcases subpage]]")
end
end