Module:PsalmFunctions
From Psalms: Layer by Layer
Documentation for this module may be created at Module:PsalmFunctions/doc
local p = {} function p.getPsalmNumber(frame) -- Get the current page name local pageName = mw.title.getCurrentTitle().text -- Check if "Psalm" exists in the page name if not pageName:find("Psalm") then return "19" -- Return 1 if "Psalm" is not found end -- Extract the part of the page name after "Psalm " local psalmNumber = pageName:match("Psalm%s*(%d+)") return psalmNumber or "19" end function p.encode(frame) local text = frame.args[1] or "" text = mw.text.encode(text) -- Converts <, >, &, etc. to HTML entities return text end function p.encode_brackets_pipes(frame) local text = frame.args[1] or "" -- Replace only brackets and pipes with URL encoding text = text:gsub("%[", "%%5B") -- Encode '[' as '%5B' :gsub("%]", "%%5D") -- Encode ']' as '%5D' :gsub("%|", "%%7C") -- Encode '|' as '%7C' :gsub("%=", "%%3D") -- Encode '=' as '%3D' return text end function p.decode_brackets_pipes(frame) local text = frame.args[1] or "" -- Replace only brackets and pipes with URL encoding text = text:gsub("%%5B","%[") :gsub("%%5D","%]") :gsub("%%7C","|") :gsub("%%3C","<") :gsub("%%3E",">") :gsub("%%3D","=") return text end function p.escape_equals(frame) local text = frame.args[1] or "" -- Replace only brackets and pipes with URL encoding text = text:gsub("=", "{{=}}}}") return text end function p.url_encode(frame) local text = frame.args[1] or "" text = text:gsub("\n", "\r\n") -- Convert newlines to CRLF text = text:gsub("([^%w%-%.%_%~])", function(c) return string.format("%%%02X", string.byte(c)) -- Convert special characters to %XX format end) return text end function p.url_decode(frame) local text = frame.args[1] or "" text = text:gsub("%%(%x%x)", function(hex) return string.char(tonumber(hex, 16)) -- Convert hex code to character end) return text end function p.makeID(frame) local str = frame.args[1] or "" -- Ensure we only return the modified string, avoiding unintended second return values str = str:gsub("%s+", "-") -- Replace spaces with hyphens :gsub("%.", "") -- Remove periods :gsub(",", "-") -- Replace commas with hyphens return str end function p.validPageName(frame) local str = frame.args[1] or "" -- Ensure we only return the modified string, avoiding unintended second return values str = str:gsub("%s+", "_") return str end function p.listSubpages(frame) local prefix = frame.args[1] or mw.title.getCurrentTitle().prefixedText local namespace = mw.title.getCurrentTitle().namespace local limit = tonumber(frame.args[2]) or 50 -- Set a reasonable limit (default: 50) -- Call the MediaWiki API to get subpages local api = mw.ext.data and mw.ext.data.getAllPageNames if not api then return "Error: API function not available. Check your MediaWiki configuration." end local pages = api({ namespace = namespace, prefix = prefix .. "/", limit = limit }) if not pages or #pages == 0 then return "No subpages found for: " .. prefix end -- Format the list of subpages local result = {} for _, page in ipairs(pages) do table.insert(result, "[[" .. page .. "]]") end return table.concat(result, "<br>") end -- used for VxV Notes tables local function splitLines(text) local lines = {} for line in mw.text.gsplit(text, "<br%s*/?>") do table.insert(lines, mw.text.trim(line)) end return lines end function p.buildVerseTable(frame) local args = frame.args local verse = mw.text.trim(args[1] or "?") local hebrewText = args[2] local englishText = args[3] local hebrewLines = splitLines(hebrewText or "") local englishLines = splitLines(englishText or "") local output = {} table.insert(output, '{| class="wikitable"\n|-\n! v. !! Hebrew !! Close-but-clear') for i, heb in ipairs(hebrewLines) do local partLetter = string.char(96 + i) -- 1 = a, 2 = b, etc. local eng = englishLines[i] or '' table.insert(output, string.format('|-\n|%s%s ||%s ||%s', verse, partLetter, heb, eng)) end table.insert(output, '|}') return table.concat(output, '\n') end function p.random(frame) local min = tonumber(frame.args[1]) or 1 local max = tonumber(frame.args[2]) or 1000 return math.random(min, max) end function p.TabbedContentHeaders(frame) local args = frame.args local names = mw.text.split(args[1] or "", ",") local parentID = args[2] or "parentID" local result = {} for i, name in ipairs(names) do table.insert(result, frame:expandTemplate{ title = "TabbedContent/Header", args = { ParentID = parentID, ID = tostring(i), Title = mw.text.trim(name), Style = "header" } }) end return table.concat(result, "\n") end function p.TabbedContentSubPages(frame) local args = frame.args local names = mw.text.split(args[1] or "", ",") local parentID = mw.text.trim(args[2] or "parentID"):gsub("_$", "") local currentPage = mw.title.getCurrentTitle().fullText local result = {} for i, name in ipairs(names) do local subpageName = mw.text.trim(name) local fullPageName = currentPage .. "/" .. subpageName local transclusion = frame:preprocess('{{:' .. fullPageName .. '}}') local divEnd = '</div>' table.insert(result, frame:expandTemplate{ title = "TabbedContent/Header", args = { ParentID = parentID, ID = tostring(i), Title = mw.text.trim(name), Style = "body" } }) table.insert(result, transclusion) table.insert(result, divEnd) end return table.concat(result, "\n") end function p.TabbedContentAnnotations(frame) local args = frame.args local names = mw.text.split(args[1] or "", ",") local parentID = mw.text.trim(args[2] or "parentID"):gsub("_$", "") local chapter = mw.text.trim(args[3] or "19") local result = {} for i, name in ipairs(names) do local subpageName = mw.text.trim(name) local divID = parentID .. "-" .. tostring(i) local divClass = "tab-pane fade" .. (i == 1 and " show active" or "") local labelFor = divID .. "Label" -- Build the full page title of the rendered subpage local renderedTitle = string.format("Psalm %s/Overlays/%s/Rendered", chapter, subpageName) local titleObj = mw.title.new(renderedTitle) local bodyContent = "" if titleObj and titleObj.exists then -- Transclude the rendered page bodyContent = string.format("{{:%s}}", renderedTitle) else -- Fall back to rendering it dynamically bodyContent = string.format("{{Psalm/Table |Chapter=%s|annotations=%s|speakerbars=no|sections=no}}", chapter, subpageName) end table.insert(result, string.format( '<div id="%s" class="%s" role="tabpanel" aria-labelledby="%s">%s</div>', divID, divClass, labelFor, bodyContent )) end return frame:preprocess(table.concat(result, "\n")) end function p.setPropertiesFromArgs(frame) local args = frame:getParent().args local out = {} for name, value in pairs(args) do name = mw.text.trim(name) value = mw.text.trim(value) if name ~= "" and value ~= "" then table.insert(out, string.format('%s: [[%s::%s]]', name, name, value)) table.insert(out, "<br/>") end end return table.concat(out, "\n") end function p.setSubobjectFromArgs(frame) local args = frame:getParent().args local category = frame.args[1] or "subobject" local out = {} local subobject = {} table.insert(subobject, '{{#subobject:') table.insert(subobject, string.format('|IsCategory=%s', category)) table.insert(subobject, string.format('|Chapter=%s', p.getPsalmNumber(frame))) for name, value in pairs(args) do name = mw.text.trim(name) value = mw.text.trim(value) if name ~= "" and value ~= "" then table.insert(subobject, string.format('|%s=%s', name, value)) end end table.insert(subobject, "}}") table.insert(out, frame:preprocess(table.concat(subobject, "\n"))) return "" end function p.setVersePropertiesFromArgs(frame) local args = frame:getParent().args local category = frame.args[1] or "HebrewText" local out = {} for name, value in pairs(args) do name = mw.text.trim(name) value = mw.text.trim(value) local subobject = {} if name ~= "" and value ~= "" then local number, part = string.match(name, "^(%d+)([a-z]?)$") table.insert(subobject, '{{#subobject:') table.insert(subobject, string.format('|IsCategory=%s', category)) table.insert(subobject, "|Chapter={{CurrentChapter}}") table.insert(subobject, string.format('|Reference=Psalm {{CurrentChapter}}/%s', name)) table.insert(subobject, string.format('|VersePortion=%s', name)) if number then table.insert(subobject, string.format('|Verse=%s', number)) end if part and part ~= "" then table.insert(subobject, string.format('|VersePart=%s', part)) end table.insert(subobject, string.format('|Text=%s', value)) table.insert(subobject, "}}") table.insert(out, frame:preprocess(table.concat(subobject, "\n"))) end end return "" end function p.psalmImages(frame) local output = {} local total = tonumber(frame.args[1]) or 150 -- default to 150 Psalms local perRow = tonumber(frame.args[2]) or 5 for i = 1, total do table.insert(output, frame:preprocess(string.format("{{PsalmImage|%d|%d}}", i, perRow))) end return table.concat(output, " ") end function p.GenerateDiagramID(frame) local str = frame.args[1] or "" -- Ensure we only return the modified string, avoiding unintended second return values str = str:gsub("%s+", "-") -- Replace spaces with hyphens :gsub("%.", "") -- Remove periods :gsub(",", "-") -- Replace commas with hyphens :gsub("[%s/\\]+", "-") -- turn spaces/slashes into dashes :gsub("[^%w%-]+", "") -- remove non-word characters except dashes :gsub("%-+", "-") -- collapse multiple dashes into one :gsub("^%-+", "") -- trim leading dashes :gsub("%-+$", "") -- trim trailing dashes return str end function p.renderWikitext(frame) local input = frame.args[1] or '' return frame:preprocess(input) end return p