Module:Quotations
Dokumentasie vir hierdie module kan geskep word by: Module:Quotations/doc
local m_scriptutils = require("Module:script utilities")
local date_validation = require("Module:Quotations/date validation")
local loadModule -- a forward declaration
local export = {}
local hasData = {
['grc'] = true,
['la'] = true,
['xcl'] = true,
['he'] = true,
['hy'] = true,
['axm'] = true,
['en'] = true,
['sa'] = true,
['hi'] = true,
['ae'] = true,
}
function export.create(frame)
local passed = true
local results = ''
passed, results = pcall(export.Create, frame)
if passed then
return results
else
return '<span class="wiktQuote previewonly" data-validation="red">'..results..'</span>'
end
end
function export.Create(frame)
-- Set up our initial variables; set empty parameters to false
local args = {}
local params = {
['thru'] = true,
['quote'] = true,
['trans'] = true,
['transauthor'] = true,
['transyear'] = true,
['notes'] = true,
['form'] = true,
['year'] = true,
-- [''] = true,
}
for k, v in pairs(frame:getParent().args) do
if not ( type(k) == 'number' or params[k] ) then
-- [[Special:WhatLinksHere/Template:tracking/Quotations/param error]]
require("Module:debug").track("Quotations/param error")
-- error('The parameter "' .. k .. '" is not recognized. See the template documentation.')
end
if v == '' then
if k == "lang" then
args[k] = nil
else
args[k] = false
end
else
args[k] = v
end
end
local lang = args[1]
lang = require("Module:languages").getByCode(lang) or require("Module:languages").err(lang, 1)
local ante = {}
if hasData[lang:getCode()] then
local m_langModule = loadModule(lang)
ante = m_langModule.expand(args)
end
if ante.author == nil then
ante.author = args[2]
end
if ante.work == nil then
ante.work = args[3]
end
if ante.ref == nil then
ante.ref = ''
local dot = false
for i = 4, 10 do
if args[i] then
ante.ref = ante.ref..(dot and '.' or '')..args[i]
dot = true
else
break
end
end
end
for k,v in pairs(args) do
if type(k) ~= 'number' then
ante[k] = args[k]
end
end
local penult = {['year'] = '', ['author'] = '', ['work'] = '', ['ref'] = '',
['notes'] = '', ['otherLines'] = {}, ['s1'] = '', ['s2'] = '',
['s3'] = '', ['s4'] = ''}
local comma = false
--Language specific modules are responsible for first line parameters.
--Base formatting module will poll for other parameters,
--pulling them only if the language module hasn't returned them.
local otherOtherLineStuff = {'quote', 'transyear', 'transauthor', 'trans'}
for i = 1, 4 do
ante[otherOtherLineStuff[i]] = ante[otherOtherLineStuff[i]] or args[otherOtherLineStuff[i]]
end
if not ante.code then
penult.elAttr = ' class="wiktQuote" data-validation="white">'
else
penult.elAttr = ' class="wiktQuote" data-validation="'..ante.code..'">'
end
if ante.year then
penult.year = "'''"..date_validation.main(ante.year).."'''"
comma = true
end
if ante.author then
penult.s1 = (comma and ', ' or '')
penult.author = ante.author
comma = true
end
if ante.work then
penult.s2 = (comma and ', ' or '')
penult.work = "''"..ante.work.."''"
comma = true
end
if ante.ref then
penult.s3 = (comma and ' ' or '')
penult.ref = ante.ref
end
if ante.notes then
penult.s4 = (comma and', ' or '')
penult.notes = '('..ante.notes..')'
end
if ante.quote or ante.trans then
table.insert(penult.otherLines, '<dl><dd>')
if ante.quote then
local sc = require("Module:scripts").findBestScript(ante.quote, lang)
table.insert(penult.otherLines, m_scriptutils.tag_text(ante.quote, lang, sc, nil, "e-quotation"))
if not require("Module:script utilities").is_Latin_script(sc) then
local transliteration = lang:transliterate(require("Module:links").remove_links(ante.quote), sc)
if transliteration then
table.insert(penult.otherLines, '<dl><dd>' .. require("Module:script utilities").tag_translit(transliteration, lang, "usex"))
end
end
end
if ante.trans then
if ante.transyear or ante.transauthor then
table.insert(penult.otherLines, '<ul><li>')
if ante.transyear then
table.insert(penult.otherLines, "'''"..ante.transyear.."''' translation")
else
table.insert(penult.otherLines, 'Translation')
end
if ante.transauthor then
table.insert(penult.otherLines, ' by '..ante.transauthor)
end
table.insert(penult.otherLines, '<dl><dd>'..ante.trans..'</dd></dl></li></ul>')
else
if not ante.quote then
table.insert(penult.otherLines, ante.trans)
else
table.insert(penult.otherLines, '<dl><dd>'..ante.trans..'</dd></dl>')
end
end
end
table.insert(penult.otherLines, '</dl></dd>')
end
penult.otherLines = table.concat(penult.otherLines)
local form = args['form'] or 'full'
if form == 'full' then
ultimate = '<div'..penult.elAttr..penult.year..penult.s1..penult.author..penult.s2..penult.work..penult.s3..penult.ref..penult.s4..penult.notes..penult.otherLines..'</div>'
elseif form == 'inline' then
ultimate = '<span'..penult.elAttr..penult.author..penult.s2..penult.work..penult.s3..penult.ref..'</span>'
elseif form == 'work' then
ultimate = '<span'..penult.elAttr..penult.work..penult.s3..penult.ref..'</span>'
elseif form == 'ref' then
ultimate = '<span'..penult.elAttr..penult.ref..'</span>'
end
return ultimate
end
function loadModule(lang)
local sema = require('Module:Quotations/' .. lang:getCode())
sema.library = sema.library or mw.loadData("Module:Quotations/" .. lang:getCode() .. "/data")
if not sema.refCount then
sema.refCount = 0
end
if not sema.refParamCount then
sema.refParamCount = 0
end
sema.changeCode = sema.changeCode or function(color)
if color == 'orange' then
sema.code = 'orange'
end
if (color == 'yellow') and (sema.code == 'green') then
sema.code = 'yellow'
end
end
sema.reroute = sema.reroute or function(route)
local temp = {}
local data = sema.library.data
if not sema.rerouteRefParamCount then
sema.rerouteRefParamCount = 0
end
for k, v in pairs(route) do
temp[k] = sema.interpret(v)
if string.find(k, "^ref%d$") then
number = tonumber(string.match(k, "%d$"))
mw.log(number)
if number > sema.rerouteRefParamCount then
sema.rerouteRefParamCount = number
end
end
end
for k, v in pairs(temp) do
sema[k] = v
end
if sema.author ~= nil and data[sema.author] then
sema.aData = data[sema.author]
if sema.work ~= nil and sema.aData.works[sema.work] then
sema.wData = sema.aData.works[sema.work]
end
end
end
sema.choose = sema.choose or function(choice, optionA, optionB)
optionB = optionB or ''
choice = sema.interpret(choice)
local chosenPath = {}
if choice then
chosenPath = optionA
else
chosenPath = optionB
end
for j=1, 30 do
local innerCurrent = chosenPath[j]
if innerCurrent then
table.insert(sema.refLink, sema.interpret(current))
else
break
end
end
local ongoingDecision
decision = sema.interpret(decision)
return decision
end
sema.isLetter = sema.isLetter or function(input)
local isit = not tonumber(input)
return isit
end
sema.lower = sema.lower or mw.ustring.lower
sema.roundDown = sema.roundDown or function(period, verse)
if not tonumber(verse) then
sema.changeCode('orange')
else
local rounded = math.floor(verse/period) * period
return rounded
end
end
sema.chapterSelect = sema.chapterSelect or function(rubric, verse)
verse = tonumber(verse)
for k,v in pairs(rubric) do
if v[1] <= verse and verse <= v[2] then
return k
end
end
sema.changeCode('orange')
end
sema.interpret = sema.interpret or function(item)
local output, isRef
if type(item) == 'string' then
if string.len(item) > 1 and string.sub(item, 1, 1) == '.' then
address = string.sub(item, 2)
if string.find(address, "^ref") then
isRef = true
local number = string.match(address, "%d+")
if number then
number = tonumber(number)
if number > sema.refCount then
sema.refCount = number
end
end
end
local returnable = sema[address] or sema.library.data.Sundry and sema.library.data.Sundry[address]
output = returnable
else
output = item
end
elseif type(item) == 'table' then
--If it's a table, it's either a function call or a nested address.
local presumedFunction = sema.interpret(item[1])
if type(presumedFunction) == 'function' then
local parameters = {}
for i = 2, 30 do
if item[i] ~= nil then
local expanded = sema.interpret(item[i])
table.insert(parameters, expanded)
else
break
end
end
local result = presumedFunction(unpack(parameters))
output = result
else
local nested = sema
for i = 1, 30 do
local address = item[i]
if address and nested then
nested = nested[address]
else
break
end
end
output = nested
end
else
output = item
end
if sema.rerouteRefParamCount and sema.refCount < sema.rerouteRefParamCount or sema.refCount < sema.refParamCount or isRef then
return output
else
return ""
end
end
sema.convert = sema.convert or function(scheme, initiate)
if type(scheme) == "table" then
local initiate = tonumber(initiate) or initiate
local converted = scheme[initiate]
if converted == nil then
sema.changeCode('orange')
end
return converted
end
if type(scheme) == "function" then
local initiate = tonumber(initiate) or initiate
local converted = scheme(initiate)
if converted == nil then
sema.changeCode('orange')
end
return converted
end
sema.changeCode('orange')
end
sema.numToRoman = sema.numToRoman or function(item)
local j = tonumber(item)
if (j == nil) then
return item
end
if (j <= 0) then
return item
end
local ints = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}
local nums = {'M', 'CM', 'D', 'CD','C', 'XC','L','XL','X','IX','V','IV','I'}
local result = ""
for k = 1, #ints do
local count = math.floor(j / ints[k])
result = result .. string.rep(nums[k], count)
j = j - ints[k]*count
end
return result
end
sema.numToIndian = sema.numToIndian or require("Module:foreign numerals").to_Indian
sema.period = sema.period or '.'
sema.expand = sema.expand or function(args)
--Instantiate our variables.
local results = {}
sema.code = 'green'
local data = sema.library.data
local ultimate = ''
sema.author = args['author'] or args[2]
sema.work = args['work'] or args[3]
for i = 1, 5 do
local refName = 'ref' .. i
local paramNumber = i + 3
sema[refName] = args[refName] or args[paramNumber]
if i == 1 or sema[refName] then
sema.refParamCount = i
end
end
--Check if we've been given an author alias.
if data.authorAliases[sema.author] then
sema.author = data.authorAliases[sema.author]
end
if not data[sema.author] then
sema.changeCode('yellow')
else
sema.aData = data[sema.author]
if sema.aData.reroute then
sema.reroute(sema.aData.reroute)
else
if sema.aData.aliases and sema.aData.aliases[sema.work] then
sema.work = sema.aData.aliases[sema.work]
end
if not sema.aData.works or not sema.aData.works[sema.work] then
sema.changeCode('yellow')
else
sema.wData = sema.aData.works[sema.work]
if sema.wData.reroute then
sema.reroute(sema.wData.reroute)
end
end
end
end
--Load all author-level data.
if sema.aData and sema.aData.aLink then
results.author = '[[w:'..sema.aData.aLink..'|'..sema.author..']]'
else
results.author = sema.author
end
if sema.aData and sema.aData.year then
results.year = sema.aData.year
end
--If the database has a link for the work, incorporate it.
if not sema.wData or not sema.wData['wLink'] then
results.work = sema.work
else
results.work = '[[w:'..sema.wData['wLink']..'|'..sema.work..']]'
end
--Some works have info which overrides the author-level info.
if sema.wData then
if sema.wData['year'] then
results.year = sema.wData.year
end
if sema.wData['author'] ~= nil then
results.author = sema.wData.author
end
end
--The displayed reference usually consists of all the ref argument(s) joined with a period.
sema.refDisplay = sema.ref1 and '' or false
for i = 1, 5 do
local whichRef = 'ref' .. tostring(i)
if sema[whichRef] then
local ref = sema[whichRef]
local separator
-- no separator before a letter
if mw.ustring.match(ref, "^%a$") then
separator = ""
-- to allow colon between biblical chapter and verse
elseif sema.aData and sema.aData.rdFormat and sema.aData.rdFormat.separator then
separator = sema.aData.rdFormat.separator
else
separator = "."
end
if i > 1 then
sema.refDisplay = sema.refDisplay .. separator
end
sema.refDisplay = sema.refDisplay .. sema[whichRef]
else
break
end
end
if args['through'] then
args['thru'] = args['through']
end
if args['thru'] then
sema.refDisplay = sema.refDisplay..'–'..args['thru']
end
--[[ If the work is not in the database,
or we don't have a source text link,
the ref is simply the display.
Otherwise, we have to create a reference link,
easily the most challenging function of this script. ]]
if sema.wData and sema.wData['rlFormat'] then
sema.rlFormat = sema.aData['rlFormat'..tostring(sema.wData.rlFormat)]
if sema.rlFormat then
sema.rlTitle = sema.wData['rlTitle']
sema.refLink = {}
for i = 1, 30 do
local current = sema.rlFormat[i]
if current then
table.insert(sema.refLink, sema.interpret(current))
else
break
end
end
sema.refLink = table.concat(sema.refLink)
end
end
if sema.refLink and sema.refDisplay then
results.ref = '[['..sema.refLink..'|'..sema.refDisplay..']]'
else
results.ref = sema.refDisplay or ''
end
if args['notes'] then
results.notes = args.notes
end
results.code = sema.code
return results
end
return sema
end
return export