This module is a general-purpose base citation template builder that serves as the foundation for most of our citation templates. It is highly customizable, taking in a variety of parameters (most of which are optional); as this is a module used to build other templates, the invocation of this module should accept the result of a parameter in the template itself, i.e. |parent=. When in doubt, it's totally okay to just copy an existing template and tweak it from there to serve your uses.
They fall into three categories:
- Parent parameters:
- The following parameters are used to build a template that cites a single piece of media:
parent— the primary parameter for a single piece of parent media; this will be used to generate a single link to the media.ptext— formatting text for theparentvalue.
- The following parameters are used to build a template for a media series, like magazines.
series— an alternate way to define the parent media, used primarily for magazine citation templates; this defines the series name that will be concatenated (joined together with a space) with theissueparameter value to create the link to the individual magazine issue. Please note, it is the part of the issue title, and not the magazine series itself—so {{EncyclopediaCite}} passes in "Star Wars Encyclopedia" to this parameter, rather than Star Wars Encyclopedia (series)stext— Custom formatting for the series text; used only when it is partially italicized.issue— the issue number field, used primarily for magazines. Will be concatenated with theseriesparameter.issue1andissue2— used to support the use ofissue1andissue2parameters in the citation template, for child stories/articles that span multiple issues.- For series with more complex titles, like changing names after a certain issue or a parenthetical descriptor, the module also accepts the following parameters:
noitalics— suppresses automatic italicization of the parent/series value.series2— a secondary series name to be used for issues under the threshold. (ex: Template:InsiderCite)stext2— formatting text forseries2threshold— a threshold value for issue # under which theseries2,suffix2andimage2parameters will be used. This is for cases like Star Wars Insider, which was published under a different name for the first 22 issues. (ex: Template:InsiderCite)suffix— used to add a suffix to the issue name, like "(2013)" for The Official Star Wars Fact File Part 1 (2013) (ex: Template:FactFile2013)suffix2— likesuffixbut for the issues under the threshold (ex: Template:FactFile2014)showsuffix— causes the suffix to be shown in the actual link's text, like for the 2013 Fact Files; this defaults to false, for cases like Star Wars: Darth Vader 1 (magazine). (ex: Template:FactFile2013)
- The following parameters are used to build a template that cites a single piece of media:
- Child parameters:
child— the child media that was published in or part of the parent media.ctext— formatting text for the child media.noquotes— disables the enclosing quotation marks around the child media; this is done automatically for child media that starts with "Untitled".nolink— allows the template to list the child media without a link to a Wookieepedia article.
- And the rest:
image— the image to be included at the start of the citation template.invert— applies the "invert-image" class to the image.mode— enables most of the below parameters in common modes, such as "magazine", "tv" and "ref".nospaces— removes the spacing between the child, parent and dashndash— changes the separating dash from an mdash to an ndashsmall— causes the child value to be displayed using {{C}} instead of with a dash separator; this is used for reference magazines.parentfirst— causes the parent media to be listed first, as opposed to the default of "child - parent".audiobook— enables the template to support the automatic use of the {{Ab}} template.reprint— enables the template to support the automatic use of the {{Reprint}} template.abbr— text to strip off of the names of reprinted material, like removing Star Wars Insider from the reprints of Insider articles.reprintParent— edge case flag for {{WEGCite}}, which uses the book name as the reprint lookup key rather than the child story.
Templates that use BaseCitation have the following maintenance categories:
- Category:BaseCitation usages with invalid child parameters — tracks usages with missing/invalid child (episode/story/etc) parameter values.
- Category:BaseCitation usages with invalid parent parameters — tracks templates that do not define the parent or series parameters.
- Category:BaseCitation usages with invalid issue parameters — tracks usages of a citation template where only the
issue1parameter has been provided without a correspondingissue2parameter.
An example implementation for {{GalaxyCite}}:
{{#invoke:BaseCitation|main|template=GalaxyCite
|mode=magazine
|image=[[File:GalaxyCite.png|baseline|link=Star Wars Galaxy Magazine]]
|series=Star Wars Galaxy Magazine
|issue={{{1}}}
|issue1={{{issue1|}}}
|issue2={{{issue2|}}}
|child={{#if:{{{issue1|}}}|{{{1|}}}|{{{2|}}}}}
|ctext={{#if:{{{issue1|}}}|{{{2|}}}|{{{3|}}}}}
|noquotes={{{noquotes|}}}
}}
local p = {}
local NS_MODULE = 828
local currentTitle = mw.title.getCurrentTitle()
function yes(s)
return s ~= nil and s ~= ''
end
function isMissing(s)
return s == nil or s == '' or (s:sub(0, 3) == "{{{" and s:sub(-3) == "}}}")
end
function ternary(cond, t, f)
if cond then return t else return f end
end
function hasValue(tab, val)
for index, value in ipairs(tab) do
if value == val then
return true
end
end
return false
end
local CUSTOM_AUDIOBOOKS = {
["5-Minute Star Wars Stories (2015)"] = "5-Minute Star Wars Stories (audiobook)",
["5-Minute Star Wars Stories Strike Back"] = "5-Minute Star Wars Stories 2",
["Galactic Adventures Storybook Collection"] = "Star Wars Adventure",
["The Prequel Trilogy Stories"] = "Star Wars Storybook Collection",
["The Original Trilogy Stories"] = "Star Wars Storybook Collection",
["Canto Bight (novella collection)"] = "Canto Bight (audiobook)",
}
local ENCYCLOPEDIA = {"Ace Squadron", "Anakin Skywalker", "C-3PO", "Coruscant", "Darth Vader", "Emperor Palpatine", "Han Solo", "Luke Skywalker", "Millennium Falcon", "Naboo", "Obi-Wan Kenobi", "Padmé Amidala", "Princess Leia Organa", "R2-D2", "TIE Fighters", "Tatooine", "The Clone Wars", "The First Order", "The Grand Army of the Republic", "The Rebel Alliance", "The Resistance", "The Separatists"}
local DEPARTMENTS = {"A Certain Point of View", "Bantha Tracks", "Blaster", "Books", "Bounty Hunters", "Comics", "Comlink", "Crossword", "Games", "Jedi Archive", "Jedi Library", "Red Five", "Rogues Gallery", "Toys", "Versus"}
function buildAbText(story)
return string.format('<small>(and [[%s|audiobook]])</small>', story)
end
function buildAudiobook(param, story)
if story == "Galactic Adventures Storybook Collection" and param == "2" then
return buildAbText("Star Wars Adventure 2")
elseif CUSTOM_AUDIOBOOKS[story] ~= nil then
return buildAbText(CUSTOM_AUDIOBOOKS[story])
end
return buildAbText(story .. " (audiobook)")
end
local function makeCategoryLink(cat)
-- "Category" is split out here so that the module isn't put into the
-- category "%s" when the page is saved.
return string.format('[[%s:%s|%s]]', 'Category', cat, currentTitle.text)
end
-- isCurrentPageMainSpaceOrFile determines whether the page being parsed is a mainspace or file page.
local function isCurrentPageMainSpaceOrFile()
return currentTitle.namespace == 0 or currentTitle.namespace == 6 or currentTitle.namespace == 828 or string.find(currentTitle.fullText, 'Wookieepedia:Sources') or string.find(currentTitle.fullText, 'Wookieepedia:Appearances')
end
local function hideParenthetical(set)
local stop = set:find('%s*%(')
return stop and set:sub(1, stop - 1) or set
end
local function compare(txt, full, italics)
if not txt or not full then
return ''
end
local match = full == txt
if italics then
match = full == txt:gsub("^''", ""):gsub("''$", "")
end
if match then
if currentTitle.namespace == 0 then
return '[[Category:Unnecessary text parameters used in citation templates|' .. currentTitle.text .. ']] ·'
elseif currentTitle.namespace == 6 or currentTitle.namespace == 120 then
return '[[Category:Unnecessary text parameters used in citation templates|*' .. currentTitle.text .. ']] ·'
end
end
return ''
end
function buildIssue(s, f, i, x, y, italics, noIssue)
if isMissing(s) or (isMissing(i) and currentTitle.namespace ~= 10) then
return '<strong class="error">Missing series/issue parameters, cannot construct parent</strong>' .. makeCategoryLink("BaseCitation usages with invalid issue parameters")
elseif noIssue and yes(f) then
return string.format("[[%s|%s %s%s]]", s, f, i or '{{{issue}}}', y)
elseif noIssue then
return string.format("[[%s|%s%s%s %s%s]]", s, italics, hideParenthetical(s), italics, i or '{{{issue}}}', y)
elseif yes(f) then
return string.format("[[%s %s%s|%s %s%s]]", s, i, x, f, i or '{{{issue}}}', y)
else
return string.format("[[%s %s%s|%s%s%s %s%s]]", s, i or '{{{issue}}}', x, italics, hideParenthetical(s), italics, i or '{{{issue}}}', y)
end
end
function buildName(s, i)
return string.format('%s %s', s, i)
end
local matches = {"audiobook", "second edition", "Second Edition"}
local function autoItalicizeParent(parent)
if parent:match(" Level 1$") ~= nil then
return nil
end
local m = parent:match("( %(%d+%) %d%d?%d?)$")
local n = parent:match("( %d%d?%d?)$")
if m ~= nil then
return "''"..parent:sub(0, #parent - #m).."''"..m
elseif n ~= nil then
return "''"..parent:sub(0, #parent - #n).."''"..n
end
for _, suffix in ipairs(matches) do
local q = parent:match("( %("..suffix.."%))$")
if q ~= nil then
return "''"..parent:sub(0, #parent - #q).."'', "..suffix
end
end
return nil
end
local function isOtherSeries(args, issue)
local swap = false
if yes(args.checkseries) and yes(args.threshold) and (yes(args.series2) or yes(args.suffix2)) then
local threshold = tonumber(args.threshold)
if yes(args.issue) and tonumber(args.issue) ~= nil and tonumber(args.issue) <= threshold then
swap = true
elseif yes(args.issue1) and tonumber(args.issue1) ~= nil and tonumber(args.issue1) <= threshold then
swap = true
end
end
return swap and makeCategoryLink("Legacy magazine series citations") or ''
end
function buildParent(args)
local image = args.image
local cat = ''
local italics = "''"
if yes(args.noitalics) or (args.parent or ''):find('Free Comic Book Day') then
italics = ''
end
local ptext = args.ptext
if yes(args.parent) and not yes(args.ptext) and args.italicize then
ptext = autoItalicizeParent(args.parent)
end
if yes(args.parent) and yes(ptext) then
return image, args.parent, string.format("[[%s|%s]]", args.parent, ptext) .. compare(args.ptext, hideParenthetical(args.parent), italics)
elseif yes(args.parent) then
return image, args.parent, string.format('%s[[%s|%s]]%s', italics, args.parent, hideParenthetical(args.parent), italics)
end
local series = args.series
if isMissing(series) and isCurrentPageMainSpaceOrFile() then
return image, '', '<strong class="error">Missing series parameters, cannot construct parent</strong>' .. makeCategoryLink("BaseCitation usages with invalid parent parameters")
elseif isMissing(series) then
return image, '', string.format('%s[[{{{parent}}}]]%s', italics, italics)
end
local noIssueLink = args.noissue
local stext = args.stext
local issue = args.issue
local issue1 = args.issue1
local issue2 = args.issue2
local suffix = ''
local ss = ''
if yes(args.suffix) then
suffix = ' ' .. args.suffix
if yes(args.showsuffix) then
ss = ' ' .. suffix
end
end
if yes(args.threshold) and (yes(args.series2) or yes(args.suffix2)) then
local threshold = tonumber(args.threshold)
local swap = false
if yes(issue) and tonumber(issue) ~= nil and tonumber(issue) <= threshold then
swap = true
elseif yes(issue1) and tonumber(issue1) ~= nil and tonumber(issue1) <= threshold then
swap = true
end
if swap then
if yes(args.series2) then
series = args.series2
end
if yes(args.suffix2) then
suffix = ' ' .. args.suffix2
if yes(args.showsuffix) then
ss = ' ' .. args.suffix2
end
end
if yes(args.image2) then
image = args.image2
end
end
end
if args.mode == "ref" and yes(issue) and yes(args.lookupIssue) then
local target = buildName(series, issue .. suffix)
if series == "Star Wars Starships & Vehicles" and issue == "S1" then
target = "Star Wars Starships & Vehicles: Death Star II"
elseif series == "Star Wars Starships & Vehicles" and issue == "S2" then
target = "Star Wars Starships & Vehicles: Starkiller Base"
end
local issueText = lookUpFormattedText("Issue", args, args.lookupIssueType, '', false)
if yes(issueText) then
return image, target, string.format("[[%s|%s]]", target, issueText)
end
end
if noIssueLink and yes(issue1) and yes(issue2) then
return image, series, buildIssue(series, stext, issue1 .. '–' .. issue2, suffix, ss, italics, noIssueLink)
elseif yes(issue1) and yes(issue2) then
local i1 = buildIssue(series, stext, issue1, suffix, ss, italics, noIssueLink)
local i2 = string.format("[[%s %s%s|%s]]", series, issue2, suffix, issue2)
return image, buildName(series, issue1 .. suffix), string.format("%s–%s", i1, i2)
elseif yes(issue1) then
return image, buildName(series, issue1 .. suffix), buildIssue(series, stext, issue1, suffix, ss, italics, noIssueLink) .. makeCategoryLink('BaseCitation usages with invalid issue parameters')
elseif yes(issue) then
return image, buildName(series, issue .. suffix), buildIssue(series, stext, issue, suffix, ss, italics, noIssueLink)
elseif yes(stext) and stext:find("''") then
return image, series, string.format("[[%s|%s]]", series, stext)
elseif yes(stext) then
return image, series, string.format("%s[[%s|%s]]%s", italics, series, stext, italics)
else
return image, series, string.format("%s[[%s|%s]]%s", italics, series, hideParenthetical(series), italics)
end
end
function prepareChild(args)
local child = args.child
if child ~= nil and child ~= "" and args.parentheses then
for k in args.parentheses:gmatch('[^%,]+') do
if k:find(' %(') and string.lower(child) == string.lower(k:sub(0, k:find(' %(') - 1)) then
return k
end
end
end
return child
end
function lookUpFormattedText(target, args, lookupType, textValue, combine, combine)
if lookupType ~= nil and lookupType ~= "" then
local render = require('Module:FormattedTextLookup').render
return render({type = lookupType or '', template = args.template,
issue = args.issue, target = target, text = textValue,
combine = args.lookupCombine, textOnly = 'yes'})
end
return ""
end
function buildChild(args, small)
if isMissing(args.child) and args.mode == "ref" and yes(args.parentMode) then
return "", ""
elseif isMissing(args.child) and isCurrentPageMainSpaceOrFile() then
return "", '<strong class="error">Missing child parameters, cannot construct child link</strong>' .. makeCategoryLink("BaseCitation usages with invalid child parameters")
elseif isMissing(args.child) then
return "", '"[[{{{child|}}}]]"'
end
if args.template == "EncyclopediaCite" then
local book = args.child:gsub(" %(..+%)$", "")
if book == "Millennium Falcon" then
return book .. ' (reference book)', string.format('"[[Millennium Falcon (reference book)|%s]]"', "''Millennium Falcon''")
elseif hasValue(ENCYCLOPEDIA, book) then
return book .. ' (reference book)', string.format('"[[%s (reference book)|%s]]"', book, book)
else
return book, string.format('"[[%s]]"', book, book)
end
end
local child = prepareChild(args)
if child == "Bantha Tracks (newsletter)" or child == "Bantha Tracks (department)" or child == "Bantha Tracks" then
return child, "[[Bantha Tracks (department)|''Bantha Tracks'']]"
elseif args.template == "InsiderCite" and hasValue(DEPARTMENTS, child) then
child = child .. ' (department)'
end
local ctext = args.ctext
if args.lookupText then
ctext = lookUpFormattedText(args.child, args, args.lookupType, args.lookupTextValue, args.lookupCombine)
if not ctext and args.child ~= child then
ctext = lookUpFormattedText(child, args, args.lookupType, args.lookupTextValue, args.lookupCombine)
end
if not ctext then
ctext = args.ctext
end
end
local textCat = ''
if ctext and ctext:find("%[%[Category:") then
local z = ctext:find("%[%[Category:")
textCat = ctext:sub(z)
ctext = ctext:sub(0, z - 1)
end
local quote = '"'
if yes(args.noquotes) or small then
quote = ''
elseif string.lower(child:sub(0, 8)) == "untitled" then
quote = ''
end
if yes(args.nolink) then
return child, string.format("%s%s%s", quote, hideParenthetical(yes(ctext) and ctext or child), quote) .. compare(ctext, hideParenthetical(child), false) .. textCat
elseif yes(ctext) then
return child, string.format("%s[[%s|%s]]%s", quote, child, ctext, quote) .. compare(ctext, hideParenthetical(child), false) .. textCat
elseif child:find('%(1%)') or child:find('%(2%)') then
return child, string.format("%s[[%s|%s]]%s", quote, child, child, quote) .. textCat
else
return child, string.format("%s[[%s|%s]]%s", quote, child, hideParenthetical(child), quote) .. textCat
end
end
local function addHideSpan(s)
return '<span class="pnh">' .. s .. '</span>'
end
function p.citation(args)
local spacing, dash, parentFirst = ' ', '—', false
local small = false
local mode = string.lower(args.mode or '')
if mode == "tv" then
parentFirst = true
elseif mode == "magazine" then
parentFirst = false
elseif mode == "ref" then
parentFirst = true
small = true
else
if yes(args.nospaces) then
spacing = ''
end
dash = yes(args.ndash) and '–' or '—'
parentFirst = yes(args.parentfirst)
end
small = small or yes(args.small)
local image, parent, parentText = buildParent(args)
local child, childText = buildChild(args, small)
local imageText= ''
if yes(image) and small and yes(args.child) then
imageText = image..' '
elseif yes(image) then
imageText = string.format('<span class="mhi %s">%s</span> ', yes(args.invert) and "invert-images" or '', image)
end
local text = ''
if yes(args.parentMode) then
text = imageText .. parentText
elseif small and yes(args.child) then
--text = string.format('%s <small class="cgct">%s%s%s</small>', addHideSpan(image..' '..parentText), addHideSpan('('), childText, addHideSpan(')'))
text = string.format('%s <small class="cgct">%s</small>', addHideSpan(imageText..parentText), childText)
elseif parentFirst then
text = string.format("%s%s%s%s%s%s", imageText, parentText, spacing, dash, spacing, childText)
else
text = string.format("%s%s%s%s%s%s", imageText, childText, spacing, dash, spacing, parentText)
end
if mode == 'magazine' and yes(parent) and yes(child) and parent == child then
text = text .. makeCategoryLink("Magazine citations using issue as article parameter")
end
text = text .. isOtherSeries(args)
if yes(args.audiobook) and yes(parent) then
text = text .. ' ' .. buildAudiobook(args.audiobook, parent)
end
if yes(args.reprint) then
local buildReprint = require('Module:Reprint').buildReprint
local rt = buildReprint(yes(args.reprintParent) and parent or child, args.issue, false, args.abbr)
if yes(rt) then
text = text .. ' ' .. rt
end
end
return text
end
function p.main(frame)
return p.citation(frame.args)
end
return p