Module:R/sandbox

From Wikipedia, the free encyclopedia
Jump to navigation Jump to search
local rp = {}
local r = {}
local hyphen2dash = require('Module:String2').hyphen_to_dash
local lang = require('Module:Lang')
local trim_quotes = require('Module:trim quotes')._trim
local getArgs = require('Module:Arguments').getArgs
local plainText = require('Module:Plain text')._main

local notblank = function(v) return (v or '') ~= '' end

local pageTest = {pages = 1, pp = 1, page = 1, p = 1}
local wrapTest = {yes = 1, y = 1, forced = 1, f = 1}

-- get first non-empty argument from a list of names
local function firstArg(args, ...)
	for i = 1, select('#', ...) do
		local n = select(i, ...)
		local v = args[n]
		if notblank(v) then return v end
	end
	return nil
end

local function firstArgN(s, args, ...)
	for i = 1, select('#', ...) do
		local n = select(i, ...)
		local v = args[n .. s]
		if notblank(v) then return v end
	end
	return nil
end

-- Implements [[Template:page_needed]]
-- may replace with lua implementation at some point
local function page_needed(frame, date, reason)
	return frame:expandTemplate{title='Page needed', args = {date = date, reason = reason}}
end

-- Implements [[Template:R/langcode]]
-- Only for template/module use: |language=code/name
function r._langcode(language)
	language = language or ''
	local tag, result = lang._tag_from_name{language}
	if result then
		return tag
	elseif lang._is_ietf_tag(language) then
		return language
	end
	return 'mis' -- use language code "mis" for any unrecognized language
end
function r.langcode(frame)
	args = getArgs(frame)
	return r._langcode(args.language)
end


-- Implements [[Template:R/where]] sub-template
-- Only for template/module use: |plural=pages |singular=page |location=in-source-location |spacing=character
function r._where(params)
	local out = {}

	if notblank(params.plural) then
		table.insert(out, params.plural)
		if notblank(params.singular) then
			table.insert(out, "," .. (params.spacing or "") .. "[" .. params.singular .. "]")
		end
	elseif notblank(params.singular) then
		table.insert(out, params.singular)
	end

	if notblank(params.location) then
		if notblank(params.plural) or notblank(params.singular) then
			table.insert(out, "," .. (params.spacing or ""))
		end
		table.insert(out, params.location)
	end

	return table.concat(out)
end
function r.where(frame)
	return r._where(getArgs(frame))
end


-- Implements [[Template:R/superscript]]
-- Only for template/module use: |wrap=n[o]/y[es]/f[orced] |leadin=value |prefix=value |pp=value |where=value |sup-where=value |quote-where=value |quote=value |language=value |translation=value |suffix=value
function r._superscript(params)
	if not params or not notblank(params.where) then
		return ""
	end

	local out = {}
	
	-- "wrap" if wrap is "yes", "y", "f" or "forced", else "nowrap"
	local wrap = wrapTest[string.ulower(params.wrap or '')]
	table.insert(out, '<sup class="reference ' .. (wrap and "" or "no") .. 'wrap">')

	--prefix, if there's a quote
	if notblank(params.quote) and notblank(params.prefix) then
		table.insert(out, params.prefix)
	end
	
	-- open tooltip span
	table.insert(out, '<span title="')
	
	-- Lead-in text (escaped)
	local whereText = notblank(params["quote-where"]) and params["quote-where"]
		or (params["where"] or "")
	local tooltipText = plainText((params.leadin or "") .. ": " .. whereText, false)
	table.insert(out, mw.text.encode(tooltipText, '<>"'))

	-- Quotation block if present
	if notblank(params.quote) then
		local quoteTab = {}
		if notblank(params.language) then
			local langText = lang._is_ietf_tag(params.language) and lang._name_from_tag{params.language} or params.language
			table.insert(quoteTab, "&#32;(" .. langText .. ")")
		end
		
		table.insert(quoteTab, "&#58; &quot;" .. trim_quotes(params.quote) ..
			"&quot;")

		if notblank(params.translation) then
			table.insert(quoteTab, "&#10;Translation: &quot;" ..
				trim_quotes(params.translation) .. "&quot;")
		end
		
		local quoteText = plainText(table.concat(quoteTab), false)
		table.insert(out, "&#10;Quotation" .. mw.text.encode(quoteText, '<>"') ..
			'" class="tooltip tooltip-dashed" style="border-bottom: 1px dashed;')
	end
	
	-- close tooltip span
	table.insert(out, '">')
	
	-- prefix, if not inserted above
	if (not notblank(params.quote)) and notblank(params.prefix) then
		table.insert(out, params.prefix)
	end
	
	--pp and sup-where
	table.insert(out, params.pp or '')
	table.insert(out, params['sup-where'] or '')
	
	-- suffix
	if notblank(params.quote) then
		table.insert(out, "</span>" .. (params.suffix or ""))
	else
		table.insert(out, (params.suffix or "") .. "</span>")
	end

	table.insert(out, "</sup>")

	return table.concat(out)
end
function r.superscript(frame)
	return r._superscript(getArgs(frame))
end

-- Implements [[Template:R/ref]]
function r._ref(params, frame)
	local frame = frame or mw.getCurrentFrame()
	local out = {}
	
	local contextSectionName = mw.uri.anchorEncode(
			'cite_sect-' ..
			trim_quotes(params[1] or '') ..	'-' ..
			trim_quotes(params[2] or '') .. '-' .. 
			trim_quotes(
				(notblank(params.page) and params.page or hyphen2dash(params.pages or '', ' ')) ..
				(params.location or '')
			)
		)
	local contentId = notblank(params['content-id']) and mw.uri.anchorEncode(params['content-id']) or nil
	local whereArgs = {
		plural = hyphen2dash(params.pages, ' '),
		singular = params.page,
		location = params.location,
		spacing = '&#32;'
	}
	local quoteWhereArgs = {
		plural = hyphen2dash(params['quote-pages'], ' '),
		singular = params['quote-page'],
		location = params['quote-location'],
		spacing = '&#32;'
	}
	local refArgs = {name = params[1] or '', group = params[2] or ''}
	
	-- Debug facility
	if notblank(params.debug) then
		table.insert(out, "DEBUG: ")
		for k, v in pairs(params) do
			table.insert(out, k .. "=" .. (v or '') .. ", ")
		end
		table.insert(out, ". Potential context-section-name:")
		table.insert(out, contextSectionName .. '".')
	end
	
	-- Opening "support context" span
	local lst
	if notblank(params.section) then
		local section = (params.section == 'yes' or params.section == 'y') and
			contextSectionName or params.section
		lst = frame:callParserFunction('#lst', {
			mw.title.getCurrentTitle().fullText,
			section
		})
		if notblank(lst) then
			table.insert(out, '<templatestyles src="Template:Tooltip/styles.css"/>')
			table.insert(out, '<span class="rt-commentedText tooltip tooltip-dotted"' ..
				'title="Context: &quot;' .. mw.text.encode(plainText(lst, false), '<>"') ..
				'&quot;">')
		end
	end
	
	--First call to create reference link (variants identical except for dir):
	if notblank(params['link-id']) then
		table.insert(out, '<span id="' .. mw.uri.anchorEncode(params['link-id']) ..
			'class="citation">')
	end

	local refContent = {}
	if (not notblank(params.annotation)) then
		table.insert(refContent, params.reference or '')
		if contentId then
			table.insert(refContent, 1, '<span id="' .. contentId .. '" class="citation">')
			table.insert(refContent, '</span>')
		end
		table.insert(refContent, params.postscript or '')
	end

	if notblank(params.direction) then
		refArgs.dir = params.direction
	end
	table.insert(out, frame:extensionTag('ref', table.concat(refContent), refArgs))
	
	if notblank(params['link-id']) then
		table.insert(out, '</span>')
	end
	
	--Optional second call to append data to reference (variants identical except for dir):
	if notblank(params.annotation) then
		refContent = {}
		if pageTest[params.annotation] then
			if notblank(firstArg(params, 'pages', 'page', 'location')) then
				table.insert(refContent, params.leadin or '')
				table.insert(refContent, r._where(whereArgs))
				if contentId then
					table.insert(refContent, 1, '<span id="' .. contentId .. '">')
					table.insert(refContent, '</span>')
				end
				table.insert(refContent, 1, '&#8204;')
			end
		elseif ({quote = 1, q = 1})[params.annotation] then
			table.insert(refContent, '&#8204;')
			if pageTest[firstArg(params, 'quote-pages', 'quote-page', 'quote-location')] then
				if notblank(firstArg(params, 'pages', 'page', 'location')) then
					table.insert(refContent, params.leadin or '')
					table.insert(refContent, r._where(whereArgs) .. ':&#32;')
				end
			else
				table.insert(refContent, params.leadin or '')
				table.insert(refContent, r._where(quoteWhereArgs) .. ':&#32;')
			end
			
			table.insert(refContent '<q ')
			if contentId then
				table.insert(refContent, 'id="' .. contentId .. '" ')
			end
			local qcli = firstArg(params, 'quote-cite', 'link-id')
			if notblank(qcli) then
				table.insert(refContent, 'cite="#' .. (mw.uri.anchorEncode(qcli)) .. '" ')
			end
			if notblank(params.language) then
				local langcode = r._langcode(params.language)
				table.insert(refContent, 'lang="' .. langcode .. '">')
				table.insert(refContent, '<bdi lang="' .. langcode .. '">')
			else
				table.insert(refContent, '><bdi>')
			end
			table.insert(refContent, trim_quotes(params.quote or '') .. '</bdi></q>')
			if notblank(params.translation) then
				table.insert(refContent, '&#32;&#91;<bdi ')
				if notblank(params.language) then
					table.insert(refContent, 'lang="' .. r._langcode(params.language) .. '"')
				end
				table.insert(refContent, '>' .. trim_quotes(params.translation .. '</bdi>&#93;'))
			end
		elseif contentId then
			table.insert(refContent, '<span id="' .. contentId ..
				' class="citation">' .. (params.leadin or '') ..
				params.annotation .. '</span>')
		else
			table.insert(refContent, (params.leadin or '') .. params.annotation)
		end
		table.insert(refContent, params.postscript or '')
		refArgs = {follow = params[1] or '', group = params[2] or ''}
		if notblank(params.direction) then
			refArgs.dir = params.direction
		end
		table.insert(out, frame:extensionTag('ref', table.concat(refContent), refArgs))
	end
	
	--Superscript pages and tooltip for help, pages, quotes:
	local ssAma = string.ulower(params.style or '') == 'ama'
	-- p/pp is only used in superscript label, therefore it does not contain any qp params
	local ssPp = ''
	if ssAma and (not notblank(params['no-pp'])) then
		if notblank(params.pages) then
			ssPp = 'pp'
		elseif notblank(params.page) then
			ssPp = 'p'
		end
	end
	-- leadin is only used in tooltip
	local ssLeadin = ''
	if pageTest[firstArg(params, 'quote-pages', 'quote-page', 'quote-location')] then
		if notblank(params.pages) then
			ssLeadin = 'Pages'
		elseif notblank(params.page) then
			ssLeadin = 'Page'
		elseif notblank(params.location) then
			ssLeadin = 'Location'
		else
			ssLeadin = 'Page&nbsp;/ location'
		end
	elseif notblank(params['quote-pages']) then
		ssLeadin = 'Pages'
	elseif notblank(params['quote-page']) then
		ssLeadin = 'Page'
	elseif notblank(params['quote-location']) then
		ssLeadin = 'Location'
	else
		ssLeadin = 'Page&nbsp;/ location'
	end
	
	table.insert(out, r._superscript{
		prefix = ssAma and '(' or '&#58;&hairsp;',
		suffix = ssAma and ')' or '&hairsp;',
		pp = ssPp,
		leadin = ssLeadin,
		where = r._where(whereArgs), -- where must not include qp params
		['sup-where'] = r._where{ -- sup-where same as where, but with improved list spacing for superscript
			plural = hyphen2dash(params.pages, '&hairsp;'),
			singular = params.page,
			location = params.location,
			spacing='&hairsp;'
		},
		['quote-where'] = r._where( -- quote-where must not contain normal in-source-location params
			pageTest[firstArg(params, 'quote-pages', 'quote-page', 'quote-location')] and
			whereArgs or quoteWhereArgs
		),
		quote = params.quote,
		language = params.language,
		translation = params.translation,
		['wrap'] = params['wrap']
	})
	
	-- Closing "support context" span:
	if notblank(params.section) and notblank(lst) then
		table.insert(out, '</span>')
	end
	
	-- Page needed functionality:
	if notblank(params['needed-reason']) then
		local pnReason = ({yes = 1, y = 1})[params['needed-reason']] and
			'No reason given' or params['needed-reason']
		table.insert(out, page_needed(frame, params['needed-date'], pnReason))
	end
	
	-- Line wrapping functionality:
	if wrapTest[string.ulower(params.wrap or '')] then
		table.insert(out, "&#8203;") --zero-width space
	end
	
	--End of code
	return table.concat(out)
end
function r.ref(frame)
	return r._ref(getArgs(frame), frame)
end

function r._r(args, frame)
	frame = frame or mw.getCurrentFrame()
	local output = {}
	-- ### 1 ###
	output[1] = r._ref({
		[1]				= firstArg(args, 'name1', 'name', 'n1', 'n', 1),
		[2]				= firstArg(args, 'group', 'grp', 'g'),
		direction		= firstArg(args, 'direction1', 'direction', 'dir1', 'dir'),
		page			= firstArg(args, 'page1', 'page', 'p1', '1p', 'p'),
		pages			= firstArg(args, 'pages1', 'pages', 'pp1', '1pp', 'pp'),
		location		= firstArg(args, 'location1', 'location', 'loc1', '1loc', 'loc', 'at1', 'at'),
		['quote-page']	= firstArg(args, 'quotation-page1', 'quotation-page', 'quote-page1', 'quote-page', 'qp1', 'qp'),
		['quote-pages']	= firstArg(args, 'quotation-pages1', 'quotation-pages', 'quote-pages1', 'quote-pages', 'qpp1', 'qpp'),
		['quote-location'] = firstArg(args,
			'quotation-location1', 'quotation-location', 'quote-location1', 'quote-location', 'quote-loc1', 'quote-loc',
			'quote-at1', 'quote-at'
		),
		quote			= firstArg(args, 'quotation1', 'quotation', 'quote1', 'quote', 'q1', 'q'),
		language		= firstArg(args, 
			'quotation-language1', 'quotation-language', 'quote-language1', 'quote-language', 'quotation-lang1',
			'quotation-lang', 'quote-lang1', 'quote-lang', 'ql1', 'ql', 'language1', 'language', 'lang1', 'language', 'l1', 'l'
		),
		translation		= firstArg(args,
			'translation-quotation1', 'translation-quotation', 'trans-quotation1', 'trans-quotation', 'translation-quote1',
			'translation-quote', 'trans-quote1', 'trans-quote', 'tq1', 'tq', 'translation1', 'translation', 'trans1', 'trans',
			't1', 't', 'xlat1', 'xlat'
		),
		['quote-cite']	= firstArg(args, 'quotation-cite1', 'quotation-cite', 'quote-cite1', 'quote-cite', 'qc1', 'qc'),
		reference		= firstArg(args,
			'reference1', 'references', 'reference', 'notes', 'note', 'content', 'text', 'refn1', 'refn', 'refs', 'r1', 'r'
		),
		annotation		= firstArg(args, 'annotation1', 'annotation', 'annot1', 'annot', 'a1', 'a'),
		leadin			= args.leadin,
		postscript		= firstArg(args, 'postscript', 'postscript1', 'ps', 'ps1', '1ps'),
		section			= firstArg(args, 'section1', 'section', 'sec1', 'sec', 's1', 's'),
		['needed-reason'] = firstArg(args, 'needed-reason1', 'needed-reason', 'needed1', 'needed', 'reason'),
		['needed-date']	= firstArg(args, 'needed-date', 'date'),
		wrap			= args.wrap,
		['no-pp']		= firstArg(args, 'no-pp', 'nopp'),
		style			= args.style,
		['content-id']	= firstArg(args, 'ref1', '1ref', 'ref', 'id1', 'id'),
		['link-id']		= firstArg(args, 'link-id1', 'link-id'),
		['debug']		= args['debug']
	}, frame)

	-- ### 2+ ###
	local n = 2
	while firstArg(args, "name" .. n, "n" .. n, n) ~= nil do
		output[n] = r._ref({
			[1]				= firstArg(args, 'name' .. n, 'n' .. n, n),
			[2]				= firstArg(args, 'group', 'grp', 'g'),
			direction		= firstArgN(n, args, 'direction', 'dir'),
			page			= firstArg(args, 'page' .. n, 'p' .. n, n .. 'p'),
			pages			= firstArg(args, 'pages' .. n, 'pp' .. n, n .. 'pp'),
			location		= firstArg(args, 'location' .. n, 'loc' .. n, n .. 'loc', 'at' .. n),
			['quote-page']	= firstArgN(n, args, 'quotation-page', 'quote-page', 'qp'),
			['quote-pages']	= firstArgN(n, args, 'quotation-pages', 'quote-pages', 'qpp'),
			['quote-location'] = firstArgN(n, args, 'quotation-location', 'quote-location', 'quote-loc', 'quote-at'),
			quote			= firstArgN(n, args, 'quotation', 'quote', 'q'),
			language		= firstArgN(n, args,
				'quotation-language', 'quote-language',	'quotation-lang', 'quote-lang', 'ql', 'language', 'lang', 'l'
			),
			translation		= firstArgN(n, args,
				'translation-quotation', 'trans-quotation', 'translation-quote', 'trans-quote', 'tq', 'translation', 'trans', 't',
				'xlat'
			),
			['quote-cite']	= firstArgN(n, args, 'quotation-cite', 'quote-cite', 'qc'),
			reference		= firstArgN(n, args, 'reference', 'refn', 'r'),
			annotation		= firstArgN(n, args, 'annotation', 'annot', 'a'),
			leadin			= args.leadin,
			postscript		= firstArg(args, 'postscript' .. n, 'ps' .. n, n .. 'ps', 'postscript', 'ps'),
			section			= firstArgN(n, args, 'section', 'sec', 's'),
			['needed-reason'] = firstArgN(n, args, 'needed-reason', 'needed'),
			['needed-date']	= firstArg(args, 'needed-date', 'date'),
			['wrap']		= args['wrap'],
			['no-pp']		= firstArg(args, 'no-pp', 'nopp'),
			style			= args.style,
			['content-id']	= firstArg(args, 'ref' .. n, n .. 'ref', 'id' .. n),
			['link-id']		= args['link-id' .. n],
			['debug']		= args['debug'],
		}, frame)
		n = n + 1
	end
	return table.concat(output)
end
function r.r(frame)
	return r._r(getArgs(frame), frame)
end

-- Implements [[Template:Rp]]
function rp._rp(args, frame)
	frame = frame or mw.getCurrentFrame()
	-- If needed param is present and non-empty, show {{page needed}}
	if notblank(args.needed) then
		return page_needed(frame, args.date, args.reason)
	end

	-- prefix/suffix depending on style
	local ama = string.ulower(args.style or "") == "ama"
	local prefix = ama and "(" or "&#58;&hairsp;"
	local suffix = ama and ")" or "&hairsp;"

	-- p/pp is only used in superscript label, therefore it does not contain any qp params
	local pp = ""
	if ama and not notblank(args["no-pp"]) and not notblank(args.nopp) then
		if notblank(args.pages) or notblank(args.pp) then
			pp = "pp"
		elseif notblank(args.page) or notblank(args.p) then
			pp = "p"
		end
	end
	
	-- leadin is only used in tooltip
	local leadin
	local quote_switch = firstArg(args, "quotation-pages", "quote-pages", "qpp",
		"quotation-page", "quote-page", "qp",
		"quotation-location", "quote-location", "quote-loc", "quote-at")

	if not pageTest[quote_switch] then
		if notblank(firstArg(args, "quotation-pages", "quote-pages", "qpp")) then
			leadin = "Pages"
		elseif notblank(firstArg(args, "quotation-page", "quote-page", "qp")) then
			leadin = "Page"
		elseif notblank(firstArg(args, "quotation-location", "quote-location", "quote-loc", "quote-at")) then
			leadin = "Location"
		end
	end
	if not leadin then
		--either the quote_switch wasn't 'pages', 'pp', 'page',
		-- or 'p', or the 'quotation' params were all blank/nil
		if notblank(firstArg(args, "pages", "pp")) then
			leadin = "Pages"
		elseif notblank(firstArg(args, "page", "p")) then
			leadin = "Page"
		elseif notblank(firstArg(args, "location", "loc", "at")) then
			leadin = "Location"
		else
			leadin = "Page&nbsp;/ location"
		end
	end

	-- where must not include qp params
	local where = r._where{
		plural = hyphen2dash(firstArg(args, "pages", "pp", "1"), '&#32;'),
		singular = firstArg(args, "page", "p"),
		location = firstArg(args, "location", "loc", "at"),
		spacing = "&#32;"
	}

	-- sup-where same as where, but with improved list spacing for superscript
	local sup_where = r._where{
		plural = hyphen2dash(firstArg(args, "pages", "pp", "1"), '&hairsp;'),
		singular = firstArg(args, "page", "p"),
		location = firstArg(args, "location", "loc", "at"),
		spacing = "&hairsp;"
	}

	-- quote-where must not contain normal in-source-location params
	local quote_where
	if pageTest[quote_switch] then
		quote_where = r._where{
			plural = hyphen2dash(firstArg(args, "pages", "pp", 1), ' '),
			singular = firstArg(args, "page", "p"),
			location = firstArg(args, "location", "loc", "at"),
			spacing = "&#32;"
		}
	else
		quote_where = r._where{
			plural = hyphen2dash(firstArg(args, "quotation-pages", "quote-pages", "qpp"), ' '),
			singular = firstArg(args, "quotation-page", "quote-page", "qp"),
			location = firstArg(args, "quotation-location", "quote-location", "quote-loc", "quote-at"),
			spacing = "&#32;"
		}
	end

	local zws = ""
	if wrapTest[string.ulower(args.wrap or '')] then
		zws = "&#8203;" --zero-width space
	end

	return r._superscript{
		prefix = prefix,
		suffix = suffix,
		pp = pp,
		leadin = leadin,
		["where"] = where,
		["sup-where"] = sup_where,
		["quote-where"] = quote_where,
		quote = firstArg(args, "quotation", "quote", "q"),
		language = firstArg(args, "quotation-language", "quote-language",
			"quotation-lang", "quote-lang", "ql", "language", "lang", "l"),
		translation = firstArg(args, "translation-quotation", "trans-quotation",
			"translation-quote", "trans-quote", "tq", "translation", "trans",
			"t", "xlat"),
		["wrap"] = args.wrap
	} .. zws
end
function rp.rp(frame)
	return rp._rp(getArgs(frame), frame)
end

return {
	[''] = r.r,
	r = r.r,
	_r = r._r,
	rp = rp.rp,
	_rp = rp._rp,
	ref = r.ref,
	_ref = r._ref,
	where = r.where,
	_where = r._where,
	langcode = r.langcode,
	_langcode = r._langcode,
	superscript = r.superscript,
	_superscript = r._superscript
}