Join the Discord →
Learn More →
See Project →
See About page
Module:Cite
--- Generates citations across the wiki to ensure standard formatting.
-- The module accepts several different types of citations and processes each
-- differently, based on the f table's functions. When the module
-- is called without a type, it acts as a citation needed template.
-- @module cite
-- @alias p
-- @require Dev:Date
-- @require Dev:User error
-- @require Dev:Yesno
-- @require Module:Tags
-- @author KockaAdmiralac
-- <nowiki>
local p = {}
-- Module dependencies local Date = require('Dev:Date') local userError = require('Dev:User error') local yesno = require('Dev:Yesno') local tags = require('Module:Tags') local data = mw.loadData('Module:Cite/data') local title = mw.title.getCurrentTitle()
-- Private logic.
--- Wrapper for userError that places the page under the Pages with
-- user errors category.
-- @function err
-- @param {string} text Text to display as an error
-- @return {string} Wikitext with the error and category
-- @local
local function err(text)
return userError(text, 'Pages with user errors')
end
--- Checks whether a given date string is a valid date. -- @function valid_date -- @param {string} d Date string to check -- @return {bool} Whether the string is a valid date -- @local function valid_date(d)
return pcall(function()
Date(d)
end)
end
--- Table of possible citation types and the way they are processed. -- Each type has a function associated with it that gets passed the arguments -- after the type, does validation of these arguments and returns the whole -- citation text. -- @table cite_functions -- @alias f local f = {}
--- Handles Twitter citations. -- Twitter citations receive arguments in this order: -- * Twitter snowflake -- * Tweet author's handle -- * Citation from the tweet -- * (Optional) Timestamp of the tweet's archival -- * (Optional) Whether the original tweet link is dead -- @function f.twitter -- @param {table} args Citation type arguments -- @return {string} Citation text function f.twitter(args)
-- Check validity of arguments
if not args[1] or not tonumber(args[1]) then
return err('Tweet snowflake invalid or not specified')
end
if not args[2] or not args[3] then
return err('Tweet author or citation not specified')
end
-- Twitter snowflake date extraction
-- Credits: https://github.com/client9/snowflake2time
local snowflake = tonumber(args[1])
local epoch = math.floor(snowflake / 4194304 + 1288834974657)
local date1 = Date(math.floor(epoch / 1000))
-- Format citation
local deadurl = yesno(args[5], false)
local archived = yesno(args[4], true)
local str = {
'\'\,
args[3],
'\'\' - ['
}
if deadurl and archived then
table.insert(str, 'https://web.archive.org/web/')
table.insert(str, args[4])
table.insert(str, '/')
end
table.insert(str, 'https://twitter.com/')
table.insert(str, args[2])
table.insert(str, '/status/')
table.insert(str, args[1])
if data.twitter[args[2]] then
table.insert(str, ' ')
table.insert(str, data.twitter[args[2]])
table.insert(str, ' (@')
table.insert(str, args[2])
table.insert(str, ')')
else
table.insert(str, ' @')
table.insert(str, args[2])
end
table.insert(str, ' on Twitter,] ')
table.insert(str, date1:fmt('%B %d, %Y.'))
if deadurl then
if archived then
table.insert(str, ' Archived on ')
table.insert(str, Date(args[4]):fmt('%B %d, %Y.'))
else
table.insert(str, ' \'\'\'[deleted]\'\'\)
end
end
return table.concat(str)
end
--- Handles citations of text in the game. -- Game citations receive arguments in this order: -- * Quotation -- * Quote author and the situation in which they made the quote -- @function f.game -- @param {table} args Citation type arguments -- @return {string} Citation text function f.game(args)
if not args[1] then
return err('Quote not specified')
end
if not args[2] then
return err('Quote author not specified')
end
return table.concat({
'\'\,
tags.replace(args[1]),
'\'\' - ',
args[2]
})
end
--- Handles citations of YouTube videos. -- YouTube citations receive arguments in this order: -- * YouTube video ID -- * Video title -- * (Optional) Time at which the video plays -- @function f.youtube -- @param {table} args Citation type arguments -- @return {string} Citation text function f.youtube(args)
if not args[1] or not args[2] then
return err('Video ID or title not specified')
end
local str = {
'\'\,
args[2],
'\'\' - [https://youtu.be/',
args[1]
}
if args[3] then
table.insert(str, '?t=')
table.insert(str, args[3])
end
table.insert(str, ' YouTube]')
return table.concat(str)
end
--- Handles Tumblr citations. -- Tumblr citations receive arguments in this order: -- * Tumblr name of the author -- * Tumblr post ID -- * Citation from the post -- * Date in YYYY-MM-DD format (or any other standard format) -- @function f.tumblr -- @param {table} args Citation type arguments -- @return {string} Citation text function f.tumblr(args)
if not args[1] or not args[3] then
return err('Author or quote not specified')
end
if not args[2] or not tonumber(args[2]) then
return err('Post ID invalid or not specified')
end
if not args[4] or not valid_date(args[4]) then
return err('Date invalid or not specified')
end
return table.concat({
'\'\,
tags.replace(args[3]),
'\'\' - [http://',
args[1],
'.tumblr.com/post/',
args[2],
' ',
args[1],
' on Tumblr,] ',
Date(args[4]):fmt('%B %d, %Y.')
})
end
--- Handles citations of the game's code. -- Code citations receive arguments in this order: -- * GML script name -- * (Optional) Starting line number -- * (Optional) Ending line number -- @function f.code -- @param {table} args Citation type arguments -- @return {string} Citation text -- @see https://github.com/KockaAdmiralac/deltarune-viewer function f.code(args)
if not args[1] then
return err('Script name not specified')
end
if (args[2] and not tonumber(args[2])) or (args[3] and not tonumber(args[3])) then
return err('Line number is not a number')
end
local str = {
args[1],
' script'
}
if args[2] then
table.insert(str, ', line')
if args[3] then
table.insert(str, 's ')
table.insert(str, args[2])
table.insert(str, '–')
table.insert(str, args[3])
else
table.insert(str, ' ')
table.insert(str, args[2])
end
end
return table.concat(str)
end
--- Handles citations from news sources. -- News citations receive arguments in this order: -- * Excerpt from the news -- * News post title -- * News site name -- * News post URL -- * News post date -- * (Optional) First name of the author -- * (Optional) Last name of the author -- @function f.news -- @param {table} args Citation type arguments -- @return {string} Citation text function f.news(args)
if not args[1] then
return err('Relevant news post excerpt not specified')
end
if not args[2] then
return err('News post title not specified')
end
if not args[3] then
return err('News site name not specified')
end
if not args[4] then
return err('News post URL not specified')
end
if not args[5] or not valid_date(args[5]) then
return err('News post date invalid or not specified')
end
local author = {}
if args[6] then
if args[7] then
table.insert(author, args[7])
table.insert(author, ', ')
end
table.insert(author, args[6])
table.insert(author, ', ')
end
return table.concat({
'\'\,
args[1],
'\'\' - [',
args[4],
' ',
args[2],
'] (',
table.concat(author),
Date(args[5]):fmt('%B %d, %Y.'),
') \'\,
args[3],
'\'\'.'
})
end
-- Package items.
--- Template entrypoint for Template:Cite. -- @function p.main -- @param {table} frame Scribunto frame object -- @return {string} Citation text function p.main(frame)
local args = frame:getParent().args
local t = args[1]
if t then
if f[t] then
local nargs = {}
for i, v in ipairs(args) do
if i > 1 then
nargs[i - 1] = v
end
end
return f[t](nargs);
else
return err('Invalid citation type specified')
end
else
-- Template:Cite was used
local str = '[citation needed]'
if title.namespace == 0 or title.namespace == 14 then
return str ..
else
return str
end
end
end
return p