Module:VolDiff
Jump to navigation
Jump to search
Documentation for this module may be created at Module:VolDiff/doc
local p = {}
-- Helper function to parse chapter number from the chapter link
local function getChapterNumber(chapterLink)
local fullMatch = mw.ustring.match(chapterLink, "%[%[(.-)%]%]")
if fullMatch then
local splitMatch = mw.text.split(fullMatch, "|")
return splitMatch[1]
end
return nil
end
-- Helper function to extract content under a specific section header
local function extractSection(content, header)
-- Find the start of the specified header
local startPattern = header .. "(.-)(==)"
local sectionStart, sectionEnd = mw.ustring.find(content, startPattern)
-- If the section is not found, try to match until the end of the content
if not sectionStart then
local endPattern = header .. "(.-)$"
sectionStart, sectionEnd = mw.ustring.find(content, endPattern)
end
-- If the section is found, find the next section header (either === or ==)
if sectionStart then
local nextHeaderPattern = "==[^=]"
local nextHeaderStart, nextHeaderEnd = mw.ustring.find(content, nextHeaderPattern, sectionEnd + 1)
-- Extract the content until the next section header or the end of the content
if nextHeaderStart then
return mw.ustring.sub(content, sectionStart, nextHeaderStart - 1)
else
return mw.ustring.sub(content, sectionStart)
end
end
-- Return nil if the section is not found
return nil
end
-- Helper function to capture the entire template, including nested braces
local function captureTemplate(content, templateName)
local templateStart, templateEnd = mw.ustring.find(content, "{{%s*" .. templateName .. "%s*[|\n]")
if not templateStart then
return nil, nil, nil
end
local finalTemplate = { mw.ustring.sub(content, templateStart, templateEnd) }
local i = templateEnd + 1
local braceCount = 2 -- Account for the initial "{{"
while i <= mw.ustring.len(content) do
local char = mw.ustring.sub(content, i, i)
table.insert(finalTemplate, char)
if char == '{' then
braceCount = braceCount + 1
elseif char == '}' then
braceCount = braceCount - 1
if braceCount == 0 then
break
end
end
i = i + 1
end
return table.concat(finalTemplate), templateStart, i
end
-- Helper function to capture the entire Desc parameter
local function captureDescParameter(diff)
local descStart, descEnd = mw.ustring.find(diff, "Desc%s*=%s*")
if not descStart then
return nil
end
local finalDesc = {}
local i = descEnd + 1
local braceCount = 0
while i <= mw.ustring.len(diff) - 2 do -- Subtract 2 from length to remove the }} from Diff
local char = mw.ustring.sub(diff, i, i)
table.insert(finalDesc, char)
if char == '{' or char == '[' then
braceCount = braceCount + 1
elseif char == '}' or char == ']' then
if braceCount > 0 then
braceCount = braceCount - 1
else
break
end
elseif char == '|' and braceCount == 0 then
break
end
i = i + 1
end
return mw.text.trim(table.concat(finalDesc))
end
-- Function to find all Diff positions
local function findDiffPositions(content)
local positions = {}
local startPos = 1
while true do
local diffStart, diffEnd = mw.ustring.find(content, "{{%s*Diff%s*[|\n]", startPos)
if not diffStart then
break
end
table.insert(positions, {diffStart, diffEnd})
startPos = diffEnd + 1
end
return positions
end
-- Main function to process the VolDiffs template
function p.main(frame)
local args = frame:getParent().args
local currentTitle = mw.title.getCurrentTitle().text
local sourcePage = args[1]
local sectionType = args[2] or "magazine"
local sectionHeader = sectionType == "reprint" and "===Reprint Differences===" or "===Magazine Differences==="
local result = ""
if not sourcePage then
return "Error: No source page specified."
end
-- Fetch the content from the specified source page
local startTime = os.clock()
local content = mw.title.new(sourcePage):getContent()
if not content then
return "Error: Could not fetch content from the specified source page."
end
-- Timing log: After fetching content
local fetchTime = os.clock()
mw.log('Time after fetching content: ' .. (fetchTime - startTime))
-- Extract the section content
local sectionContent = extractSection(content, sectionHeader)
if not sectionContent then
return "Error: No section found with header " .. sectionHeader
end
-- Timing log: After extracting section content
local sectionTime = os.clock()
mw.log('Time after extracting section content: ' .. (sectionTime - fetchTime))
-- Extract the entire VolDiffs content using brace counting
local volDiffsContent, _, _ = captureTemplate(sectionContent, "VolDiffs")
if not volDiffsContent then
return "Error: No VolDiffs found in the specified section."
end
-- Timing log: After extracting VolDiffs content
local volDiffsTime = os.clock()
mw.log('Time after extracting VolDiffs content: ' .. (volDiffsTime - sectionTime))
-- Extract VolDiffs parameters
local part = mw.ustring.match(volDiffsContent, "Part%s*=%s*([^|]+)") or ""
local title = mw.ustring.match(volDiffsContent, "Title%s*=%s*([^|]+)") or ""
local label1 = mw.ustring.match(volDiffsContent, "Label1%s*=%s*([^|]*)") or ""
local label2 = mw.ustring.match(volDiffsContent, "Label2%s*=%s*([^|]*)") or ""
-- Start the VolDiffs template
result = result .. string.format('{{VolDiffs|Part=%s|Title=%s', part, title)
if label1 ~= "" then result = result .. string.format('|Label1=%s', label1) end
if label2 ~= "" then result = result .. string.format('|Label2=%s', label2) end
result = result .. '|\n'
-- Find all Diff positions
local diffPositions = findDiffPositions(volDiffsContent)
-- Timing log: After finding Diff positions
local diffPositionsTime = os.clock()
mw.log('Time after finding Diff positions: ' .. (diffPositionsTime - volDiffsTime))
-- Process each Diff entry
local hasDiffs = false
local diffEntries = {}
for _, pos in ipairs(diffPositions) do
local diffContent, _, _ = captureTemplate(volDiffsContent:sub(pos[1]), "Diff")
if diffContent then
local diffPart = mw.ustring.match(diffContent, "Part%s*=%s*([^|]+)")
local diffChapter = mw.ustring.match(diffContent, "Chapter%s*=%s*(%[%[.-%]%])")
local diffPage = mw.ustring.match(diffContent, "Page%s*=%s*([^|]+)")
local diffImage1 = mw.ustring.match(diffContent, "Image1%s*=%s*([^|]+)")
local diffImage2 = mw.ustring.match(diffContent, "Image2%s*=%s*([^|]+)")
local diffDesc = captureDescParameter(diffContent)
local diffLabel1 = mw.ustring.match(diffContent, "Label1%s*=%s*([^|]*)") or ""
local diffLabel2 = mw.ustring.match(diffContent, "Label2%s*=%s*([^|]*)") or ""
if diffPart and diffChapter and diffPage and diffImage1 and diffImage2 and diffDesc then
local chapterNumber = getChapterNumber(diffChapter)
-- Check if the current page title matches the chapter number
if chapterNumber and mw.ustring.match(currentTitle, chapterNumber) then
hasDiffs = true
table.insert(diffEntries, string.format('{{Diff|Part=%s|Chapter=%s|Page=%s|Image1=%s|Image2=%s|Desc=%s',
diffPart, diffChapter, diffPage, diffImage1, diffImage2, mw.text.trim(diffDesc)))
-- Add optional labels if they are present
if diffLabel1 ~= "" then table.insert(diffEntries, string.format('|Label1=%s', diffLabel1)) end
if diffLabel2 ~= "" then table.insert(diffEntries, string.format('|Label2=%s', diffLabel2)) end
table.insert(diffEntries, '}}\n')
end
end
end
end
-- Timing log: After processing Diff entries
local processDiffsTime = os.clock()
mw.log('Time after processing Diff entries: ' .. (processDiffsTime - diffPositionsTime))
-- Concatenate all diff entries at once
result = result .. table.concat(diffEntries)
-- End the VolDiffs template or provide a message if no diffs are found
if hasDiffs then
result = result .. '}}'
else
result = "No differences found for this chapter."
end
-- Total time taken
local totalTime = processDiffsTime - fetchTime
mw.log('Total time taken: ' .. totalTime)
return frame:preprocess(result)
end
return p