Module:Cite source

local util_vars = require('Module:VarsUtil') --originally from https://thealchemistcode.fandom.com/wiki/Module:VarsUtil local util_link = require('Module:LinkUtil') local util_text = require('Module:TextUtil') local util_smw = require('Module:SMW') local cache = require('mw.ext.LuaCache') local PREFIX = 'SC_STORE_01-' local p = {} --p stands for package local h = {} --h stands for helper

-- from https://stackoverflow.com/a/7927877 under CC-BY-SA 3.0 - written by lhf (https://stackoverflow.com/users/107090/lhf) function h.tableInvert(t) local s={} for k,v in pairs(t) do    s[v]=k end return s end

--==========================================	Generating and saving citations	==========================================

function h.getAndFormatUnlinkedItems(args) --gets and formats data for items that are unlinked	in the infobox local data = {["anthology"] = "", ["writer"] = "", ["publisher"] = "", ["adapted from"] = "", ["network"] = ""} for key, val in pairs(data) do		if args[key] and args[key] ~= "" then local current = util_text.split(args[key], args["separator"]) if #current > 4 then data[key] = "" .. util_link.stripPipe(util_link.stripDab(current[1])) .. "" .. ", et al. " else for i = 1, #current do data[key] = data[key] .. "" .. util_link.stripPipe(util_link.stripDab(current[i])) .. "" if i == #current-1 then data[key] = data[key] .. " and " elseif i == #current then data[key] = data[key] else data[key] = data[key] .. ", "					end end end end end return data end

function h.getAndFormatIssuesText(args) --formats issues text (similar concept as above but doesn't add links) local issues = "" if args["publication"] then local current = util_text.split(args["publication"], args["separator"]) for i = 1, #current do issues = issues .. current[i] if i == #current-1 then issues = issues .. " and " elseif i == #current then issues = issues else issues = issues .. ", "			end end end return issues end

function h.getAndFormatSeriesText(args) -- making series text local series = "" if args["citation series"] then series = args["citation series"] elseif args["range"] then series = "\'\'" .. util_link.stripPipe(util_link.stripDab(args["range"])) .. "\'\'" elseif args["series"] then if args["series"] == "Doctor Who television stories" then series = "\'\'Doctor Who\'\'" else series = args["series"] end if args["season number"] then series = series .. " " .. "" .. string.lower(util_link.stripPipe(util_link.stripDab(args["season number"]))) .. "" end end return series end

function h.getReleaseYearText(argsRaw) -- get and format release year local args = argsRaw local releaseYearText = "" if args["release date"] or args["broadcast date"] or args["premiere"] or args["beta release date"] or args["cover date"] then args["release date"] = util_text.split(util_link.stripDab(args["release date"] or args["broadcast date"] or args["premiere"] or args["beta release date"] or args["cover date"]), "-") local releaseYear local releaseEndYear if #args["release date"] >= 2 then releaseYear = args["release date"][1]:gsub("%s+", ""):sub(-4) releaseEndYear = args["release date"][2]:gsub("%s+", ""):sub(-4) if tonumber(releaseEndYear) == nil then releaseEndYear = nil end if tonumber(releaseYear) == nil then releaseYear = releaseEndYear releaseEndYear = nil end else releaseYear = args["release date"][1]:gsub("%s+", ""):sub(-4) end if releaseEndYear and releaseYear and (releaseEndYear ~= releaseYear) then releaseYearText = releaseYearText .. "" .. releaseYear .."-" .. releaseEndYear .. "" else releaseYearText = "" .. releaseYear .."" end end return releaseYearText end

function h.makeOutput(data, args) -- making outputTest local outputText = "" -- outputText = "Rewrite in progress. Functionality will be restored shortly. Work in progress citation: " --temporary if data["writer"] ~= "" then outputText = outputText .. data["writer"] .. ", "		if data["adapted from"] ~= "" then outputText = outputText .. "adapted from ''" .. data["adapted from"] .. "''"			local originalWriter = mw.smw.ask( "" .. util_link.stripPipe(args["adapted from"]) .. "" .. "\n|?Writer")[1]["Writer"] or "" if originalWriter ~= "" then outputText = outputText .. " (" .. originalWriter .. ")" end outputText = outputText .. ", "		end elseif data["adapted from"] ~= "" then outputText = outputText .. "adapted from ''" .. data["adapted from"] .. "''"		local originalWriter = mw.smw.ask( "" .. util_link.stripPipe(args["adapted from"]) .. "" .. "\n|?Writer")[1]["Writer"] or "" if originalWriter ~= "" then outputText = outputText .. " (" .. originalWriter .. ")" end outputText = outputText .. ", "	end local KEYS = {"series", "anthology", "publisher", "network", "release year"} local loopData = {} for _, key in pairs(KEYS) do		if data[key] and data[key] ~= "" then if key == "anthology" then table.insert(loopData, ""..data[key].."") else table.insert(loopData, data[key]) end end end if loopData[1] then outputText = outputText .. loopData[1] if loopData[2] then outputText = outputText .. " (" .. loopData[2]			if loopData[3] then				outputText = outputText .. ", " .. loopData[3]				if loopData[4] then					outputText = outputText .. ", " .. loopData[4]					if loopData[5] then						outputText = outputText .. ", " .. loopData[5]					end				end			end			outputText = outputText ..")" end end --fallback in case of an error if outputText == "" or outputText == nil then outputText = "Error: code 1 - data table empty." else outputText = outputText .. "."	end return outputText end

function h.storeText(outputText, name) util_vars.setVar(PREFIX .. name, outputText) cache.delete(PREFIX .. name) cache.set(PREFIX .. name, outputText) mw.smw.set({["Story info"] = outputText}) end

function p.infoboxStore( frame ) local args = frame:getParent.args local name = frame.args[1] if args["citation text"] then outputText = args["citation text"] else if not args["separator"] then args["separator"] = "," end -- combines and if args["anthology"] and args["audio anthology"] then args["anthology"] = args["anthology"] .. ", " .. args["audio anthology"] elseif (not args["anthology"]) and args["audio anthology"] then args["anthology"] = args["audio anthology"] end -- combines and if args["adapted from"] and args["novelisation of"] then args["adapted from"] = args["adapted from"] .. ", " .. args["novelisation of"] elseif (not args["adapted from"]) and args["novelisation of"] then args["adapted from"] = args["novelisation of"] end local data = h.getAndFormatUnlinkedItems(args) data["issues"] = h.getAndFormatIssuesText(args) data["series"] = h.getAndFormatSeriesText(args) data["release year"] = h.getReleaseYearText(args) data["edition"] = "" data["original"] = "" for key, val in pairs(data) do util_vars.setVar(PREFIX .. name .. "-" .. key, val) end if args["season number"] and (args["season number"] ~= "") then util_vars.setVar(PREFIX .. name .. "-" .. "season", "true") end local outputText = h.makeOutput(data, args) --outputText = util_smw.dump(data) --for testing h.storeText(outputText, name) end end

function p.variantStore(frame) local args = frame:getParent.args local name = frame.args[1] if args["citation text"] then outputText = args["citation text"] else if not args["separator"] then args["separator"] = "," end -- combines and if args["anthology"] and args["audio anthology"] then args["anthology"] = args["anthology"] .. ", " .. args["audio anthology"] elseif (not args["anthology"]) and args["audio anthology"] then args["anthology"] = args["audio anthology"] end -- combines and if args["adapted from"] and args["novelisation of"] then args["adapted from"] = args["adapted from"] .. ", " .. args["novelisation of"] elseif (not args["adapted from"]) and args["novelisation of"] then args["adapted from"] = args["novelisation of"] end local variantData = h.getAndFormatUnlinkedItems(args) variantData["issues"] = h.getAndFormatIssuesText(args) variantData["series"] = h.getAndFormatSeriesText(args) variantData["release year"] = h.getReleaseYearText(args) local data = {["anthology"] = "", ["writer"] = "", ["publisher"] = "", ["adapted from"] = "", ["network"] = "", ["issues"] = "", ["series"] = "", ["release year"] = ""} for key, val in pairs(data) do data[key] = util_vars.getVar(PREFIX .. name .. "-" .. key) or "" end data["variant"] = args["variant"] or "variant" data["original"] = args["original"] or ("" .. util_link.stripPipe(util_link.stripDab(name)) .. "") if util_vars.getVar(PREFIX .. name .. "-" .. "season") == "true" then args["season number"] = "true" end local outputText = string.upper(string.sub(data["variant"], 1, 1)) .. string.sub(data["variant"], 2) if variantData["release year"] and variantData["release year"] ~= "" then outputText = outputText .. " from " .. variantData["release year"] end -- maybe add other variant data here? outputText = outputText .. ", " .. h.makeOutput(data, args) h.storeText(outputText, name .. "-" .. data["variant"]) end end

--==========================================	Displaying citations	==========================================

function h.generatePreciseCite(args) local preciseCite = "" if args["ed"] and args["ed"] ~= "" then preciseCite = preciseCite .. " Edition: " .. args["ed"] if args["chapt"] and args["chapt"] ~= "" then preciseCite = preciseCite .. "; chapter: " .. args["chapt"] if args["page"] and args["page"] ~= "" then if string.match(args["page"], "-") then preciseCite = preciseCite .. "; pages: " .. args["page"] else preciseCite = preciseCite .. "; page: " .. args["page"] end end elseif args["page"] and args["page"] ~= "" then if string.match(args["page"], "-") then preciseCite = preciseCite .. "; pages: " .. args["page"] else preciseCite = preciseCite .. "; page: " .. args["page"] end end elseif args["chapt"] and args["chapt"] ~= "" then preciseCite = preciseCite .. " Chapter: " .. args["chapt"] if args["page"] and args["page"] ~= "" then if string.match(args["page"], "-") then preciseCite = preciseCite .. "; pages: " .. args["page"] else preciseCite = preciseCite .. "; page: " .. args["page"] end end elseif args["page"] and args["page"] ~= "" then if string.match(args["page"], "-") or string.match(args["page"], ",") or string.match(args["page"], "&") or string.match(args["page"], "and") then preciseCite = preciseCite .. " Pages: " .. args["page"] else preciseCite = preciseCite .. " Page: " .. args["page"] end end if preciseCite ~= "" then preciseCite = preciseCite .. "."	end return preciseCite end

function h.getInfo(story, variant) local info local dataStore = story if variant and variant ~= "" then dataStore = story .. "-" .. variant end if util_vars.getVar(PREFIX .. dataStore) then info = util_vars.getVar(PREFIX .. dataStore) elseif cache.get(PREFIX .. dataStore) then info = cache.get(PREFIX .. dataStore) util_vars.setVar(PREFIX .. dataStore, info) elseif mw.smw.ask( "" .. story .. "" .. "\n|?Story info")[1]["Story info"] then smwResult = mw.smw.ask( "" .. story .. "" .. "\n|?Story info")[1]["Story info"] if type(smwResult) == "table" then if variant and variant ~= "" then if #smwResult == 2 then info = smwResult[2] util_vars.setVar(PREFIX .. dataStore, info) cache.set(PREFIX .. dataStore, info) else info = "Error: Code 4 - no data in variables or cache and SMW returned information for multiple variants, the one required here not being clear." -- at the moment, this code is being a bit lazy. It is theoretically possible to get an actual output here, but it would require trying to find the correct story info value for the requested variant which is hard. It is believed that this situation will not come up commonly enough for this to be an issue. end else info = smwResult[1] util_vars.setVar(PREFIX .. dataStore, info) cache.set(PREFIX .. dataStore, info) end elseif type(smwResult) == "string" and not(variant and variant ~= "") then info = smwResult util_vars.setVar(PREFIX .. dataStore, info) cache.set(PREFIX .. dataStore, info) else info = "Error: Code 2 - no data stored in variables, cache or SMW." end else info = "Error: Code 2 - no data stored in variables, cache or SMW." end return info end

function p.displayCitation(frame) local args = frame:getParent.args local finishedCitation = "" local usingNamedPageCitation = false if args["name"] and args["name"] ~= "" then if util_vars.getVar(PREFIX .. "NAMED-PAGE-CITATION" .. args["name"]) then finishedCitation = util_vars.getVar(PREFIX .. "NAMED-PAGE-CITATION" .. args["name"]) usingNamedPageCitation = true end end if usingNamedPageCitation == false then if not args[1] or args[1] == "" then return "Error: code 3 - no story given in template transclusion." end local story = args[1] local additionalDisplay = "" local section = "" local variant = "" if args["var"] and args["var"] ~= "" then variant = args["var"] additionalDisplay = additionalDisplay .. " (" .. args["var"]			if args["sect"] and args["sect"] ~= "" then				section = "#" .. args["sect"]				additionalDisplay = additionalDisplay .. ")" elseif args["namedep"] and args["namedep"] ~= "" then section = "#" .. args["namedep"] additionalDisplay = additionalDisplay .. ")"			elseif args["part"] and args["part"] ~= "" then				section = "#Part " .. args["part"]				additionalDisplay = additionalDisplay .. ", part " .. string.lower(args["part"]) .. ")" elseif args["ep"] and args["ep"] ~= "" then section = "#Episode " .. args["ep"] additionalDisplay = additionalDisplay .. ", episode " .. string.lower(args["ep"]) .. ")"			else				additionalDisplay = additionalDisplay .. ")" end else if args["sect"] and args["sect"] ~= "" then section = "#" .. args["sect"] elseif args["namedep"] and args["namedep"] ~= "" then section = "#" .. args["namedep"] elseif args["part"] and args["part"] ~= "" then section = "#Part " .. args["part"] additionalDisplay = additionalDisplay .. " (part " .. string.lower(args["part"]) .. ")" elseif args["ep"] and args["ep"] ~= "" then section = "#Episode " .. args["ep"] additionalDisplay = additionalDisplay .. " (episode " .. string.lower(args["ep"]) .. ")" end end local preciseCite = h.generatePreciseCite(args) local display = "" local quote = "" local ital = "''" local pretext = "" if args["noital"] and args["noital"] ~= "" then ital = "" end if args["namedep"] and args["namedep"] ~= "" then display = util_link.stripDab(args["namedep"]) quote = "\""			pretext = pretext .. "Part of " .. ital .. util_link.stripDab(story) .. ital .. additionalDisplay .. ", "		elseif args["namedpart"] and args["namedpart"] ~= "" then			display = util_link.stripDab(args["namedpart"])			quote = "\"" pretext = pretext .. "Part of " .. ital .. util_link.stripDab(story) .. ital .. additionalDisplay .. ", " elseif args[2] and args[2] ~= "" then display = ital .. args[2] .. ital else display = ital .. util_link.stripDab(story) .. ital .. additionalDisplay end if args["quote"] and args["quote"] ~= "" then quote = "\""		end		local collapsibleText = ""		if args["citationtext"] and args["citationtext"] ~= "" then			collapsibleText = args["citationtext"]		else			local main = ""			-- overides system - needs A LOT more work			local overideArgs = {["anthology"] = "", ["writer"] = "", ["publisher"] = "", ["adapted from"] = "", ["network"] = "", ["publication"] = "", ["release date"] = "", ["series"] = ""}			args["release date"] = args["release year"] or ""			local overides = false			for key, val in pairs(overideArgs) do				if args[key] and args[key] ~= "" then					overideArgs[key] = args[key]					overides = true				end			end			if overides then				overideArgs["separator"] = args["separator"] or ","				local smwQuery = "\[\[" .. args[1] .. "\]\]"				local SMWPROPS = {["anthology"] = "Anthology", ["writer"] = "Writer", ["publisher"] = "Publisher", ["adapted from"] = "Adapted from", ["network"] = "Premiere network", ["publication"] = "Issues", ["release date"] = "Release date", ["series"] = "Series"} local SMWPROPSINVERSE = h.tableInvert(SMWPROPS) for key, val in pairs(overideArgs) do					if val == "" then smwQuery = smwQuery .. "\n|?" .. SMWPROPS[key] if key == "release date" then smwQuery = smwQuery .. "\n|?Release end date" end end end local smwResult = mw.smw.ask(smwQuery)[1] table.remove(smwResult, 1) local UNLINKEDVALUES = {["Anthology"] = true, ["Writer"] = true, ["Publisher"] = true, ["Adapted from"] = true, ["Premiere network"] = true} for key, val in pairs(smwResult) do					if type(val) == "table" then local list = "" for _, item in pairs(smwResult) do							if UNLINKEDVALUES[key] then list = list .. overideArgs["separator"] .. util_link.stripLink(item):sub(2) else list = list .. overideArgs["separator"] .. item end end overideArgs[SMWPROPSINVERSE[key]] = list or "" else if UNLINKEDVALUES[key] then overideArgs[SMWPROPSINVERSE[key]] = util_link.stripLink(val):sub(2) or "" elseif key == "Release date" then overideArgs["release date"] = util_text.split(val, "-")[1] elseif key == "Release end date" then overideArgs["release date"] = overideArgs["release date"] .. " - " .. util_text.split(val, "-")[1] else overideArgs[SMWPROPSINVERSE[key]] = val or "" end end end local data = h.getAndFormatUnlinkedItems(overideArgs) data["issues"] = h.getAndFormatIssuesText(overideArgs) data["series"] = h.getAndFormatSeriesText(overideArgs) data["release year"] = h.getReleaseYearText(overideArgs) main = h.makeOutput(data, overideArgs) else -- this is what happens in the majority of cases main = h.getInfo(story, variant) end collapsibleText = pretext .. main .. preciseCite end finishedCitation = quote .. "" .. display .. "" .. quote .. " [+] " .. collapsibleText .. " "		if args["name"] and args["name"] ~= "" then util_vars.setVar(PREFIX .. "NAMED-PAGE-CITATION" .. args["name"], finishedCitation) end end return finishedCitation end

return p