Module:Footnotes/sandbox

From blackwiki
< Module:Footnotes
Revision as of 14:31, 8 August 2018 by test>Trappist the monk
Jump to navigation Jump to search

Documentation for this module may be created at Module:Footnotes/sandbox/doc

require('Module:No globals');

--[[--------------------------< A R G S _ D E F A U L T >------------------------------------------------------

a table to specify initial values.

]]

local args_default = {
	bracket_left = "",
	bracket_right = "",
	bracket_year_left = "",
	bracket_year_right = "",
	postscript = "",
	page = "",
	pages = "",
	location = "",
	article = "",
	page_sep = ", p.&nbsp;",
	pages_sep = ", pp.&nbsp;",
	ref = "",
	};


--[[--------------------------< T R I M >----------------------------------------------------------------------

TODO: get rid of this function

]]

local function trim( str )
	if str == nil then
		return nil;
	end
	return str:match( "^%s*(.-)%s*$");
end    


--[[--------------------------< I S _ Y E A R >----------------------------------------------------------------

evaluates param to see if it is one of these forms with or without lowercase letter disambiguator:
	YYYY
	n.d.
	nd	
	c. YYYY
	YYYY–YYYY	(separator is endash)

return true when param has a recognized form; false else

]]

local function is_year (param)
	return param:match ('^%d%d%d%d?%l?$') or param:match ('^n%.d%.%l?$') or param:match ('^nd%l?$') or param:match ('^c%. %d%d%d%d?%l?$') or param:match ('^%d%d%d%d–%d%d%d%d%l?$');
end


--[[--------------------------< C O R E >----------------------------------------------------------------------

returns an anchor link (CITEREF) formed from on to four author names, year, and insource location (|p=, |pp=, loc=)

]]

local function core( args )
	local result;

	if args.P5 ~= "" then
		if is_year (args.P5) then
			result = table.concat ({args.P1, ' et al. ', args.bracket_year_left, args.P5, args.bracket_year_right});
		else
			args.P5 = '';														-- when P5 not a year don't include in anchor
			result = table.concat ({args.P1, ' et al.'});						-- and don't render it
		end

	elseif args.P4 ~= "" then
		if is_year (args.P4) then
			result = table.concat ({args.P1, ', ', args.P2, ' &amp; ', args.P3, ' ', args.bracket_year_left, args.P4, args.bracket_year_right});	-- three names and a year
		else
			result = table.concat ({args.P1, ' et al.'});						-- four names
		end

	elseif args.P3 ~= "" then
		if is_year (args.P3) then
			result = table.concat ({args.P1, ' &amp; ', args.P2, ' ', args.bracket_year_left, args.P3, args.bracket_year_right});	-- two names and a year
		else
			result = table.concat ({args.P1, ', ', args.P2, ' ', ' &amp; ', args.P3});	-- three names
		end
			
	elseif args.P2 ~= "" then
		if is_year (args.P2) then
			result = table.concat ({args.P1, ' ', args.bracket_year_left, args.P2, args.bracket_year_right});	-- one name and year
		else
			result = table.concat ({args.P1, ' &amp; ', args.P2});				-- two names
		end
		
	else
		result = args.P1;														-- one name
	end
																				-- when author-date result ends with a dot (typically when the last positional parameter holds 'n.d.')
																				-- and when no in-source location (no |p=, |pp=, or |loc=)
																				-- and when the first or only character in args.postscript is a dot
																				-- remove the author-date result trailing dot
																				-- the author-date result trailing dot will be replaced later with the content of args.postscript (usually a dot)
	if ('.' == result:sub(-1)) and ('.' == args.postscript:sub(1)) and ('' == args.page) and ('' == args.pages) and ('' == args.location) then
		result = result:gsub ('%.$', '');
	end
	
	if args.ref ~= 'none' then
		if args.ref ~= "" then
			result = "[[" .. args.article .. "#" .. mw.uri.anchorEncode(args.ref) .. "|" .. result .. "]]";
		else
			result = "[[" .. args.article .. "#CITEREF" .. mw.uri.anchorEncode(args.P1 .. args.P2 .. args.P3 .. args.P4 .. args.P5) .. "|" .. result .. "]]";
		end
	end

	if args.page ~= "" then
		result = result .. args.page_sep .. args.page;
	elseif args.pages ~= "" then
		result = result .. args.pages_sep .. args.pages;
	end      

	if args.location ~= "" then
		result = result .. ", " .. args.location;
	end

	result = table.concat ({args.bracket_left, result, args.bracket_right, args.postscript}):gsub ('%s+', ' ');		-- strip redundant spaces
	return result;
end


--[[--------------------------< A R G S  _ F E T C H >---------------------------------------------------------

Because all of the templates share a common set of parameters, a single common function to fetch those parameters
from frame and parent frame.

]]

local function args_fetch (frame, ps)
	local args = args_default;													-- create a copy of the default table
	local pframe = frame:getParent();											-- point to the template's parameter table

	for k, v in pairs (frame.args) do											-- override defaults with values provided in the #invoke: if any
		args[k] = v;	   
	end
	
	args.postscript = pframe.args.postscript or pframe.args.ps or ps;
	if 'none' == args.postscript then
		args.postscript = '';
	end
	args.page = pframe.args.p or pframe.args.page or "";
	args.pages = pframe.args.pp or pframe.args.pages or "";
	args.location = pframe.args.loc or "";
	args.ref = pframe.args.ref or pframe.args.Ref or "";
	
	for i=1, 5 do																-- loop through the five positional parameters and trim if set else empty string
		args['P'..i] = (pframe.args[i] and mw.text.trim (pframe.args[i])) or "";
	end

	return args;
end


--[[--------------------------< H A R V A R D _ C O R E >------------------------------------------------------

entry point for templates that call {{harvard core}}

TODO: rewrite those templates to make direct calls into this module in a manner similar to {{sfnp}}

]]

local function harvard_core (frame)
	local args = {};
	local pframe = frame:getParent();

	args.bracket_left = pframe.args.BracketLeft or "";
	args.bracket_right = pframe.args.BracketRight or "";
	args.bracket_year_left = pframe.args.BracketYearLeft or "";
	args.bracket_year_right = pframe.args.BracketYearRight or "";
	args.postscript = pframe.args.Postscript or "";
	if 'none' == args.postscript then
		args.postscript = '';
	end

	args.page = pframe.args.Page or "";
	args.pages = pframe.args.Pages or "";
	args.location = pframe.args.Location or "";
	args.page_sep = pframe.args.PageSep or "";
	args.pages_sep = pframe.args.PagesSep or "";
	args.ref = pframe.args.REF or "{{{REF}}}";
	args.P1 = trim( pframe.args.P1 ) or "";
	args.P2 = trim( pframe.args.P2 ) or "";
	args.P3 = trim( pframe.args.P3 ) or "";
	args.P4 = trim( pframe.args.P4 ) or "";
	args.P5 = trim( pframe.args.P5 ) or "";

	return core( args );
end


--[[--------------------------< H A R V A R D _ C I T A T I O N >----------------------------------------------

entry point for {{harvard citation}}, its redirect {{harv}}, {{Harvard citation no brackets}} and its redirect {{harvnb}}

]]

local function harvard_citation (frame)
	local args = args_fetch (frame, '');										-- get the template and invoke parameters; default postscript is empty string

	return core (args);
end


--[[--------------------------< S T R I P _ U R L >------------------------------------------------------------

used only by sfn().  This function fixes an issue with reference tooltip gadget where the tooltip is not displayed
when an insource locator (|p=, |pp=, |loc=) has an external wikilink that contains a # character

strip uri-reserved characters from urls in |p=, |pp-, and |loc= parameters  The researved characters are:
	!#$&'()*+,/:;=?@[]
	
]]

local function strip_url (pages)
local escaped_uri;
	if not pages or ('' == pages) then
		return pages;
	end
	
	for uri in pages:gmatch ('%[(%a[%w%+%.%-]*://%S+)') do						-- for each external link get the uri
		escaped_uri = uri:gsub ("([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" );		-- save a copy with lua pattern characters escaped
		uri = uri:gsub ("[!#%$&'%(%)%*%+,/:;=%?@%[%]%.]", '');					-- remove reserved characters
		pages = pages:gsub (escaped_uri, uri, 1);								-- replace original uri with the stripped version
	end
	
	return pages;
end


--[[--------------------------< S F N >------------------------------------------------------------------------

entry point for {{sfn}} and {{sfnp}}

]]

local function sfn (frame)
	local args = args_fetch (frame, '.');										-- get the template and invoke parameters; default postscript is a dot

	local result = core (args);													-- go make a CITEREF anchor
	
																				-- put it all together and then strip redundant spaces
	local name = table.concat ({'FOOTNOTE', args.P1, args.P2, args.P3, args.P4, args.P5, strip_url (args.page), strip_url (args.pages), strip_url (args.location)}):gsub ('%s+', ' ');

	return frame:extensionTag ({name='ref', args={name=name}, content=result});	

	
end

local function sfnt( frame )
	local args = args_default;
	args.article = mw.title.getCurrentTitle().subjectPageTitle.fullText;
	return f.sfn(frame, args);
end

return {
	harvard_core = harvard_core,
	harvard_citation = harvard_citation,
--	harvard_citation_no_bracket = harvard_citation_no_bracket,
	sfn = sfn,
	sfnt = sfnt,
	};