Documentation for this module may be created at Module:UtilsMarkup/Format/doc
local p = {} local h = {} local utilsString = require("Module:UtilsString") local utilsTable = require("Module:UtilsTable") local CLASS_TOOLTIP = require("Module:Constants/class/tooltip") local function tag(tag, attributes, styles) return function(content) return tostring(mw.html.create(tag) :attr(attributes or {}) :css(styles or {}) :wikitext(content)) end end local function extensionTag(tag, defaultArgs) return function(content, overrideArgs) local args = utilsTable.merge({}, defaultArgs or {}, overrideArgs or {}) return mw.getCurrentFrame():extensionTag(tag, content, args) .. "\n" -- tags like <pre> don't work properly without the newline end end function p.bold(text) return tag("b")(text) end function p.class(class, text) return tag("span", { class = class })(text) end function p.code(text) return "<code>" .. text .. "</code>" end function p.heading(level, content) local headingTag = string.rep("=", level) return "\n" .. headingTag .. content .. headingTag .. "\n" end function p.italic(text) return tag("i")(text) end function p.inline(text, options) options = options or {} if options.nowiki then text = mw.text.nowiki(text) end if options.code then text = p.code(text) end if options.italic then text = p.italic(text) end if options.bold then text = p.bold(text) end if options.tooltip then text = p.tooltip(text, options.tooltip) end if options.class then text = p.class(options.class, text) end return text end function p.lua(content, options) local wrapLines = options and options.wrapLines local attrs = {} if type(content) ~= "string" then content = utilsTable.print(content) end if wrapLines == false then attrs.class = "nowrapLines" end return p.syntaxHighlight("lua")(content or "nil", attrs) end function p.pre(text, options) options = options or {} local attrs = {} local wrapLines = options and options.wrapLines if wrapLines == false then attrs.style = "white-space: pre;" end return extensionTag("pre", attrs)(text) end function p.separateMarkup(text) local firstMarkupIndex = string.find(text, "[<%[]") local firstStripMarkerIndex = string.find(text, "\127'\"`UNIQ") firstMarkupIndex = h.min(firstMarkupIndex, firstStripMarkerIndex) local markup = "" if firstMarkupIndex then markup = string.sub(text, firstMarkupIndex, #text) text = string.sub(text, 1, firstMarkupIndex - 1) if utilsString.endsWith(text, " ") then text = utilsString.trim(text) markup = " "..markup end end return text, markup end function p.syntaxHighlight(lang, args) local args = utilsTable.merge({}, args or {}, { lang = lang }) return extensionTag("syntaxHighlight", args) end function p.tooltip(baseText, tooltipText) local attrs = { class = CLASS_TOOLTIP, title = tooltipText, } return tag("span", attrs)(baseText) end function h.min(a, b) if a == nil or b == nil or a == b then return a or b elseif b < a then return b else return a end end function p.Schemas() return { bold = { text = { type = "string", required = true, desc = "The text to bold." }, }, code = { text = { type = "string", required = true, desc = "The text to render monospaced." }, }, italic = { text = { type = "string", required = true, desc = "The text to italicize." }, }, inline = { text = { type = "string", required = true, }, options = { type = "record", desc = "Formatting options are applied in the reverse order in which they are listed below. In other words, <code>nowiki</code> is always the outermost tag and <code>i</code> is always the innermost.", properties = { { name = "nowiki", type = "boolean", }, { name = "code", type = "boolean", }, { name = "class", type = "string", }, { name = "tooltip", type = "string", }, { name = "bold", type = "boolean", }, { name = "italic", type = "boolean", }, }, }, }, heading = { level = { type = "number", required = true, desc = "The heading level." , }, text = { type = "string", required = true, desc = "The heading text.", }, }, tooltip = { baseText = { type = "string", required = true, desc = "The text to receive a tooltip.", }, tooltipText = { type = "string", required = true, desc = "The text to display on hover.", }, }, pre = { text = { type = "string", required = true, desc = "Text to render as preformatted.", }, options = { type = "record", properties = { { name = "wrapLines", type = "boolean", default = true, desc = "If set to <code>false</code>, prevents lines from wrapping by setting [https://developer.mozilla.org/en-US/docs/Web/CSS/white-space white-space] to <code>pre</code>." } } } }, lua = { text = { type = "string", required = true, desc = "A string of text to format as Lua code." }, options = { type = "record", properties = { { name = "wrapLines", type = "boolean", default = true, desc = "If set to <code>false</code>, prevents lines from wrapping by setting [https://developer.mozilla.org/en-US/docs/Web/CSS/white-space white-space] to <code>pre</code>." } } } } } end function p.Documentation() return { bold = { params = {"text"}, returns = "The bolded text.", cases = { { args = { "Fooloo Limpah" }, expect = "<b>Fooloo Limpah</b>", }, }, }, italic = { params = {"text"}, returns = "The italicized text.", cases = { { args = { "Fooloo Limpah" }, expect = "<i>Fooloo Limpah</i>", }, }, }, class = { params = {"class", "text"}, returns = "Text wrapped in a span tag with the given class string.", cases = { { args = {"term error", "Fooloo Limpah"}, expect = [[<span class="term error">Fooloo Limpah</span>]] }, }, }, heading = { params = {"level", "text"}, returns = "<code>string</code> of text for the heading", cases = { outputOnly = true, { args = {2, "Section"}, expect = "\n==Section==\n", }, { args = {3, "Sub-section"}, expect = "\n===Sub-section===\n" } } }, tooltip = { params = {"baseText", "tooltipText", "type"}, returns = "Text with a tooltip.", cases = { { args = {"hover over me", "hello world!"}, expect = '<span title="hello world!" class="tooltip">hover over me</span>' }, }, }, code = { params = {"text"}, returns = "The formatted text.", cases = { { args = {"code stuff"}, expect = "<code>code stuff</code>", }, }, }, inline = { params = {"text", "options"}, returns = "The formatted text.", cases = { { args = {"Fooloo Limpah", { class = "error", tooltip = "Don't steal them!", bold = true, italic = true, }, }, expect = [[<span class="error"><span title="Don't steal them!" class="tooltip"><b><i>Fooloo Limpah</i></b></span></span>]], }, { args = {"{{Foo}}", { code = true, nowiki = true, bold = true, } }, expect = "<b><code>{{Foo}}</code></b>", }, }, }, pre = { params = {"text", "options"}, returns = "A block of pre-formatted text.", cases = { resultOnly = true, { args = { [[{{List |foo |bar |baz }}]] } } } }, lua = { params = {"text", "options"}, returns = "A block of pre-formatted, syntax-highlighted Lua code", cases = { resultOnly = true, { args = { [[function(foo) return foo end]] }, } } }, separateMarkup = { desc = "Separates plain text from any wikitext markup that follows it. Used by [[:Category:List templates|list templates]] such as [[Template:Term List]], [[Template:Gallery List]], [[Template:Wares]], etc.", params = {"text"}, returns = { "<code>text</code> with trailing markup stripped off", "Any trailing markup from <code>text</code>, or an empty string if there is none.", }, cases = { outputOnly = true, { args = {"Some Text <sup>Some Markup</sup>"}, expect = {"Some Text", " <sup>Some Markup</sup>"}, }, { args = {"Some Text"}, expect = {"Some Text", ""}, }, }, }, } end return p