Module:Quotations

கட்டற்ற பன்மொழி அகரமுதலியான விக்சனரியில் இருந்து.

Documentation for this module may be created at 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 LanguageModule = {}
LanguageModule.__index = LanguageModule

local hasData = {
	['ae'] = true,
	['axm'] = true,
	['bra'] = true,
	['en'] = true,
	['grc'] = true,
	['he'] = true,
	['hi'] = true,
	['hy'] = true,
	['la'] = true,
	['peo'] = true,
	['sa'] = true,
	['xcl'] = true,
}

function export.create(frame)
	local passed, results = pcall(export.Create, frame)
	if passed then
		return results
	else
		--[[Special:WhatLinksHere/Template:tracking/Quotations/error]]
		require('Module:debug').track('Quotations/error')
		return '<span class="wiktQuote previewonly error" 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")
			mw.log("incorrect param in {{Q}}: |" .. k .. "=" .. tostring(v))
--			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 = LanguageModule.new(lang)
		ante = m_langModule:expand(args)
	else
		require("Module:debug").track {
			'Quotations/no data',
			'Quotations/no data/' .. lang:getCode(),
		}
	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
		ref = {}
		for i = 4, 10 do
			if args[i] then
				table.insert(ref, args[i])
			else
				break
			end
		end
		ante.ref = table.concat(ref, '.')
	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 _, item in ipairs(otherOtherLineStuff) do
		ante[item] = ante[item] or args[item]
	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
	
	local form = args['form'] or 'full'
	if form == 'full' then
		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") .. '</dd></dl>')
					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, '</dd></dl>')
		end
		penult.otherLines = table.concat(penult.otherLines)
		
		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

local function add_self(func)
	return function(self, ...)
		return func(...)
	end
end

function LanguageModule.new(lang)
	local sema = require('Module:Quotations/' .. lang:getCode())
	sema.library = mw.loadData("Module:Quotations/" .. lang:getCode() .. "/data")
	
	setmetatable(sema, LanguageModule)
	
	-- Have to insert unused self parameter or Lua–PHP interface complains about
	-- table with boolean keys.
	sema.lower = add_self(mw.ustring.lower)
	
	-- This should only be loaded if needed....
	sema.numToIndian = add_self(require("Module:foreign numerals").to_Indian)
	
	sema.period = '.'
	
	return sema
end

function LanguageModule:changeCode(color)
	if color == 'orange' then
		self.code = 'orange'
	end
	if (color == 'yellow') and (self.code == 'green') then
		self.code = 'yellow'
	end
end

function LanguageModule:reroute(route)
	local temp = {}
	local data = self.library.data
	
	for k, v in pairs(route) do
		temp[k] = self:interpret(v)
	end
	
	for k, v in pairs(temp) do
		self[k] = v
	end
	
	if self.author ~= nil and data[self.author] then
		self.aData = data[self.author]
		if self.work ~= nil and self.aData.works[self.work] then
			self.wData = self.aData.works[self.work]
		end
	end
end

function LanguageModule:choose(choice, optionA, optionB)
	optionB = optionB or ''
	choice = self: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(self.refLink, self:interpret(current))
		else
			break
		end
	end
	local ongoingDecision
	decision = self:interpret(decision)
	return decision
end

function LanguageModule:isLetter(input)
	local isit = not tonumber(input)
	return isit
end

function LanguageModule:roundDown(period, verse)
	if not tonumber(verse) then
		self:changeCode('orange')
	else
		local rounded = math.floor(verse/period) * period
		return rounded
	end
end

function LanguageModule:chapterSelect(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
	self:changeCode('orange')
end

function LanguageModule:interpret(item)
	local output
	
	if type(item) == 'string' then
		if string.len(item) > 1 and string.sub(item, 1, 1) == '.' then
			address = string.sub(item, 2)
			local returnable = self[address] or self.library.data.Sundry and self.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 = self:interpret(item[1])
		if type(presumedFunction) == 'function' then
			local parameters = {}
			for i = 2, 30 do
				if item[i] ~= nil then
					table.insert(parameters, self:interpret(item[i]))
				else
					break
				end
			end
			output = presumedFunction(self, unpack(parameters))
		else
			local nested = self
			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
	
	return output
end

function LanguageModule:convert(scheme, initiate)
	if type(scheme) == "table" then
		local initiate = tonumber(initiate) or initiate
		local converted = scheme[initiate]
		if converted == nil then
			self: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
			self:changeCode('orange')
		end
		return converted
	end
	self:changeCode('orange')
end

function LanguageModule:numToRoman(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

-- Iterate through "array" and its sublevels. Find indices in "array" that
-- contain a string matching "valToFind". Return last index where that string
-- (minus its first letter) is the key for a field in "self", as well as last
-- index where that string was found.
-- Used to locate the place where the "rlformat" should be skipped out of,
-- because there's no ".ref" value supplied for what comes next.
-- For instance, if book but not line number has been supplied.
local function findLastValidRefIndex(self, array, valToFind)
	local lastValidIndex, lastIndex
	for i, val in ipairs(array) do
		if type(val) == 'table' then
			local res1, res2 = findLastValidRefIndex(self, val, valToFind)
			if res1 then
				lastValidIndex = i
			end
			if res2 then
				lastIndex = i
			end
		elseif type(val) == 'string' and val:find(valToFind) then
			lastIndex = i
			if self[val:sub(2)] then
				lastValidIndex = i
			end
		end
	end
	return lastValidIndex, lastIndex
end

function LanguageModule:expand(args)
	--Instantiate our variables.
	local results = {}
	self.code = 'green'
	local data = self.library.data
	local ultimate = ''

	self.author = args['author'] or args[2]
	self.work = args['work'] or args[3]
	
	for i = 1, 5 do
		local refName = 'ref' .. i
		local paramNumber = i + 3
		self[refName] = args[refName] or args[paramNumber]
	end

	--Check if we've been given an author alias.
	if data.authorAliases[self.author] then
		self.author = data.authorAliases[self.author]
	end

	if not data[self.author] then
		self:changeCode('yellow')
	else
		self.aData = data[self.author]
		if self.aData.reroute then
			self:reroute(self.aData.reroute)
		else
			if self.aData.aliases and self.aData.aliases[self.work] then
				self.work = self.aData.aliases[self.work]
			end
			if not (self.aData.works and self.aData.works[self.work]) then
				self:changeCode('yellow')
			else
				self.wData = self.aData.works[self.work]
				if self.wData.reroute then
					self:reroute(self.wData.reroute)
				end
			end
		end
	end

	--Load all author-level data.
	if self.aData and self.aData.aLink then
		results.author = '[[w:'..self.aData.aLink..'|'..self.author..']]'
	else
		results.author = self.author
	end
	if self.aData and self.aData.year then
		results.year = self.aData.year
	end

	--If the database has a link for the work, incorporate it.
	if not self.wData or not self.wData['wLink'] then
		results.work = self.work
	else
		results.work = '[[w:'..self.wData['wLink']..'|'..self.work..']]'
	end
	
	--Some works have info which overrides the author-level info.
	if self.wData then
		if self.wData['year'] then
		results.year = self.wData.year
		end
		if self.wData['author'] ~= nil then
			results.author = self.wData.author
		end
	end

	--The displayed reference usually consists of all the ref argument(s) joined with a period.
	self.refDisplay = self.ref1 and '' or false
	for i = 1, 5 do
		local whichRef = 'ref' .. tostring(i)
		if self[whichRef] then
			local ref = self[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 self.aData and self.aData.rdFormat and self.aData.rdFormat.separator then
				separator = self.aData.rdFormat.separator
			else
				separator = "."
			end
			
			if i > 1 then
				self.refDisplay = self.refDisplay .. separator
			end
			self.refDisplay = self.refDisplay .. self[whichRef]
		else
			break
		end
	end
	if args['through'] then
		args['thru'] = args['through']
	end
	if args['thru'] then
		self.refDisplay = self.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 self.wData and self.wData['rlFormat'] then
		self.rlFormat = self.aData['rlFormat'..tostring(self.wData.rlFormat)]
		if self.rlFormat then
			self.rlTitle = self.wData['rlTitle']
			
			-- Go through indices in "self.rlFormat" that contain a string
			-- beginning in ".ref" (either in the first level of "self.rlFormat"
			-- or a sublevel). Return the index of the string that has a
			-- corresponding field in "self", as well as the index of the last
			-- such string.
			local lastValidIndex, lastIndex = findLastValidRefIndex(self, self.rlFormat, '^%.ref(%d+)$')
			-- If there isn't another ".ref" string after the last valid index,
			-- then there is no need to cut short the rlFormat.
			local indexToStopAt
			if lastIndex and lastValidIndex and lastIndex > lastValidIndex then
				indexToStopAt = lastValidIndex
			else
				indexToStopAt = math.huge
			end
			
			self.refLink = {}
			for i, current in ipairs(self.rlFormat) do
				if i > indexToStopAt then
					break
				end
				
				table.insert(self.refLink, self:interpret(current))
			end
			self.refLink = table.concat(self.refLink)
		end
	end
	if self.refLink and self.refDisplay then
		results.ref = '[['..self.refLink..'|'..self.refDisplay..']]'
	else
		results.ref = self.refDisplay or ''
	end
	if args['notes'] then
		results.notes = args.notes
	end
	results.code = self.code
	
	return results

end

return export
"https://ta.wiktionary.org/w/index.php?title=Module:Quotations&oldid=1684297" இலிருந்து மீள்விக்கப்பட்டது