Module:Footnotes/anchor id list: Difference between revisions
From All Skies Encyclopaedia
imported>Trappist the monk No edit summary |
imported>Trappist the monk No edit summary |
||
Line 286: | Line 286: | ||
return { |
return { |
||
citerefs = |
citerefs = harv_link_test, -- table of CITEREFs available in this article |
||
-- harv_link_test = harv_link_test, -- FOR DEBUG ONLY |
-- harv_link_test = harv_link_test, -- FOR DEBUG ONLY |
||
} |
} |
Revision as of 00:14, 1 March 2020
Documentation for this module may be created at Module:Footnotes/anchor id list/doc
require('Module:No globals');
local citerefs = {};
local redirects_citation = {
'[Cc]itation',
'[Cc]ite',
'[Cc]ite citation',
'[Cc]ite study',
'[Cc]ite [Tt]echnical standard',
}
local redirects_sfnref = {
'^[Ss]fn[Rr]ef$',
'^[Hh]arvid$',
}
local aliases_author = {
'last#',
'author#',
'surname#',
'author-last#',
'author#-last',
'subject#',
'host#',
}
local aliases_editor = {
'editor#',
'editor-last#',
'editor#-last',
'editor-surname#',
'editor#-surname',
}
local aliases_date = {
'year',
'date',
'publicationdate',
'publication-date',
}
local patterns_date = {
'^(%d%d%d%d–%d%d%d%d%l?)$', -- YYYY–YYYY four-digit year range; with or without dab
'^(%d%d%d%d–%d%d%l?)$', -- YYYY–YY two-digit year range; with or without dab
'(%d%d%d%d?%l?)$', -- three- or four-digit year at end of date (dmy or mdy); with or without dab
'^(%d%d%d%d?%l?)', -- three- or four-digit year at end of date (ymd or YYYY); with or without dab
'^(n%.d%.%l?)$', -- 'no date' with dots; with or without dab
'^(nd%l?)$', -- 'no date' without dots; with or without dab
'^(c%. %d%d%d%d?%l?$)$', -- three- or four-digit circa year; with or without dab
}
--[[--------------------------< I S _ T E M P L A T E >--------------------------------------------------------
is the template one that is listed in the redirects table; returns true if found; nil else.
]]
local function is_template (template, redirects)
for _, redirect in ipairs (redirects) do -- spin through the redirects table
if template:match (redirect) then -- if found
return true -- done
end
end
return false; -- not found and done
end
--[[--------------------------< S F N R E F _ G E T >----------------------------------------------------------
make a CITEREF from the contents of {{sfnref}} or {{harvid}}. this function assumes that {{sfnref}} and {{harvid}}
are correctly formed.
]]
local function sfnref_get (template)
template = template:gsub ('{{%s*(.-)%s*}}', '%1'); -- strip bounding template markup and trim
local parts = mw.text.split (template, '%s*|%s*'); -- split at the pipe and remove extraneous space characters
if is_template (parts[1], redirects_sfnref) then
return table.concat (parts, '', 2); -- assume that sfnref template is properly formed, concatenate and done
end
return nil;
end
--[[--------------------------< D A T E _ G E T >--------------------------------------------------------------
extract year from one of |year=, |date=, |publicationdate=, or |publication-date in that order. Does not error
check (that is left to the cs1|2 templates to do)
]]
local function date_get (params)
local date;
for _, alias in ipairs (aliases_date) do -- spin through the date aliases
if params[alias] then -- if cs1|2 template has this date-alias parameter
for _, pattern in ipairs (patterns_date) do -- spin through the recognized date formats
date = params[alias]:match (pattern); -- has a year-portion is recognized; nil else
if date then
return date; -- matched so return
end
end
end
end
return ''; -- no date param or date param doesn't hold a recognized date; empty string for concatenation
end
--[[--------------------------< N A M E S _ G E T >------------------------------------------------------------
get the author names from the cs1|2 template; if there are no authors names, attempt to get editor names.
returns concatenated names in enumeration order when successful; nil else
missing names (missing or empty |lastn= parameter) are omitted but the other names are included.
]]
local function names_get (params, aliases_list)
local names = {}; -- first four author or editor names go here
local enum_alias; -- alias with '#' replaced with a digit
for i, alias in ipairs (aliases_list) do
for enum=1, 5 do
enum_alias = alias:gsub ('#', enum); -- replace '#' to make 'lastn'
if 1 == enum then -- because |last= and last1= are exact aliases
if params[enum_alias] then -- test |last1= first
names[enum] = params[enum_alias]; -- found so save the value assigned to |last1=
else
enum_alias = alias:gsub ('#', ''); -- replace '#' to make 'last'
if params[enum_alias] then
names[enum] = params[enum_alias]; -- found so save the value assigned to |last=
end
end
else -- here for enum 2, 3, 4
if params[enum_alias] then
names[enum] = params[enum_alias]; -- found so save the value assigned to |lastn=
end
end
end
end
return 0 ~= #names and table.concat (names) or nil -- return a concatenation of the names; nil else
end
--[[--------------------------< T E M P L A T E _ S T R I P >--------------------------------------------------
Templates are not allowed in parameters that are made part of COinS metadata; yet, they will appear. cs1|2 does
not see the template markup but instead sees the result of the template as html. cs1|2 strips the html which
leaves the displayed value for the CITEREF. We can't necessarily do that here so, because templates aren't allowed
in parameters, we simply discard any templates found in the cs1|2 template.
this may leave a |lastn= parameter empty which will be treated as if it were really empty as cs1|2 do (three authors,
|last2= empty -> CITEREFLast1Last3YYYY (the harv and sfn render: 'Last1, & Last3 YYYY' with CITEREFLast1Last3YYYY).
]]
local function template_strip (template)
template = template:gsub ('^{{', ''):gsub ('}}$', '', 1); -- remove outer {{ and }} (cs1|2 template delimiters)
template = template:gsub ('%b{}', ''); -- remove any templates from the cs1|2 template
return template;
end
--[=[-------------------------< W I K I L I N K _ S T R I P >--------------------------------------------------
Wikilink markup des not belong in CITEREF and can / does confuse the code that parses apart the cs1|2 template so
here we remove any wiki markup:
[[link|label]] -> label text
[[link]] -> link text
]=]
local function wikilink_strip (template)
template = template:gsub ('%[%[.-|(.-)%]%]', '%1'); -- replace complex [[link|lable]] wikilinks with label text
template = template:gsub ('%[%[(.-)%]%]', '%1'); -- replace simple [[link]] wikilinks with link text
return template;
end
--[[--------------------------< C I T E R E F _ M A K E >------------------------------------------------------
inspect |ref= to decide what to do:
|ref=harv - get names and date from template parameters
|ref=CITEREF... - take everything after 'CITEREF'
|ref={{SfnRef|name|name|name|name|year}} - assemble CITEREF from positional parameters
|ref={{Harvid|name|name|name|name|year}} - assemble CITEREF from positional parameters
|ref=none - skip; do nothing because CITEREF intentionally suppressed; TODO: keep with a type code of '0'?
|ref= - empty or missing
for cs1: skip
for cs2: get names and date from template parameters
|ref=??? - skip; not CITEREF compatible
]]
local function citeref_make (template)
local ref; -- content of |ref=
local template_name; -- name of the template for cs2 detection
local citeref; -- the assembled CITEREF from this template
local params = {}; -- table of cs1|2 parameters
template_name = template:match ('{{%s*([^|]+)'):lower(); -- get lowercase template name
ref = template:match ('|%s*ref%s*=%s*(%b{})'); -- first look for |ref={{sfnref}} or |ref={{harvid}}
if not ref then -- if not found
if template:match ('|%s*ref%s*=([^|}]+)') then -- if there is a |ref= param with an assigned value
ref = template:match ('|%s*ref%s*=([^|}]+)'):gsub ('%s*(.-)%s*', '%1'); -- because we will strip templates from the cs1|2 template and ref migh hold |ref={{sfnref}} or |ref={{harvid}}
else -- here when |ref= missing or empty
if is_template (template, redirects_citation) then -- could be cs2
ref = 'harv'; -- spoof to handle cs2 as if it were cs1 with |ref=harv
end
end
end
template = wikilink_strip (template); -- because piped wikilinks confuses code that builds params{} and because plain wikilinks not allowed in CITEREF
-- strip templates after getting |ref= value because |ref={{sfnref}} and |ref={{harvid}} are allowed
template = template_strip (template); -- because template markup can confuse code that builds params{} and because templates in name parameters are not allowed
for param, value in template:gmatch ('|%s*([^=]-)%s*=%s*([^|}]+)') do -- build a table of template parameters and their values
params[param] = mw.text.trim (value);
end
if 'harv' == ref then -- |ref=harv
citeref = names_get (params, aliases_author) or names_get (params, aliases_editor); -- get author name; if none then get editor names
if citeref then -- if names were gotten
citeref = citeref .. date_get (params); -- get date portion
end
elseif ref:match ('CITEREF(.+)') then -- for hand-created CITEREFs, take everything but the 'CITEREF' prefix
citeref = ref:match ('CITEREF(.+)');
elseif ref:match ('%b{}') then -- ref holds a template
citeref = sfnref_get (ref); -- returns content of {{sfnref}} or {{harvid}}; nil else
elseif 'none' == ref then -- |ref=none
return nil; -- CITEREF expicitly suppressed
elseif '' ~= ref then -- |ref=??? TODO: keep this content because {{harv}} etc has |ref= parameter that overrides CITEREF?
return nil; -- text other than something acceptible as a CITEREF
end
return citeref; -- citeref text without 'CITEREF' prefix if found or decoded; nil else
end
--[[--------------------------< H A R V _ L I N K _ T E S T >--------------------------------------------------
]]
local function harv_link_test ()
local article_content = mw.title.getCurrentTitle():getContent() or ''; -- get the content of the article or ''; new pages edited w/ve do not have 'content' until saved; ve does not preview; phab:T221625
if '' == article_content then -- when there is no article content
return ''; -- no point in continuing
end
local tstart, tend, _ = article_content:find ('{{%s*[Vv]?[Cc]it[ae]'); -- find the first cs1|2 template (or vcite xxx template)
local template; -- place to hold the template that we found
local citeref; -- place to hold CITEREFs as they are extracted / decoded
while tstart do -- nil when cs1|2 / vcite template not found
template = article_content:match ('%b{}', tstart); -- get the whole template
if template then -- necessary?
citeref = citeref_make (template); -- extract CITEREF from this template
if citeref then -- if there was a CITEREF extracted
citeref = mw.uri.anchorEncode (citeref); -- encode to remove wikimarkup, convert spaces to underscores etc
if not citerefs[citeref] then -- if not already saved
citerefs[citeref] = 1; -- save it
else -- here when this CITEREF already saved
citerefs[citeref] = 2; -- to indicate that there are multiple same name/date citations
end
end
end
tstart = tend; -- reset the search starting index
tstart, tend, _ = article_content:find ('{{%s*[Vv]?[Cc]it[ae]', tstart); -- search for another cs1|2 / vcite template
end
-- return mw.dumpObject (citerefs);
return citerefs;
end
--[[--------------------------< E X P O R T E D _ T A B L E S >------------------------------------------------
]]
return {
citerefs = harv_link_test, -- table of CITEREFs available in this article
-- harv_link_test = harv_link_test, -- FOR DEBUG ONLY
}