Module:T
- Subpages
{{#dpl: | namespace = Module | titlematch = T/% | skipthispage = false }}
-- <nowiki> -------------------------------------------------------------------------------- -- A feature-packed example generator for brace-based wikitext. -- -- @module T -- @alias p -- @version 0.6.3 -- @release experimental -- @requires [[Global Lua Modules/Arguments|Module:Arguments]] -- @requires [[Global Lua Modules/User error|Module:User error]] -- @requires [[Global Lua Modules/Yesno|Module:Yesno]] -- @author [[User:DarthKitty]] -- @author [[User:Speedit]] -- @author [[User:ExE Boss]] -- -- @todo Extract CSS to stylesheet; transition from data-attributes to classes. -- @todo Consider adding i18n for error messages, flags, &c. -- @todo Consider adding generator(s?) for magic words and parser functions. -------------------------------------------------------------------------------- local libraryUtil = require("libraryUtil") local checkType = libraryUtil.checkType local getArgs = require("Dev:Arguments").getArgs local userError = require("Dev:User error") local yesno = require("Dev:Yesno") local p = {} -------------------------------------------------------------------------------- -- Parses a parameter to get its components: its name (optional), and either its -- value or its description (but not both). -- -- @param {string} param -- A parameter. -- @returns {table} -- The components of a parameter. -------------------------------------------------------------------------------- local function parseParam(param) local tmp = param local name, value, description -- the parameter's name is anything to the left of the first equals sign; -- the equals sign can be escaped, for wikis that don't have [[Template:=]] if tmp:find("=") or tmp:find(mw.text.nowiki("=")) then name, tmp = tmp :gsub(mw.text.nowiki("="), "=", 1) :match("^(.-)%s*=%s*(.-)$") end -- if the remaining text is wrapped in matching quotes, then it's a literal -- value; otherwise, it's a description of the parameter local first = tmp:sub(1, 1) local last = tmp:sub(-1) if (first == '"' and last == '"') or (first == "'" and last == "'") then value = tmp:sub(2, -2) elseif tmp == "" then description = "..." -- the description cannot be an empty string else description = tmp end return { name = name, value = value, description = description } end -------------------------------------------------------------------------------- -- The heart of the module. Transforms a list of parameters into wikitext -- syntax. -- -- @param {string} mode -- Which kind of brace-based wikitext we're dealing with. -- @param {string} opener -- Text to insert between the two left-braces and the first parameter. -- @param[opt] {table|nil} params -- A sequentual table of parameters. -- @param[opt] {table|nil} options -- A table with configuration flags. -- @returns {string} -- A blob of wikitext describing any brace-based syntax. -------------------------------------------------------------------------------- local function builder(mode, opener, params, options) checkType("builder", 2, opener, "string") checkType("builder", 3, params, "table", true) checkType("builder", 4, options, "table", true) params = params or {} options = options or {} local html = mw.html.create("code") :attr("data-t-role", "wrapper") :attr("data-t-mode", mode) :css("all", "unset") :css("font-family", "monospace") :tag("span") :attr("data-t-role", "opener") :wikitext(mw.text.nowiki("{"):rep(2)) :wikitext(opener) :done() if options.multiline then html:attr("data-t-multiline", "data-t-multiline") end for i, param in ipairs(params) do if type(param) ~= "string" then error("invalid entry #" .. i .. " in parameter list", 3) end local components = parseParam(param) local paramHtml = html:tag("span") :attr("data-t-role", "parameter") :attr("data-t-index", i) :wikitext(mw.text.nowiki("|")) if options.multiline then paramHtml:css("display", "block") end if components.name then paramHtml:tag("span") :attr("data-t-role", "parameter-name") :css("font-weight", "bold") :wikitext(components.name) paramHtml:wikitext(" = ") end if components.value then paramHtml:tag("span") :attr("data-t-role", "parameter-value") :wikitext(components.value) end if components.description then paramHtml:tag("span") :attr("data-t-role", "parameter-description") :css("opacity", "0.65") :wikitext(mw.text.nowiki("<")) :wikitext(components.description) :wikitext(mw.text.nowiki(">")) end end html:tag("span") :attr("data-t-role", "closer") :wikitext(mw.text.nowiki("}"):rep(2)) return tostring(html) end -------------------------------------------------------------------------------- -- Resolves a transclusion according to the MediaWiki -- transclusion resolution algorithm. -- -- @param {string} title -- The name of the transclusion to resolve. -- @return {string} -- The resolved transclusion with the namespace prefix. -- @see [[w:Template:Transclude]] -------------------------------------------------------------------------------- function resolveTransclusion(title) checkType("resolveTransclusion", 1, title, "string") local i = mw.ustring.find(title, "%:") if i == 1 then return mw.ustring.sub(title, 2) elseif i ~= nil then return title end return "Template:" .. title end -------------------------------------------------------------------------------- -- Generator for transclusion syntax, e.g. `{{foo}}`, `{{:foo}}`, -- or `{{Template:Foo}}`. -- -- @param {string} title -- The name of the template to link to. -- @param[opt] {table|nil} params -- A sequentual table of parameters. -- @param[opt] {table|nil} options -- A table with configuration flags. -- @returns {string} -- A blob of wikitext describing a template. -------------------------------------------------------------------------------- function p.transclusion(title, params, options) if type(title) ~= "string" or title == "" then error("no title specified", 2) end return builder( "transclusion", "[[:" .. resolveTransclusion(title) .. "|" .. title .. "]]", params, options ) end -------------------------------------------------------------------------------- -- Generator for invocation syntax, e.g. `{{#invoke:foo|bar}}`. -- -- @param {string} title -- The name of the module to link to, without the namespace prefix. -- @param {string} func -- The name of the function to call. -- @param {table|nil} params -- A sequentual table of parameters. -- @param {table|nil} options -- A table with configuration flags. -- @returns {string} -- A blob of wikitext describing a module. -------------------------------------------------------------------------------- function p.invocation(title, func, params, options) if type(title) ~= "string" or title == "" then error("no module specified", 2) end if type(func) ~= "string" or func == "" then error("no function specified", 2) end local link = "[[Module:" .. title .. "|" .. title .. "]]" return builder( "invocation", "#invoke:" .. link .. mw.text.nowiki("|") .. func, params, options ) end -------------------------------------------------------------------------------- -- Entry point from the wikitext side. Determines which generator to use based -- on the provided arguments. -- -- @param {Frame} frame -- A frame object whose arguments will determine the correct generator to -- use. -- @returns {string} -- A blob of wikitext describing any brace-based syntax. -------------------------------------------------------------------------------- function p.main(frame) local args = getArgs(frame, {removeBlanks = false}) local mode, minimumArity if yesno(args.invocation) or yesno(args.i) then mode = "invocation" minimumArity = 2 else mode = "transclusion" minimumArity = 1 end local params = {} local options = { multiline = yesno(args.multiline) or yesno(args.m) } -- a dynamically-generated list of arguments to the generator -- required arguments are inserted before `params` and `options` local varargs = {params, options} for i, value in ipairs(args) do if i <= minimumArity then -- pass the first few values directly to the generator -- these are used to calculate the opener table.insert(varargs, i, value) else -- put the remaining values in a table, and pass it to the generator -- these are shown as parameters in the resulting wikitext params[#params + 1] = value end end local success, response = pcall(p[mode], unpack(varargs)) return success and response or userError(response) end return p