Module:RainbowSquare

--

-- Demonstration of HTML node reuse. -- -- The functions `p._main_v2` and `p.main_v2` perform significantly better than -- `p._main_v1` and `p.main_v1`, because the former reuse HTML nodes. As proof, -- try running the following code in the debug console: -- --[=[

local inspect = require("Dev:Inspect") local text = "This is a test." local square_v1 = p._main_v1(text) local square_v2 = p._main_v2(text)

mw.log("square_v1") mw.log(inspect(square_v1)) mw.log(string.rep("\n", 30)) -- separator mw.log("square_v2") mw.log(inspect(square_v2))

--]=] -- -- Although they produce identical HTML when converted to strings, the internal -- representation of `square_v1` contains about 210 more nodes than that of -- `square_v2`. Consequently, the former requires significantly more memory to -- create and store, and is more likely to trigger Scribunto errors.

local p = {} local getArgs = require("Dev:Arguments").getArgs

-- Constructs a square of text, where the first row is a given string, and each -- subsequent row is identical to its predecessor with the first character -- moved to the end. A rainbow gradient is applied to the square, starting at -- the top-left and ending at the bottom-right. -- -- @param {string} text --    The text to transform. -- @returns {table} --    The resulting rainbow square.

function p._main_v1(text) -- This tag will not escape wikitext unless we preprocess it. local square = mw.html.create("pre")

for rowNo = 1, #text do       if rowNo > 1 then -- Mercury doesn't render line feed characters (U+000A), even when -- wikitext is wrapped in a tag and escaped. square:tag("br") end

for colNo = 1, #text do           local hue = (360 / #text) * (colNo - 1)

square:tag("span") :css("color", "hsl(" .. hue .. ", 100%, 50%)")               :wikitext(text:sub(colNo, colNo)) end end

return square end

-- Constructs a square of text, where the first row is a given string, and each -- subsequent row is identical to its predecessor with the first character -- moved to the end. A rainbow gradient is applied to the square, starting at -- the top-left and ending at the bottom-right. -- -- @param {table} frame --    Frame object. -- @param {string} frame[1] --    The text to transform. -- @returns {table} --    The resulting rainbow square.

function p.main_v1(frame) local args = getArgs(frame) local text = args[1] or ""

return p._main_v1(text) end

-- Constructs a square of text, where the first row is a given string, and each -- subsequent row is identical to its predecessor with the first character -- moved to the end. A rainbow gradient is applied to the square, starting at -- the top-left and ending at the bottom-right. -- -- @param {string} text --    The text to transform. -- @returns {table} --    The resulting rainbow square.

function p._main_v2(text) -- This tag will not escape wikitext unless we preprocess it. local square = mw.html.create("pre")

-- Mercury doesn't render line feed characters (U+000A), even when wikitext -- is wrapped in a tag and escaped. local newline = mw.html.create("br")

for rowNo = 1, #text do       if rowNo > 1 then -- Reuse the tag instead of creating a new one for each -- iteration. square:node(newline) end

for colNo = 1, #text do           if rowNo == 1 then local hue = (360 / #text) * (colNo - 1)

-- Generate nodes on the first iteration. square:tag("span") :css("color", "hsl(" .. hue .. ", 100%, 50%)")                   :wikitext(text:sub(colNo, colNo)) else local nodeIndex = (rowNo + colNo - 2) % #text + 1

-- Reuse nodes on subsequent iterations. square:node(square.nodes[nodeIndex]) end end end

return square end

-- Constructs a square of text, where the first row is a given string, and each -- subsequent row is identical to its predecessor with the first character -- moved to the end. A rainbow gradient is applied to the square, starting at -- the top-left and ending at the bottom-right. -- -- @param {table} frame --    Frame object. -- @param {string} frame[1] --    The text to transform. -- @returns {table} --    The resulting rainbow square.

function p.main_v2(frame) local args = getArgs(frame) local text = args[1] or ""

return p._main_v2(text) end

return p