Module:Cite
This module is used by Template:Cite to generate a citation based on a book title. See the template page for more documentation.
local p = {}
-- Helper: Get all labels from a list of claims
local function getLabelsFromClaims(claims)
local labels = {}
for _, claim in ipairs(claims or {}) do
if claim.mainsnak and claim.mainsnak.datavalue then
local id = claim.mainsnak.datavalue.value.id
local label = mw.wikibase.getLabel(id)
if label then table.insert(labels, label) end
end
end
return labels
end
-- Helper: Format contributors, apply "et al." if needed
local function formatContributors(contributors)
local n = #contributors
if n == 0 then return "" end
if n > 10 then
local firstSeven = {}
for i = 1, 7 do table.insert(firstSeven, contributors[i]) end
return table.concat(firstSeven, ", ") .. ", et al."
else
return table.concat(contributors, ", ")
end
end
-- Helper: Format secondary contributors (e.g., "ed.", "comp.", "trans.")
local function formatSecondaryContributors(contributors, label)
local list = formatContributors(contributors)
if list ~= "" then
return ", " .. label .. " " .. list
end
return ""
end
-- Helper: Parse page range string into start and end pages
local function parsePageRange(pageRangeStr)
local startPage, endPage
if not pageRangeStr or pageRangeStr == "" then
return nil, nil
end
pageRangeStr = mw.text.trim(pageRangeStr)
if pageRangeStr:find("%-") then
startPage, endPage = pageRangeStr:match("^(%d+)%s*%-%s*(%d+)$")
else
startPage = pageRangeStr:match("^(%d+)$")
endPage = startPage
end
if startPage then
startPage = tonumber(startPage)
endPage = tonumber(endPage)
return startPage, endPage
else
return nil, nil
end
end
-- Helper: Check if two page ranges overlap
local function rangesOverlap(aStart, aEnd, bStart, bEnd)
return aStart <= bEnd and bStart <= aEnd
end
function p.generateCitation(frame)
local userInput = frame.args[1] or ""
local pageNumbers = frame.args[2] or ""
local itemNumber = nil
local needsInput = false
local category = "[[Category:Articles requiring Bahaidata input]]"
-- Determine item number
if mw.wikibase.isValidEntityId(userInput) then
itemNumber = userInput
else
itemNumber = mw.wikibase.getEntityIdForTitle(userInput)
if not itemNumber then
local page = mw.title.new(userInput)
if page then
local rtarget = page.redirectTarget
if rtarget then
itemNumber = mw.wikibase.getEntityIdForTitle(rtarget.fullText)
end
end
end
end
if not itemNumber then
return "''" .. userInput .. "''" .. (pageNumbers ~= "" and ", p." .. pageNumbers or "") .. " " .. category
end
-- Get entity and data
local entity = mw.wikibase.getEntity(itemNumber)
local titleValue = entity.claims['P47'] and entity.claims['P47'][1].mainsnak.datavalue.value.text or ""
if titleValue == "" then
return "''" .. userInput .. "''" .. (pageNumbers ~= "" and ", p." .. pageNumbers or "") .. " " .. category
end
local authors = getLabelsFromClaims(entity.claims['P10'])
local editors = getLabelsFromClaims(entity.claims['P14'])
local compilers = getLabelsFromClaims(entity.claims['P43'])
local translators = getLabelsFromClaims(entity.claims['P32'])
local authorValue = formatContributors(authors)
local editorValue = formatContributors(editors)
local compilerValue = formatContributors(compilers)
local translatorValue = formatContributors(translators)
local publicationDate = entity.claims['P29'] and mw.text.split(entity.claims['P29'][1].mainsnak.datavalue.value.time, '-')[1]:gsub('^%+', '') or ""
local publisherValue = entity.claims['P26'] and mw.wikibase.getLabel(entity.claims['P26'][1].mainsnak.datavalue.value.id) or ""
local countryValue = entity.claims['P48'] and mw.wikibase.getLabel(entity.claims['P48'][1].mainsnak.datavalue.value.id) or ""
local isbn10Value = entity.claims['P31'] and entity.claims['P31'][1].mainsnak.datavalue.value or ""
local isbn13Value = entity.claims['P49'] and entity.claims['P49'][1].mainsnak.datavalue.value or ""
if authorValue == "" and compilerValue == "" and translatorValue == "" then
needsInput = true
end
-- Page prefix logic
local pagePrefix = "p."
if pageNumbers:find(",") or pageNumbers:find("-") then
pagePrefix = "pp."
end
-- Parse the page numbers passed in
local citedStartPage, citedEndPage = parsePageRange(pageNumbers)
if not citedStartPage then
citedStartPage, citedEndPage = 1, math.huge -- Default to all pages
end
-- Initialize variables for chapter data
local chapterAuthorValue = ""
local chapterTitleValue = ""
local chapterTranslators = {}
local chapterFound = false
-- Check if the item has chapters (P59)
if entity.claims['P59'] and citedStartPage then
for _, chapterClaim in ipairs(entity.claims['P59']) do
if chapterClaim.mainsnak and chapterClaim.mainsnak.datavalue then
local chapterId = chapterClaim.mainsnak.datavalue.value.id
local chapterEntity = mw.wikibase.getEntity(chapterId)
if chapterEntity then
-- Get the chapter's pages (P6)
local chapterPagesValue = chapterEntity.claims['P6'] and chapterEntity.claims['P6'][1].mainsnak.datavalue.value or ""
if chapterPagesValue ~= "" then
local chapterStartPage, chapterEndPage = parsePageRange(chapterPagesValue)
if chapterStartPage and chapterEndPage then
-- Check if the cited pages overlap with chapter's pages
if rangesOverlap(citedStartPage, citedEndPage, chapterStartPage, chapterEndPage) then
-- We have found the chapter
chapterFound = true
-- Get chapter title from label
chapterTitleValue = mw.wikibase.getLabel(chapterId) or ""
-- Get chapter authors (P10)
local chapterAuthors = getLabelsFromClaims(chapterEntity.claims['P10'])
chapterAuthorValue = formatContributors(chapterAuthors)
-- Use the chapter's translators if available
chapterTranslators = getLabelsFromClaims(chapterEntity.claims['P32'])
-- Use the chapter's publication date if available
local chapterPublicationDate = chapterEntity.claims['P29'] and mw.text.split(chapterEntity.claims['P29'][1].mainsnak.datavalue.value.time, '-')[1]:gsub('^%+', '') or ""
if chapterPublicationDate ~= "" then
publicationDate = chapterPublicationDate
end
break -- We found the matching chapter, exit the loop
end
end
end
end
end
end
end
-- Build the citation
local citation = ""
if chapterFound then
-- Chapter author
if chapterAuthorValue ~= "" then
citation = chapterAuthorValue
if publicationDate ~= "" then
citation = citation .. " (" .. publicationDate .. "). "
else
citation = citation .. ". "
end
elseif publicationDate ~= "" then
citation = "(" .. publicationDate .. "). "
end
-- Chapter title
if chapterTitleValue ~= "" then
citation = citation .. "\"" .. chapterTitleValue .. ".\" "
end
-- 'In' main work
citation = citation .. "In " .. "''" .. titleValue .. "''"
-- Volume number (P50)
local volumeNumber = entity.claims['P50'] and entity.claims['P50'][1].mainsnak.datavalue.value.amount or ""
if volumeNumber ~= "" then
citation = citation .. ", Vol. " .. volumeNumber
end
-- Secondary contributors (editors, compilers)
if editorValue ~= "" then
citation = citation .. ", edited by " .. editorValue
elseif compilerValue ~= "" then
citation = citation .. ", compiled by " .. compilerValue
end
-- Page numbers with prefix
if pageNumbers ~= "" then
citation = citation .. ", " .. pagePrefix .. " " .. pageNumbers
end
-- Location and publisher
if countryValue ~= "" and publisherValue ~= "" then
citation = citation .. ". " .. countryValue .. ": " .. publisherValue
elseif publisherValue ~= "" then
citation = citation .. ". " .. publisherValue
end
-- ISBN
if isbn10Value ~= "" or isbn13Value ~= "" then
citation = citation .. ". ISBN " .. (isbn10Value ~= "" and isbn10Value or isbn13Value)
end
-- Translators
local combinedTranslators = formatContributors(chapterTranslators)
if combinedTranslators ~= "" then
citation = citation .. ". Translated by " .. combinedTranslators
elseif translatorValue ~= "" then
citation = citation .. ". Translated by " .. translatorValue
end
citation = citation .. "."
else
-- Existing logic when no chapter is found
-- Primary contributor
if authorValue ~= "" then
citation = authorValue
if publicationDate ~= "" then
citation = citation .. " (" .. publicationDate .. "). "
else
citation = citation .. ". "
end
elseif compilerValue ~= "" then
citation = compilerValue .. ", comp."
if publicationDate ~= "" then
citation = citation .. " (" .. publicationDate .. "). "
else
citation = citation .. ". "
end
elseif editorValue ~= "" then
citation = editorValue .. ", ed."
if publicationDate ~= "" then
citation = citation .. " (" .. publicationDate .. "). "
else
citation = citation .. ". "
end
end
-- Title
citation = citation .. "''" .. titleValue .. "''"
-- Secondary contributors
if authorValue ~= "" then
citation = citation .. formatSecondaryContributors(compilers, "comp.")
citation = citation .. formatSecondaryContributors(editors, "ed.")
end
citation = citation .. formatSecondaryContributors(translators, "trans.")
-- Location and publisher
if countryValue ~= "" and publisherValue ~= "" then
citation = citation .. ". " .. countryValue .. ": " .. publisherValue
elseif publisherValue ~= "" then
citation = citation .. ". " .. publisherValue
end
-- Fallback date if no author
if publicationDate ~= "" and authorValue == "" then
citation = citation .. ". " .. publicationDate
end
-- Page numbers with prefix
if pageNumbers ~= "" then
citation = citation .. ". " .. pagePrefix .. " " .. pageNumbers
end
-- ISBN
if isbn10Value ~= "" or isbn13Value ~= "" then
citation = citation .. ". ISBN " .. (isbn10Value ~= "" and isbn10Value or isbn13Value)
end
citation = citation .. "."
end
-- Add category if needed
if needsInput then
citation = citation .. " " .. category
end
return citation
end
return p