Module:BCIChapters: Difference between revisions

From Candypedia
No edit summary
No edit summary
Line 43: Line 43:
     local decodedTitle = p.urlDecode(chapterTitle)
     local decodedTitle = p.urlDecode(chapterTitle)
     local normalizedTitle = p.normalizeApostrophes(decodedTitle)
     local normalizedTitle = p.normalizeApostrophes(decodedTitle)
     for _, chapter in ipairs(chapters) do
     for _, chapter in ipairs(chapters) do
         if chapter.title == normalizedTitle then
         if chapter.title == normalizedTitle then
Line 48: Line 49:
         end
         end
     end
     end
    return nil
end


function p.getChapterDetailsBySeq(seq, detail)
     -- Check for special cases
     seq = tonumber(seq) -- Ensure seq is a number
     local special_case = special_cases[chapterTitle]
     local chapters = p.getChaptersList()
     if special_case then
     for _, chapter in ipairs(chapters) do
        for _, chapter in ipairs(chapters) do
        if chapter.seq == seq then
            if chapter.seq == special_case.seq then
            return chapter[detail]
                return chapter[detail]
            end
         end
         end
     end
     end
     return nil
     return nil
end
end


function p.getNextChapterBySeq(seq)
function p.getNextChapter(seq)
    seq = tonumber(seq) -- Ensure seq is a number
     local chapters = p.getChaptersList()
     local chapters = p.getChaptersList()
     for i, chapter in ipairs(chapters) do
     for i, chapter in ipairs(chapters) do
         if chapter.seq == seq and i < #chapters then
         if chapter.seq == seq and i < #chapters then
Line 70: Line 71:
         end
         end
     end
     end
     return nil
     return nil
end
end


function p.getPreviousChapterBySeq(seq)
function p.getPreviousChapter(seq)
    seq = tonumber(seq) -- Ensure seq is a number
     local chapters = p.getChaptersList()
     local chapters = p.getChaptersList()
     for i, chapter in ipairs(chapters) do
     for i, chapter in ipairs(chapters) do
         if chapter.seq == seq and i > 1 then
         if chapter.seq == seq and i > 1 then
Line 81: Line 83:
         end
         end
     end
     end
     return nil
     return nil
end
end


function p.getNextChapter(chapterTitle)
function p.infoboxBCIChapter(frame)
     local chapters = p.getChaptersList()
     local chapterTitle = frame.args.chapter_title or mw.title.getCurrentTitle().text
     local decodedTitle = p.urlDecode(chapterTitle)
     local decodedTitle = p.urlDecode(chapterTitle)
     local normalizedTitle = p.normalizeApostrophes(decodedTitle)
     local normalizedTitle = p.normalizeApostrophes(decodedTitle)
     for i, chapter in ipairs(chapters) do
     local image = frame.args.image
        if chapter.title == normalizedTitle and i < #chapters then
    local caption = frame.args.caption
            return chapters[i + 1].title
    local major_characters = frame.args.major_characters
        end
    local minor_characters = frame.args.minor_characters
     end
    local locations = frame.args.locations
    return nil
 
end
     caption = caption and caption ~= "" and caption or nil


function p.getPreviousChapter(chapterTitle)
     local seq = p.getChapterDetails(normalizedTitle, "seq")
     local chapters = p.getChaptersList()
     if not seq then
     local decodedTitle = p.urlDecode(chapterTitle)
        local special_case = special_cases[chapterTitle]
    local normalizedTitle = p.normalizeApostrophes(decodedTitle)
         if special_case then
    for i, chapter in ipairs(chapters) do
             seq = special_case.seq
         if chapter.title == normalizedTitle and i > 1 then
             return chapters[i - 1].title
         end
         end
     end
     end
    return nil
end
function p.formatDate(date)
    local year, month, day = string.match(date, "(%d+)%-(%d+)%-(%d+)")
    if year and month and day then
        return string.format("{{Start date|%s|%s|%s}}", year, month, day)
    else
        return date
    end
end
function p.infoboxBCIChapter(frame)
    local chapterTitle = frame.args.chapter_title or mw.title.getCurrentTitle().text
    local seq = frame.args.seq
    local chapterData


     if special_cases[chapterTitle] then
     if not seq then
         seq = special_cases[chapterTitle].seq
         return "No data found for chapter sequence number."
     end
     end


     if seq then
     local date = p.getChapterDetails(normalizedTitle, "date") or "N/A"
        seq = tonumber(seq) -- Ensure seq is a number
     local pagecount = p.getChapterDetails(normalizedTitle, "pagecount") or "N/A"
        chapterData = {
    local next_chapter = p.getNextChapter(seq) or "N/A"
            title = special_cases[chapterTitle] and special_cases[chapterTitle].title or chapterTitle,
    local prev_chapter = p.getPreviousChapter(seq) or "N/A"
            date = p.getChapterDetailsBySeq(seq, "date"),
            pagecount = p.getChapterDetailsBySeq(seq, "pagecount"),
            next_chapter = p.getNextChapterBySeq(seq),
            prev_chapter = p.getPreviousChapterBySeq(seq)
        }
     else
        chapterData = {
            title = chapterTitle,
            date = p.getChapterDetails(chapterTitle, "date"),
            pagecount = p.getChapterDetails(chapterTitle, "pagecount"),
            next_chapter = p.getNextChapter(chapterTitle),
            prev_chapter = p.getPreviousChapter(chapterTitle)
        }
    end


     local infobox = mw.html.create('table')
     local infobox = mw.html.create('table')
Line 155: Line 126:
             :css('font-size', '125%')
             :css('font-size', '125%')
             :css('padding', '5px')
             :css('padding', '5px')
             :wikitext(chapterData.title)
             :wikitext(normalizedTitle)
             :done()
             :done()
         :done()
         :done()


     -- Optionally add image with standard size
     -- Optionally add image with standard size
    local image = frame.args.image
    local caption = frame.args.caption
     if image and image ~= "" then
     if image and image ~= "" then
         infobox:tag('tr')
         infobox:tag('tr')
Line 172: Line 141:


         -- Add caption below image if provided
         -- Add caption below image if provided
         if caption and caption ~= "" then
         if caption then
             infobox:tag('tr')
             infobox:tag('tr')
                 :tag('td')
                 :tag('td')
Line 187: Line 156:
     infobox:tag('tr')
     infobox:tag('tr')
         :tag('th'):wikitext('Published'):done()
         :tag('th'):wikitext('Published'):done()
         :tag('td'):wikitext(p.formatDate(chapterData.date or "N/A")):done()
         :tag('td'):wikitext(p.formatDate(date)):done()
         :done()
         :done()


     infobox:tag('tr')
     infobox:tag('tr')
         :tag('th'):wikitext('Page count'):done()
         :tag('th'):wikitext('Page count'):done()
         :tag('td'):wikitext(chapterData.pagecount or "N/A"):done()
         :tag('td'):wikitext(pagecount):done()
         :done()
         :done()


     -- Add additional parameters
     -- Add additional manual entry parameters
     local major_characters = frame.args.major_characters
     if major_characters and major_characters ~= "" then
     local minor_characters = frame.args.minor_characters
        infobox:tag('tr')
     local locations = frame.args.locations
            :tag('th'):wikitext('Major characters'):done()
            :tag('td'):wikitext(major_characters):done()
            :done()
    end
 
     if minor_characters and minor_characters ~= "" then
        infobox:tag('tr')
            :tag('th'):wikitext('Minor characters'):done()
            :tag('td'):wikitext(minor_characters):done()
            :done()
    end
 
     if locations and locations ~= "" then
        infobox:tag('tr')
            :tag('th'):wikitext('Locations'):done()
            :tag('td'):wikitext(locations):done()
            :done()
    end


if major_characters and major_characters ~= "" then
    -- Add chapter navigation heading
     infobox:tag('tr')
     infobox:tag('tr')
         :tag('th'):wikitext('Major characters'):done()
         :tag('th')
        :tag('td'):wikitext(major_characters):done()
            :attr('colspan', '2')
            :css('text-align', 'center')
            :css('font-size', '110%')
            :css('padding', '5px')
            :css('background-color', '#f0f0f0')
            :wikitext('Chapter navigation')
            :done()
         :done()
         :done()
end


if minor_characters and minor_characters ~= "" then
    -- Add chapter navigation links in separate columns
     infobox:tag('tr')
     local nav_row = infobox:tag('tr')
        :tag('th'):wikitext('Minor characters'):done()
    nav_row:tag('td')
        :tag('td'):wikitext(minor_characters):done()
        :css('text-align', 'left')
        :wikitext(prev_chapter ~= "N/A" and string.format("[[%s|← %s]]", p.getSafeTitle(prev_chapter), prev_chapter) or "← Previous")
        :done()
    nav_row:tag('td')
        :css('text-align', 'right')
        :wikitext(next_chapter ~= "N/A" and string.format("[[%s|%s →]]", p.getSafeTitle(next_chapter), next_chapter) or "Next →")
         :done()
         :done()
end
    nav_row:done()


if locations and locations ~= "" then
    -- Add link to read chapter in BCI Members' Library
     infobox:tag('tr')
     infobox:tag('tr')
         :tag('th'):wikitext('Locations'):done()
         :tag('td')
        :tag('td'):wikitext(locations):done()
            :attr('colspan', '2')
            :css('text-align', 'center')
            :wikitext("[https://bittersweetcandybowl.com/members/ Read in the BCI Members' Library]")
            :done()
         :done()
         :done()
    -- Return the complete wikitext
    return frame:preprocess(tostring(infobox))
end
end


-- Add chapter navigation heading
function p.getSafeTitle(title)
infobox:tag('tr')
     for page, details in pairs(special_cases) do
     :tag('th')
         if details.title == title then
        :attr('colspan', '2')
            return page
        :css('text-align', 'center')
        end
         :css('font-size', '110%')
     end
        :css('padding', '5px')
     return title
        :css('background-color', '#f0f0f0')
        :wikitext('Chapter navigation')
        :done()
    :done()
 
-- Add chapter navigation links in separate columns
local nav_row = infobox:tag('tr')
nav_row:tag('td')
    :css('text-align', 'left')
    :wikitext(chapterData.prev_chapter ~= "N/A" and string.format("[[%s|← %s]]", special_cases[chapterData.prev_chapter] and special_cases[chapterData.prev_chapter].title or chapterData.prev_chapter, chapterData.prev_chapter) or "← Previous")
    :done()
nav_row:tag('td')
    :css('text-align', 'right')
    :wikitext(chapterData.next_chapter ~= "N/A" and string.format("[[%s|%s →]]", special_cases[chapterData.next_chapter] and special_cases[chapterData.next_chapter].title or chapterData.next_chapter, chapterData.next_chapter) or "Next →")
    :done()
nav_row:done()
 
-- Add link to read chapter in BCI Members' Library
infobox:tag('tr')
     :tag('td')
        :attr('colspan', '2')
        :css('text-align', 'center')
        :wikitext("[https://bittersweetcandybowl.com/members/ Read in the BCI Members' Library]")
        :done()
     :done()
 
-- Return the complete wikitext
return frame:preprocess(tostring(infobox))
end
end


return p
return p

Revision as of 14:29, 27 May 2024

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

local p = {}

local special_cases = {
    ["Augustus, You Jerk 2"] = { seq = 24, title = "Augustus, You Jerk #2" }
}

function p.urlDecode(str)
    str = string.gsub(str, '%%(%x%x)', function(x) return string.char(tonumber(x, 16)) end)
    return str
end

function p.normalizeApostrophes(str)
    str = string.gsub(str, "’", "'")
    str = string.gsub(str, "&#39;", "'")
    str = string.gsub(str, "%%27", "'")
    return str
end

function p.getChaptersList()
    local listPage = mw.title.new('Template:BCIChapterList')
    if not listPage then
        return {}
    end

    local content = listPage:getContent()
    if not content then
        return {}
    end

    -- Normalize apostrophes in content
    content = p.normalizeApostrophes(content)

    local chapters = {}
    for seq, title, date, pagecount in string.gmatch(content, "{{BCIChapter|seq=(%d+)|title=([^|]+)|date=([^|]+)|pagecount=(%d+)}}") do
        table.insert(chapters, {seq = tonumber(seq), title = title, date = date, pagecount = tonumber(pagecount)})
    end

    return chapters
end

function p.getChapterDetails(chapterTitle, detail)
    local chapters = p.getChaptersList()
    local decodedTitle = p.urlDecode(chapterTitle)
    local normalizedTitle = p.normalizeApostrophes(decodedTitle)

    for _, chapter in ipairs(chapters) do
        if chapter.title == normalizedTitle then
            return chapter[detail]
        end
    end

    -- Check for special cases
    local special_case = special_cases[chapterTitle]
    if special_case then
        for _, chapter in ipairs(chapters) do
            if chapter.seq == special_case.seq then
                return chapter[detail]
            end
        end
    end

    return nil
end

function p.getNextChapter(seq)
    local chapters = p.getChaptersList()

    for i, chapter in ipairs(chapters) do
        if chapter.seq == seq and i < #chapters then
            return chapters[i + 1].title
        end
    end

    return nil
end

function p.getPreviousChapter(seq)
    local chapters = p.getChaptersList()

    for i, chapter in ipairs(chapters) do
        if chapter.seq == seq and i > 1 then
            return chapters[i - 1].title
        end
    end

    return nil
end

function p.infoboxBCIChapter(frame)
    local chapterTitle = frame.args.chapter_title or mw.title.getCurrentTitle().text
    local decodedTitle = p.urlDecode(chapterTitle)
    local normalizedTitle = p.normalizeApostrophes(decodedTitle)
    local image = frame.args.image
    local caption = frame.args.caption
    local major_characters = frame.args.major_characters
    local minor_characters = frame.args.minor_characters
    local locations = frame.args.locations

    caption = caption and caption ~= "" and caption or nil

    local seq = p.getChapterDetails(normalizedTitle, "seq")
    if not seq then
        local special_case = special_cases[chapterTitle]
        if special_case then
            seq = special_case.seq
        end
    end

    if not seq then
        return "No data found for chapter sequence number."
    end

    local date = p.getChapterDetails(normalizedTitle, "date") or "N/A"
    local pagecount = p.getChapterDetails(normalizedTitle, "pagecount") or "N/A"
    local next_chapter = p.getNextChapter(seq) or "N/A"
    local prev_chapter = p.getPreviousChapter(seq) or "N/A"

    local infobox = mw.html.create('table')
    infobox:addClass('infobox')

    -- Add title as heading
    infobox:tag('tr')
        :tag('th')
            :attr('colspan', '2')
            :css('text-align', 'center')
            :css('font-size', '125%')
            :css('padding', '5px')
            :wikitext(normalizedTitle)
            :done()
        :done()

    -- Optionally add image with standard size
    if image and image ~= "" then
        infobox:tag('tr')
            :tag('td')
                :attr('colspan', '2')
                :css('text-align', 'center')
                :wikitext('[[File:' .. image .. '|250px]]')
                :done()
            :done()

        -- Add caption below image if provided
        if caption then
            infobox:tag('tr')
                :tag('td')
                    :attr('colspan', '2')
                    :css('text-align', 'center')
                    :css('font-size', '90%')
                    :css('padding', '5px')
                    :wikitext(caption)
                    :done()
                :done()
        end
    end

    infobox:tag('tr')
        :tag('th'):wikitext('Published'):done()
        :tag('td'):wikitext(p.formatDate(date)):done()
        :done()

    infobox:tag('tr')
        :tag('th'):wikitext('Page count'):done()
        :tag('td'):wikitext(pagecount):done()
        :done()

    -- Add additional manual entry parameters
    if major_characters and major_characters ~= "" then
        infobox:tag('tr')
            :tag('th'):wikitext('Major characters'):done()
            :tag('td'):wikitext(major_characters):done()
            :done()
    end

    if minor_characters and minor_characters ~= "" then
        infobox:tag('tr')
            :tag('th'):wikitext('Minor characters'):done()
            :tag('td'):wikitext(minor_characters):done()
            :done()
    end

    if locations and locations ~= "" then
        infobox:tag('tr')
            :tag('th'):wikitext('Locations'):done()
            :tag('td'):wikitext(locations):done()
            :done()
    end

    -- Add chapter navigation heading
    infobox:tag('tr')
        :tag('th')
            :attr('colspan', '2')
            :css('text-align', 'center')
            :css('font-size', '110%')
            :css('padding', '5px')
            :css('background-color', '#f0f0f0')
            :wikitext('Chapter navigation')
            :done()
        :done()

    -- Add chapter navigation links in separate columns
    local nav_row = infobox:tag('tr')
    nav_row:tag('td')
        :css('text-align', 'left')
        :wikitext(prev_chapter ~= "N/A" and string.format("[[%s|← %s]]", p.getSafeTitle(prev_chapter), prev_chapter) or "← Previous")
        :done()
    nav_row:tag('td')
        :css('text-align', 'right')
        :wikitext(next_chapter ~= "N/A" and string.format("[[%s|%s →]]", p.getSafeTitle(next_chapter), next_chapter) or "Next →")
        :done()
    nav_row:done()

    -- Add link to read chapter in BCI Members' Library
    infobox:tag('tr')
        :tag('td')
            :attr('colspan', '2')
            :css('text-align', 'center')
            :wikitext("[https://bittersweetcandybowl.com/members/ Read in the BCI Members' Library]")
            :done()
        :done()

    -- Return the complete wikitext
    return frame:preprocess(tostring(infobox))
end

function p.getSafeTitle(title)
    for page, details in pairs(special_cases) do
        if details.title == title then
            return page
        end
    end
    return title
end

return p