Module:module documentation
Itsura
- This module lacks a documentation subpage. Please create it.
- Useful links: subpage list • links • transclusions • testcases • sandbox
local m_str_utils = require("Module:string utilities")
local codepoint = m_str_utils.codepoint
local concat = table.concat
local insert = table.insert
local u = m_str_utils.char
local rsplit = m_str_utils.split
local export = {}
--[===[ intro:
Ang modyul na ito ay awtomatikong bumubuo ng dokumentasyon para sa iba pang mga module. Kinukuha nito ang mga in-line na komento sa Lua code at
kino-magbalik-loob ang mga ito sa isang porma na maaaring gamitin sa isang pahina ng dokumentasyon sa pamamagitan ng {{tl|module documentation}}. Sa katunayan, ito
Ang dokumentasyon ng module ay isang halimbawa nito sa pagkilos!
Nakatutulong na gawin ang dokumentasyon sa ganitong paraan, dahil nangangahulugan ito na ang dokumentasyon ng punsyon/pamamaraan ay magagamit sa dalawang lugar:
sa tuktok ng pahina ng modulo (bilang kumbensyonal na Wikitext), at sa itaas ng mismong punsyon (bilang isang komento sa Lua). Ang bawat isa
nababagay sa ibang uri ng istilo ng pagitago, at ang paggawa nito sa paraang ito ay nagpapanatili sa kanila na nakapagsabayin.
Ang isang seksyon ng dokumentasyon ay ibinibigay gamit ang multi-line komento syntax ni Lua, na mukhang ganito:
{--[==[ ... ]==]}. Karaniwang dapat dalawa ang bilang ng magkaparehong mga palatandaan upang maging maayos ang dokumentasyon
na-snarfed ng {{tl|module documentation}}. Ang mga sumusunod na kumbensyon ay maaaring gamitin sa loob ng dokumentasyon:
# Mahabang linya (kapwa sa mga regular na talata at nasa listahan ng mga aytem) ay maaaring sirain ng mga bagong linya na opsyonal na sinusundan ng mga puwang
o mga tab (lalo na kapaki-pakinabang sa mga listahan, upang gawing mas nababasa ang hilaw na komento). Sa ganoong kaso, ang bagong linya ay palitan
sa isang espasyo. Gumamit ng dalawang bagong linya sa isang hilera upang masira ang mga talata. Sa pangkalahatan, inirerekumenda na putulin ang mga linya pagkatapos ng karamihan
120 karakter, para mapadali ang pagbabasa ng hilaw na komento.
# Ang mga padron na tawag (gamit ang dalawang brace) ay maaaring literal na maipasok at mapapalawak.
# Ang mga solong brace ay maaaring gamitin upang palibutan ang literal na teksto, at awtomatikong ma-syntax-highlight bilang Lua code. Nakapugad
Ang mga brace sa loob ng literal na tekstong ito ay maayos na pangasiwaan hangga't sila ay balanse. Kung ang unang karakter ng
Ang literal na teksto ay isang brace, maglagay ng puwang bago ito (ngunit hindi sa dulo), at ito ay hindi papansinin.
Maaaring gamitin ang # Backquotes upang palibutan ang literal na teksto, na ipapakita gamit ang {<code>...</code>}. Ang mga bagay sa loob ng
Ang mga backquotes ay hindi maaaring maglaman ng isang backquote (maliban sa double-backquoted na mga pangalan ng baryante ng placeholder) o pahabain sa maramihang
mga linya.
# Ang dobleng backquotes ay maaaring gamitin upang palibutan ang mga pangalan ng baryante ng placeholder, na ipapakita gamit ang {<var>...</var>}.
Ang mga bagay sa loob ng backquotes ay maaari lamang maglaman ng mga titik, numero, salungguhitan, gitling at tuldok. Karaniwan, ganyan
dapat ipakita ang mga placeholder sa isang monospace na font, na parang napapalibutan ng {<code>...</code>}. Ang epektong ito ay maaaring
nakakamit sa pamamagitan ng paggamit ng makaitlo backquotes, na epektibong gumagamit ng double-backquote syntax sa loob ng single-backquote
syntax.
Maaaring sundin ng ilang partikular na direktiba ang pambungad na multiline na tagapagpahiwatig ng komento, kung ilalagay sa parehong linya ng
tagapagpahiwatig. Sa partikular, ang mga sumusunod na direktiba ay kasalukuyang kinikilala:
* Ang direktiba na `intro:` ay nagsasaad ng pambungad na teksto, na ilalagay sa simula, bago gumana
dokumentasyon. Ito ay kapaki-pakinabang upang magbigay ng pangkalahatang panimula/pangkalahatang-ideya ng modyul.
* Ang direktiba na `func: export.<var>function</var>(<var>arg1</var>, <var>arg2</var>, ...)` ay maaaring gamitin kapag nagdodokumento ng isang
punsyon na idineklara sa isang hindi karaniwang paraan (hal. sa pamamagitan ng isang natatanggap, sa pamamagitan ng isang anonimo o lokal na idineklara na punsyon
itinalaga sa talahanayang `export`, atbp.). Ang direktiba ay nagpapahiwatig ng nais na paraan para lumitaw ang punsyon, at ang
Ang natitira sa komento ay naglalarawan sa pagpapatakbo ng punsyon, gaya ng dati.
]===]
local TEMP_LEFT_BRACE = u(0xFFF0)
local TEMP_NEWLINE = u(0xFFF1)
local function format_doc(str)
local code_blocks = {}
local code_blocks_i = 0
local private_use_start = 0x100000
local subbed_str = (str
-- Multiline literal text between backquotes; you can't use <pre> or <syntaxhighlight> because that
-- disables Wikitext parsing for <var>...</var>, italics, <span>...</span> etc. Instead use the trick of
-- putting a space at the beginning of each line, which yields monospace text without disabling Wikitext
-- interpretation.
:gsub("```(.-)```", function(inside)
return inside
-- placeholder variable names between double backquotes; we need to repeat this here to avoid
-- the following pattern for single backquotes from clobbering double backquotes
:gsub("``([A-Za-z0-9_%-. ]+)``", "<var>%1</var>")
-- single backquotes undo monospacing
:gsub("`([^`\n]+)`", '<span style="font-family: sans-serif;">%1</span>')
-- text on the first line should be monospaced
:gsub("^([^\n])", " %1")
-- text after a newline should be monospaced, and temp-escape the newline so later replacements
-- to join continued lines in a paragraph don't take effect
:gsub("\n", TEMP_NEWLINE .. " ")
-- escape { so it won't be interpreted as a code block
:gsub("{", TEMP_LEFT_BRACE)
end)
:gsub("``([A-Za-z0-9_%-. ]+)``", "<var>%1</var>") -- placeholder variable names between double backquotes
:gsub("`([^`\n]+)`", function(inside) -- literal text between backquotes, set using <code>...</code>
-- Escape { so it won't be interpreted as a code block.
inside = inside:gsub("{", TEMP_LEFT_BRACE)
return "<code>" .. inside .. "</code>"
end)
-- {} blocks: blocks of code
-- Escape to avoid removing line breaks.
:gsub("%b{}", function(m0)
local next_char = m0:sub(2, 2)
if next_char == "|" then
-- Wikitable; don't try to parse it as code. But we do want to parse special syntax in them (in
-- particular {...} syntax for embedded code snippets), and if we return nil that won't happen.
-- Instead, we call format_doc() recursively on the innards.
return "{" .. format_doc(m0:sub(2, -2)) .. "}"
end
if next_char == "{" and m0:sub(-2, -2) == "}" then return nil end
local text = "<syntaxhighlight lang=lua" .. (m0:match("\n") and "" or " inline") .. ">" .. m0:sub(2, -2):gsub("^ +", "") .. "</syntaxhighlight>"
-- Prevent any further processing by storing the desired text into the `code_blocks` array and replacing
-- the whole thing with a single private-use-area character.
code_blocks_i = code_blocks_i + 1
code_blocks[code_blocks_i] = text
return u(private_use_start + code_blocks_i)
end)
-- undo escaping of left brace to prevent code block interpretation
:gsub(TEMP_LEFT_BRACE, "{")
-- Join continued lines in a paragraph. We don't want to do that if there are two newlines in a row,
-- and not if the second line begins with whitespace or a certain special characters (#, * or : indicating
-- a list item; | indicating a wikitable item; semicolon for bolded items).
:gsub("([^\n])\n[ \t]*([^ \t\n#*:;|])", "%1 %2")
-- Repeat the previous in case of a single-character line (admittedly rare).
:gsub("([^\n])\n[ \t]*([^ \t\n#*:;|])", "%1 %2")
:gsub("\n[ \t]+%f[*#:;]", "\n") -- remove indentation for list items
:gsub("%f[\n,{]\n%f[^\n*#:;]", "\n\n") -- wiki newlines
-- double-underline to indicate types (displayed as italicized underlined)
:gsub("__([_%w]-)__", function(inside)
return "<u><i>" .. inside .. "</i></u>"
end)
-- undo escaping of newline to prevent joining of continued lines
:gsub(TEMP_NEWLINE, "\n"))
-- Put <code>...</code> around <var>...</var> invocations that don't already occur inside of
-- <code>...</code> blocks.
local split_on_code = rsplit(subbed_str, "(<code>.-</code>)")
for i = 1, #split_on_code, 2 do
split_on_code[i] = split_on_code[i]:gsub("(<var>.-</var>)", "<code>%1</code>")
end
subbed_str = concat(split_on_code)
return (subbed_str
-- Undo code-block stashing.
:gsub("\244[\128-\191][\128-\191][\128-\191]", function(char)
return code_blocks[codepoint(char) - private_use_start]
end))
end
--[===[
The main entrypoint for {{tl|module documentation}}. The frame object can contain 3 optional arguments:
* |comment_level=: The number of equals signs (=) a given section uses. Default: 2 (i.e. {--[==[ ... (comment block) ]==]})
*: e.g. The value 4 means {--[====[ ... (comment block) ]====]}.
* |section_level=: The header level used for each function/method. Default: 2 (i.e. L2: {== ... ==}).
* |identifier=: A Lua string pattern. Only the comments of functions whose names match this pattern are used. When not given, all function are accepted.
*: This is useful when giving object methods, using a pattern such as {^object_name:}.
]===]
function export.show(frame)
local args = frame:getParent().args or {}
local comment_level = tonumber(args["comment_level"]) or 2
local function make_comment_pattern(typeid)
if typeid then
typeid = "%s*" .. typeid
else
typeid = ""
end
return "%-%-%[" .. ("="):rep(comment_level) .. "%[" .. typeid .. "\n?(.-)[\t\n]*]" .. ("="):rep(comment_level) .. "]()"
end
local fn_comment_pattern = make_comment_pattern(nil)
local intro_comment_pattern = make_comment_pattern("intro:")
local metafunc_comment_pattern = make_comment_pattern("func:%s*(([^\n(]+)[^\n)]+%))")
local section_mark = ("="):rep(tonumber(args["section_level"]) or 2)
local pattern_identifier = args["identifier"] or ""
local mod_title = mw.title.getCurrentTitle()
if mod_title.text:match("/documentation$") then return "(<i>Ang nabuong dokumentasyon ay matatagpuan sa pahina ng modulo.</i>)" end
local mod_text = mod_title:getContent()
if not mod_text then return "(<i>Ang pahina ng modyul ay wala na ngayon.</i>)" end
-- This contains function and intro documentation. Each element is a two-element list of {POSITION, DOCS} specifying
-- the generated documentation for a function and the character position in the file where it was found (for sorting
-- purposes).
local docs
local intro_comment = mod_text:match("^.-" .. intro_comment_pattern)
if intro_comment then
docs = { {1, format_doc(intro_comment) }}
else
docs = {}
end
-- Look for actual functions.
for p0, f, fn in mod_text:gmatch("()\n[ \t]*function +(([^\n(]+)[^\n)]+%))") do
if fn:match(pattern_identifier) then
local c = mod_text:sub(1, p0 - 1):match("^.*" .. fn_comment_pattern .. "%s*$")
insert(docs, {p0, section_mark .. fn .. section_mark .. "\n\n" .. "<syntaxhighlight lang=lua inline>function " ..
f .. "</syntaxhighlight>\n\n" .. format_doc(c or
'<strong class="error">Walang dokumentasyon ang punsyon na ito. Mangyaring magdagdag ng paglalarawan ng mga paggamit, input at output nito, ' ..
"o ang pagkakaiba nito sa mga katulad na punsyon, o gawin itong lokal upang alisin ito sa listahan ng punsyon.</strong>" ..
"[[Category:Mga padron at modulo na nangangailangan ng dokumentasyon]]")})
end
end
-- Now look for comments with the function declaration inside them (used for metatable functions etc.).
for p0, f, fn, comment in mod_text:gmatch("()" .. metafunc_comment_pattern) do
insert(docs, {p0, section_mark .. fn .. section_mark .. "\n\n" .. "<syntaxhighlight lang=lua inline>function " .. f .. "</syntaxhighlight>\n\n" .. format_doc(comment)})
end
table.sort(docs, function(a, b) return a[1] < b[1] end)
local chunks = {}
for i, decl in ipairs(docs) do
insert(chunks, decl[2])
end
return frame:preprocess(concat(chunks, "\n\n"))
end
return export