Join our Discord Server
Join the official community
           Join the Discord →
Human Rights
Support Human Rights
           Learn More →
Despera
Check out the Despera & Yotsuba Fan Project
           See Project →
Support Us
Support the wiki directly
About Page
Please check The Codex:About page to see what to do to help.
           See About page

Module:Cite

From The Codex
Jump to navigationJump to search


--- 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