Module:BCIChapters: Difference between revisions
NeonWabbit (talk | contribs) No edit summary Tag: Reverted |
NeonWabbit (talk | contribs) No edit summary Tag: Manual revert |
||
Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
local special_cases = { | local special_cases = { | ||
["Augustus, You Jerk | ["Augustus, You Jerk 2"] = { seq = 24, title = "Augustus, You Jerk #2" } | ||
} | } | ||
function p.urlDecode(str) | function p.urlDecode(str) | ||
str = string.gsub(str, '%%(%x%x)', function(x) return string.char(tonumber(x, 16)) end) | str = string.gsub(str, '%%(%x%x)', function(x) return string.char(tonumber(x, 16)) end) | ||
Line 12: | Line 10: | ||
end | end | ||
function p.normalizeApostrophes(str) | function p.normalizeApostrophes(str) | ||
str = string.gsub(str, "’", "'") | str = string.gsub(str, "’", "'") | ||
Line 20: | Line 17: | ||
end | end | ||
function p.getChaptersList() | function p.getChaptersList() | ||
local listPage = mw.title.new('Template:BCIChapterList') | local listPage = mw.title.new('Template:BCIChapterList') | ||
Line 32: | Line 28: | ||
end | end | ||
-- Normalize apostrophes in content | |||
content = p.normalizeApostrophes(content) | content = p.normalizeApostrophes(content) | ||
Line 42: | Line 39: | ||
end | end | ||
function p.getChapterDetails(chapterTitle, detail) | function p.getChapterDetails(chapterTitle, detail) | ||
local chapters = p.getChaptersList() | local chapters = p.getChaptersList() | ||
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 52: | Line 49: | ||
end | end | ||
end | end | ||
-- | -- Check for special cases | ||
local special_case = special_cases[chapterTitle] | |||
local | if special_case then | ||
for _, chapter in ipairs(chapters) do | for _, chapter in ipairs(chapters) do | ||
if chapter.seq == special_case.seq then | |||
return chapter[detail] | |||
end | |||
end | end | ||
end | end | ||
return nil | return nil | ||
end | end | ||
function p.getNextChapter(seq) | |||
function p. | |||
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 | ||
return chapters[i + 1].title | |||
end | end | ||
end | end | ||
return nil | return nil | ||
end | end | ||
function p.getPreviousChapter(seq) | |||
function p. | |||
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 | ||
return chapters[i - 1].title | |||
end | end | ||
end | end | ||
return nil | return nil | ||
end | end | ||
function p.formatDate(date) | function p.formatDate(date) | ||
local year, month, day = string.match(date, "(%d+)%-(%d+)%-(%d+)") | local year, month, day = string.match(date, "(%d+)%-(%d+)%-(%d+)") | ||
Line 100: | Line 96: | ||
end | end | ||
function p.infoboxBCIChapter(frame) | function p.infoboxBCIChapter(frame) | ||
local chapterTitle = frame.args.chapter_title or mw.title.getCurrentTitle().text | local chapterTitle = frame.args.chapter_title or mw.title.getCurrentTitle().text | ||
Line 113: | Line 108: | ||
caption = caption and caption ~= "" and caption or nil | caption = caption and caption ~= "" and caption or nil | ||
local seq = p.getChapterDetails(normalizedTitle, "seq") | |||
local seq = | if not seq then | ||
local date = p. | local special_case = special_cases[chapterTitle] | ||
local pagecount = p. | if special_case then | ||
local next_chapter = p. | seq = special_case.seq | ||
local prev_chapter = p. | 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') | local infobox = mw.html.create('table') | ||
Line 130: | Line 135: | ||
:css('font-size', '125%') | :css('font-size', '125%') | ||
:css('padding', '5px') | :css('padding', '5px') | ||
:wikitext( | :wikitext(normalizedTitle) | ||
:done() | :done() | ||
:done() | :done() | ||
Line 206: | Line 211: | ||
nav_row:tag('td') | nav_row:tag('td') | ||
:css('text-align', 'left') | :css('text-align', 'left') | ||
:wikitext(prev_chapter ~= "N/A" and string.format("[[%s|← %s]]", | :wikitext(prev_chapter ~= "N/A" and string.format("[[%s|← %s]]", p.getSafeTitle(prev_chapter), prev_chapter) or "← Previous") | ||
:done() | :done() | ||
nav_row:tag('td') | nav_row:tag('td') | ||
:css('text-align', 'right') | :css('text-align', 'right') | ||
:wikitext(next_chapter ~= "N/A" and string.format("[[%s|%s →]]", | :wikitext(next_chapter ~= "N/A" and string.format("[[%s|%s →]]", p.getSafeTitle(next_chapter), next_chapter) or "Next →") | ||
:done() | :done() | ||
nav_row:done() | nav_row:done() | ||
Line 225: | Line 230: | ||
-- Return the complete wikitext | -- Return the complete wikitext | ||
return frame:preprocess(tostring(infobox)) | 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 | end | ||
return p | return p |
Revision as of 16:26, 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, "'", "'")
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.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 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