Module:FormatSegmentRow

From Bodhicitta
Revision as of 18:04, 10 March 2026 by Jeremi (talk | contribs) (VSCode edit)

Documentation for this module may be created at Module:FormatSegmentRow/doc

local p = {}

-- Language definitions for SscChapterQuery
-- Each entry: { id, params (list of template param names to try), classPrefix, textClass, type }
local languages = {
	{ id = 'tibetan',  params = {'SegmentSource'},                    classPrefix = 'tibetan-version',  textClass = 'text-160',    langType = 'source' },
	{ id = 'tibetan-tsadra', params = {'SegmentSourceTsadra'},              classPrefix = 'tibetan-tsadra-version', textClass = 'text-160',    langType = 'source' },
    { id = 'english',        params = {'SegmentTranslation'},               classPrefix = 'english-version',        textClass = 'text-article', langType = 'translation' },
    { id = 'wylie',    params = {'SourceTranslit'},                   classPrefix = 'wylie-version',    textClass = 'text-article', langType = 'translation' },
    { id = 'wylie-tsadra',   params = {'SegmentTranslitTsadra'},            classPrefix = 'wylie-tsadra-version',   textClass = 'text-article', langType = 'translation' },
    { id = 'french',         params = {'FrenchTranslation', 'French'},      classPrefix = 'french-version',         textClass = 'text-article', langType = 'translation' },
    { id = 'spanish',        params = {'Spanish'},                          classPrefix = 'spanish-version',        textClass = 'text-article', langType = 'translation' },
    { id = 'devanagari',     params = {'SanskritSource'},                   classPrefix = 'devanagari-version',     textClass = 'text-160',    langType = 'source' },
    { id = 'sanskrit',       params = {'SanskritTranslit'},                 classPrefix = 'sanskrit-version',       textClass = 'text-article', langType = 'translation' },
}

-- Priority order for default visible language per side, given available params
local leftPriority  = { 'tibetan', 'tibetan-tsadra', 'devanagari', 'wylie', 'wylie-tsadra', 'sanskrit' }
local rightPriority = { 'english', 'french', 'spanish', 'wylie', 'wylie-tsadra' }

-- Get first non-empty value from a list of param names
local function getParamValue(args, paramNames)
    for _, name in ipairs(paramNames) do
        local val = args[name]
        if val and mw.text.trim(val) ~= '' then
            return mw.text.trim(val)
        end
    end
    return nil
end

-- Resolve default language for a side: first priority-list entry with content in args
local function resolveDefault(args, priorityList)
    local paramsByLang = {}
    for _, lang in ipairs(languages) do
        paramsByLang[lang.id] = lang.params
    end
    for _, id in ipairs(priorityList) do
        local params = paramsByLang[id]
        if params and getParamValue(args, params) then
            return id
        end
    end
    return priorityList[1]
end

-- Convert semicolon-separated page names into wiki links
local function wikiLinkList(str)
    local links = {}
    for page in mw.text.gsplit(str, '%s*;%s*') do
        if page ~= '' then
            table.insert(links, '[[' .. page .. ']]')
        end
    end
    return table.concat(links, ', ')
end

-- Wrap content with poem extension tag (for translation-side verse formats)
local function wrapPoem(frame, content)
    return frame:extensionTag('poem', '<p class="m-0">' .. content .. '</p>')
end

-- Apply SegmentFormat styling to content
-- isSource: true for source-type languages, false for translation-type
local function formatContent(content, format, isSource, frame, sabcheNum, quoteSource)
    if not content then return nil end

    if format == 'Root' then
        if isSource then
            return '<div class="pl-4" style="color: #8c1409;"><p>' .. content .. '</p></div>'
        else
            return '<div class="p-bl-fix pl-4 my-2" style="color: #8c1409;"><p>' .. content .. '</p></div>'
        end

    elseif format == 'Title' then
        if isSource then
            return '<span class="text-130" style="color: #467083;">' .. content .. '</span>'
        else
            return '<div class="h3 font-serif-alt" style="color: #467083; white-space: break-spaces;">' .. content .. '</div>'
        end

    elseif format == 'Commentary' or format == 'Commentary2' or format == 'Colophon' then
        return content

    elseif format == 'Quote' then
        local noteSuffix = ''
        if quoteSource and quoteSource ~= '' then
            noteSuffix = frame:expandTemplate{ title = 'note', args = { 'source', wikiLinkList(quoteSource) } }
        end
        if isSource then
            return '<div class="pl-4" style="color: #897435;">' .. content .. noteSuffix .. '</div>'
        else
            return '<div class="pl-4" style="color: #897435;">' .. wrapPoem(frame, content .. noteSuffix) .. '</div>'
        end

    elseif format == 'DoubleQuote' or format == 'Verse inside a quote' then
        local noteSuffix = ''
        if quoteSource and quoteSource ~= '' then
            noteSuffix = frame:expandTemplate{ title = 'note', args = { 'source', wikiLinkList(quoteSource) } }
        end
        if isSource then
            return '<div class="pl-5" style="color: #897435;">' .. content .. noteSuffix .. '</div>'
        else
            return '<div class="pl-5" style="color: #897435;">' .. wrapPoem(frame, content .. noteSuffix) .. '</div>'
        end

    elseif format == 'Sabche' then
        if isSource then
            return '<span style="color: #467083;">' .. content .. '</span>'
        else
            local sabche = '<div class="p-bl-fix"><span style="color: #467083;">' .. content .. '</span>'
            if sabcheNum then
                sabche = sabche .. ' <span class="float-right">' .. sabcheNum .. '</span>'
            end
            return sabche .. '</div>'
        end

    elseif format == 'SabcheHeading' then
        if isSource then
            return '<div class="mt-3" style="color: #467083;">' .. content .. '</div>'
        else
            local heading = '<div class="h5 mt-3 font-serif-alt" style="color: #467083;">' .. content
            if sabcheNum then
                heading = heading .. ' <span class="float-right">' .. sabcheNum .. '</span>'
            end
            return heading .. '</div>'
        end

    elseif format == 'SabcheSubHeading' then
        if isSource then
            return '<div class="mt-2" style="color: #467083;">' .. content .. '</div>'
        else
            local subheading = '<div class="h6 mt-2 font-serif-alt" style="color: #467083;">' .. content
            if sabcheNum then
                subheading = subheading .. ' <span class="float-right">' .. sabcheNum .. '</span>'
            end
            return subheading .. '</div>'
        end

    elseif format == 'Section Title1' then
        if isSource then
            return content
        else
            return '<div class="h3 font-serif-alt" style="color: #467083; white-space: break-spaces;">' .. content .. '</div>'
        end

    elseif format == 'Section Title2' then
        if isSource then
            return '<span class="text-120" style="color: #467083;">' .. content .. '</span>'
        else
            return '<div class="h4 font-serif-alt" style="color: #467083; white-space: break-spaces;">' .. content .. '</div>'
        end

    elseif format == 'Indented Verse' then
        if isSource then
            return '<div class="pl-4">' .. content .. '</div>'
        else
            return '<div class="pl-4">' .. wrapPoem(frame, content) .. '</div>'
        end

    elseif format == 'Root non-verse' then
        return '<span style="color: #8c1409;">' .. content .. '</span>'

    else
        -- Default: no special formatting
        return content
    end
end

-- Render all language divs for one side (left or right)
local function renderSide(args, side, format, frame, defaultLang)
    local sabcheNum = getParamValue(args, {'SourceSabcheNumber'})
    local quoteSource = getParamValue(args, {'QuoteSource'})
    local parts = {}

    for _, lang in ipairs(languages) do
        local content = getParamValue(args, lang.params)
        if content then
            local isSource = (lang.langType == 'source')
            local formatted = formatContent(content, format, isSource, frame, sabcheNum, quoteSource)

            if formatted then
                local hidden = lang.id ~= defaultLang and ' hidden' or ''
                local classes = 'toggleable ' .. lang.classPrefix .. '-' .. side .. ' ' .. lang.textClass .. hidden
                table.insert(parts, '<div class="' .. classes .. '">' .. formatted .. '</div>')
            end
        end
    end

    return table.concat(parts)
end

function p.main(frame)
    local args = frame:getParent().args
    local format = getParamValue(args, {'SegmentFormat'}) or 'Commentary'

    local defaultLeft  = resolveDefault(args, leftPriority)
    local defaultRight = resolveDefault(args, rightPriority)

    local left = renderSide(args, 'left', format, frame, defaultLeft)
    local right = renderSide(args, 'right', format, frame, defaultRight)

    local leftCol = '<div class="col-md-6 font-serif line14 p-bl-fix mb-3">' .. left .. '</div>'
    local rightCol = '<div class="col-md-6 line14 p-bl-fix mb-3">' .. right .. '</div>'

    return leftCol .. rightCol
end

return p