Module:Citation/CS1: Difference between revisions
Jump to navigation
Jump to search
sync from sandbox;
>Tomoneill (copy from https://en.wikipedia.org/w/index.php?title=Module:Citation/CS1&oldid=11868083413) |
>Trappist the monk (sync from sandbox;) |
||
Line 1,039: | Line 1,039: | ||
end | end | ||
end | end | ||
if nil == mw.ustring.find (last, "^[A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143%-%s%']*$") or | if nil == mw.ustring.find (last, "^[A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143\225\184\128-\225\187\191%-%s%']*$") or | ||
nil == mw.ustring.find (first, "^[A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143%-%s%'%.]*$") then | nil == mw.ustring.find (first, "^[A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143\225\184\128-\225\187\191%-%s%'%.]*$") then | ||
add_vanc_error (cfg.err_msg_supl['non-Latin char'], position); | add_vanc_error (cfg.err_msg_supl['non-Latin char'], position); | ||
return false; -- not a string of Latin characters; Vancouver requires Romanization | return false; -- not a string of Latin characters; Vancouver requires Romanization | ||
Line 1,065: | Line 1,065: | ||
]] | ]] | ||
local function reduce_to_initials(first, position) | local function reduce_to_initials (first, position) | ||
local name, suffix = mw.ustring.match(first, "^(%u+) ([%dJS][%drndth]+)$"); | if first:find (',', 1, true) then | ||
return first; -- commas not allowed; abandon | |||
end | |||
local name, suffix = mw.ustring.match (first, "^(%u+) ([%dJS][%drndth]+)$"); | |||
if not name then -- if not initials and a suffix | if not name then -- if not initials and a suffix | ||
name = mw.ustring.match(first, "^(%u+)$"); -- is it just initials? | name = mw.ustring.match (first, "^(%u+)$"); -- is it just initials? | ||
end | end | ||
Line 1,087: | Line 1,091: | ||
end -- if here then name has 3 or more uppercase letters so treat them as a word | end -- if here then name has 3 or more uppercase letters so treat them as a word | ||
local | local initials_t, names_t = {}, {}; -- tables to hold name parts and initials | ||
local i = 1; -- counter for number of initials | local i = 1; -- counter for number of initials | ||
names_t = mw.text.split (first, '[%s%-]+'); -- split into a sequence of names and possible suffix | |||
while | while names_t[i] do -- loop through the sequence | ||
if 1 < i and | if 1 < i and names_t[i]:match ('[%dJS][%drndth]+%.?$') then -- if not the first name, and looks like a suffix (may have trailing dot) | ||
names_t[i] = names_t[i]:gsub ('%.', ''); -- remove terminal dot if present | |||
if is_suffix ( | if is_suffix (names_t[i]) then -- if a legitimate suffix | ||
table.insert ( | table.insert (initials_t, ' ' .. names_t[i]); -- add a separator space, insert at end of initials sequence | ||
break; -- and done because suffix must fall at the end of a name | break; -- and done because suffix must fall at the end of a name | ||
end -- no error message if not a suffix; possibly because of Romanization | end -- no error message if not a suffix; possibly because of Romanization | ||
end | end | ||
if 3 > i then | if 3 > i then | ||
table.insert ( | table.insert (initials_t, mw.ustring.sub (names_t[i], 1, 1)); -- insert the initial at end of initials sequence | ||
end | end | ||
i = i + 1; -- bump the counter | i = i + 1; -- bump the counter | ||
end | end | ||
return table.concat( | return table.concat (initials_t); -- Vancouver format does not include spaces. | ||
end | end | ||
Line 1,247: | Line 1,251: | ||
if one then -- if <one> has a value (name, mdash replacement, or mask text replacement) | if one then -- if <one> has a value (name, mdash replacement, or mask text replacement) | ||
local proj, tag = interwiki_prefixen_get (one, true); -- get the interwiki prefixen if present | local proj, tag = interwiki_prefixen_get (one, true); -- get the interwiki prefixen if present | ||
if 'w' == proj and ('Wikipedia' == mw.site.namespaces.Project['name']) then | if 'w' == proj and ('Wikipedia' == mw.site.namespaces.Project['name']) then | ||
proj = nil; -- for stuff like :w:de:<article>, :w is unnecessary TODO: maint cat? | proj = nil; -- for stuff like :w:de:<article>, :w is unnecessary TODO: maint cat? | ||
end | end | ||
if proj then | if proj then | ||
local proj_name = ({['d'] = 'Wikidata', ['s'] = 'Wikisource', ['w'] = 'Wikipedia'})[proj]; -- :w (wikipedia) for linking from a non-wikipedia project | |||
if | if proj_name then | ||
one = one .. utilities.wrap_style ('interproj', | one = one .. utilities.wrap_style ('interproj', proj_name); -- add resized leading space, brackets, static text, language name | ||
utilities.add_prop_cat ('interproj-linked-name', proj); -- categorize it; <proj> is sort key | |||
tag = nil; -- unset; don't do both project and language | tag = nil; -- unset; don't do both project and language | ||
end | end | ||
Line 1,265: | Line 1,269: | ||
if lang then -- error messaging done in extract_names() where we know parameter names | if lang then -- error messaging done in extract_names() where we know parameter names | ||
one = one .. utilities.wrap_style ('interwiki', lang); -- add resized leading space, brackets, static text, language name | one = one .. utilities.wrap_style ('interwiki', lang); -- add resized leading space, brackets, static text, language name | ||
utilities.add_prop_cat ('interwiki-linked-name', tag); -- categorize it; <tag> is sort key | |||
end | end | ||
end | end | ||
Line 1,847: | Line 1,852: | ||
-- emit a maintenance message if user postscript is the default cs2 postscript | -- emit a maintenance message if user postscript is the default cs2 postscript | ||
-- we catch the opposite case for cs1 in set_cs_style | -- we catch the opposite case for cs1 in set_cs_style | ||
if 'cs2' == mode or 'citation' == cite_class then | if 'cs2' == mode or ('cs1' ~= mode and 'citation' == cite_class) then -- {{citation |title=Title |mode=cs1 |postscript=none}} should not emit maint message | ||
utilities.set_message ('maint_postscript'); | utilities.set_message ('maint_postscript'); | ||
end | end | ||
Line 1,973: | Line 1,978: | ||
--[[--------------------------< E X T R A _ T E X T _ I N _ V O L _ I S S _ C H E C K >------------------------ | --[[--------------------------< E X T R A _ T E X T _ I N _ V O L _ I S S _ C H E C K >------------------------ | ||
Adds error if |volume= or |issue= has what appears to be some form of redundant 'type' indicator. | Adds error if |volume= or |issue= has what appears to be some form of redundant 'type' indicator. Applies to | ||
both; this function looks for issue text in both |issue= and |volume= and looks for volume-like text in |voluem= | |||
and |issue=. | |||
For |volume=: | For |volume=: | ||
Line 1,982: | Line 1,989: | ||
For |issue=: | For |issue=: | ||
'No.', 'I.', 'Iss.' (with or without the dot) abbreviations, or 'Issue' in the first characters of the | 'No.', 'I.', 'Iss.' (with or without the dot) abbreviations, or 'Issue' in the first characters of the | ||
parameter content (all case insensitive). | parameter content (all case insensitive); numero styling: 'n°' with degree sign U+00B0, and № precomposed | ||
numero sign U+2116. | |||
Single character values ('v', 'i', 'n') allowed when not followed by separator character ('.', ':', '=', or | Single character values ('v', 'i', 'n') allowed when not followed by separator character ('.', ':', '=', or | ||
Line 2,000: | Line 2,008: | ||
end | end | ||
local handler = 'v' == selector and 'err_extra_text_volume' or 'err_extra_text_issue'; | local handler = 'v' == selector and 'err_extra_text_volume' or 'err_extra_text_issue'; | ||
val = val:lower(); -- force parameter value to lower case | val = val:lower(); -- force parameter value to lower case | ||
for _, pattern in ipairs ( | |||
for _, pattern in ipairs (cfg.vol_iss_pg_patterns.vi_patterns_t) do -- spin through the sequence table of patterns | |||
if val:match (pattern) then -- when a match, error so | if val:match (pattern) then -- when a match, error so | ||
utilities.set_message (handler, name); -- add error message | utilities.set_message (handler, name); -- add error message | ||
Line 2,465: | Line 2,472: | ||
local path, timestamp, flag; -- portions of the archive.org URL | local path, timestamp, flag; -- portions of the archive.org URL | ||
timestamp = url:match ('//archive.today/(%d%d%d%d%d%d%d%d%d%d%d%d%d%d)/') | timestamp = url:match ('//archive.today/(%d%d%d%d%d%d%d%d%d%d%d%d%d%d)/') or -- get timestamp from archive.today urls | ||
url:match ('//archive.today/(%d%d%d%d%.%d%d%.%d%d%-%d%d%d%d%d%d)/'); -- this timestamp needs cleanup | |||
if timestamp then -- if this was an archive.today url ... | if timestamp then -- if this was an archive.today url ... | ||
return url, date, timestamp; | return url, date, timestamp:gsub ('[%.%-]', ''); -- return ArchiveURL, ArchiveDate, and timestamp (dots and dashes removed) from |archive-url=, and done | ||
end | end | ||
-- here for archive.org urls | -- here for archive.org urls | ||
Line 2,918: | Line 2,926: | ||
local Encyclopedia = A['Encyclopedia']; -- used as a flag by this module and by ~/COinS | local Encyclopedia = A['Encyclopedia']; -- used as a flag by this module and by ~/COinS | ||
local ScriptEncyclopedia = A['ScriptEncyclopedia']; | |||
local TransEncyclopedia = A['TransEncyclopedia']; | |||
if utilities.is_set (Encyclopedia) then | if utilities.is_set (Encyclopedia) or utilities.is_set (ScriptEncyclopedia) then -- emit error message when Encyclopedia set but template is other than {{cite encyclopedia}} or {{citation}} | ||
if 'encyclopaedia' ~= config.CitationClass and 'citation' ~= config.CitationClass then | if 'encyclopaedia' ~= config.CitationClass and 'citation' ~= config.CitationClass then | ||
utilities.set_message ('err_parameter_ignored', {A:ORIGIN ('Encyclopedia')}); | if utilities.is_set (Encyclopedia) then | ||
Encyclopedia = nil; -- unset because not supported by this template | utilities.set_message ('err_parameter_ignored', {A:ORIGIN ('Encyclopedia')}); | ||
else | |||
utilities.set_message ('err_parameter_ignored', {A:ORIGIN ('ScriptEncyclopedia')}); | |||
end | |||
Encyclopedia = nil; -- unset these because not supported by this template | |||
ScriptEncyclopedia = nil; | |||
TransEncyclopedia = nil; | |||
end | end | ||
elseif utilities.is_set (TransEncyclopedia) then | |||
utilities.set_message ('err_trans_missing_title', {'encyclopedia'}); | |||
end | end | ||
Line 2,931: | Line 2,949: | ||
end | end | ||
if utilities.is_set (Encyclopedia) then | if utilities.is_set (Encyclopedia) or utilities.is_set (ScriptEncyclopedia) then | ||
Periodical = Encyclopedia; -- error or no, set Periodical to Encyclopedia for rendering; {{citation}} could (not legitimately) have both; use Encyclopedia | Periodical = Encyclopedia; -- error or no, set Periodical to Encyclopedia for rendering; {{citation}} could (not legitimately) have both; use Encyclopedia | ||
Periodical_origin = A:ORIGIN ('Encyclopedia'); | Periodical_origin = A:ORIGIN ('Encyclopedia'); | ||
ScriptPeriodical = ScriptEncyclopedia; | |||
ScriptPeriodical_origin = A:ORIGIN ('ScriptEncyclopedia'); | |||
if utilities.is_set (Title) or utilities.is_set (ScriptTitle) then | if utilities.is_set (Title) or utilities.is_set (ScriptTitle) then | ||
if not utilities.is_set (Chapter) then | if not utilities.is_set (Chapter) then | ||
Chapter = Title; -- |encyclopedia= and |title= are set so map |title= to |article= | Chapter = Title; -- |encyclopedia= and |title= are set so map |title= params to |article= params for rendering | ||
ScriptChapter = ScriptTitle; | ScriptChapter = ScriptTitle; | ||
ScriptChapter_origin = A:ORIGIN('ScriptTitle') | ScriptChapter_origin = A:ORIGIN('ScriptTitle') | ||
Line 2,943: | Line 2,963: | ||
ChapterURL = URL; | ChapterURL = URL; | ||
ChapterURL_origin = URL_origin; | ChapterURL_origin = URL_origin; | ||
ChapterUrlAccess = UrlAccess; | ChapterUrlAccess = UrlAccess; | ||
ChapterFormat = Format; | |||
if not utilities.is_set (ChapterURL) and utilities.is_set (TitleLink) then | if not utilities.is_set (ChapterURL) and utilities.is_set (TitleLink) then | ||
Chapter = utilities.make_wikilink (TitleLink, Chapter); | Chapter = utilities.make_wikilink (TitleLink, Chapter); | ||
end | end | ||
Title = Periodical; | Title = Periodical; -- now map |encyclopedia= params to |title= params for rendering | ||
ScriptTitle = ScriptPeriodical or ''; | |||
TransTitle = TransEncyclopedia or ''; | |||
Periodical = ''; -- redundant so unset | Periodical = ''; -- redundant so unset | ||
ScriptPeriodical = ''; | |||
URL = ''; | URL = ''; | ||
Format = ''; | Format = ''; | ||
TitleLink = ''; | TitleLink = ''; | ||
end | end | ||
elseif utilities.is_set (Chapter) or utilities.is_set (ScriptChapter) then | elseif utilities.is_set (Chapter) or utilities.is_set (ScriptChapter) then -- |title= not set | ||
Title = Periodical; -- |encyclopedia= set and |article= set so map |encyclopedia= to |title= for rendering | Title = Periodical; -- |encyclopedia= set and |article= set so map |encyclopedia= to |title= for rendering | ||
ScriptTitle = ScriptPeriodical or ''; | |||
TransTitle = TransEncyclopedia or ''; | |||
Periodical = ''; -- redundant so unset | Periodical = ''; -- redundant so unset | ||
ScriptPeriodical = ''; | |||
end | end | ||
end | end | ||
Line 3,136: | Line 3,159: | ||
local Year = A['Year']; | local Year = A['Year']; | ||
if utilities.is_set (Year) then | |||
validation.year_check (Year); -- returns nothing; emits maint message when |year= doesn't hold a 'year' value | |||
end | |||
if not utilities.is_set (Date) then | if not utilities.is_set (Date) then | ||
Date = Year; -- promote Year to Date | Date = Year; -- promote Year to Date | ||
Line 3,194: | Line 3,221: | ||
local error_list = {}; | local error_list = {}; | ||
anchor_year, Embargo = validation.dates(date_parameters_list, COinS_date, error_list); | anchor_year, Embargo = validation.dates(date_parameters_list, COinS_date, error_list); | ||
if utilities.is_set (Year) and utilities.is_set (Date) then -- both |date= and |year= not normally needed; | if utilities.is_set (Year) and utilities.is_set (Date) then -- both |date= and |year= not normally needed; | ||
validation.year_date_check (Year, A:ORIGIN ('Year'), Date, A:ORIGIN ('Date'), error_list); | validation.year_date_check (Year, A:ORIGIN ('Year'), Date, A:ORIGIN ('Date'), error_list); | ||
end | end | ||
if 0 == #error_list then -- error free dates only; 0 when error_list is empty | if 0 == #error_list then -- error free dates only; 0 when error_list is empty | ||
local modified = false; -- flag | local modified = false; -- flag | ||
Line 3,731: | Line 3,752: | ||
Series = utilities.is_set (Series) and wrap_msg ('series', {sepc, Series}) or ""; -- not the same as SeriesNum | Series = utilities.is_set (Series) and wrap_msg ('series', {sepc, Series}) or ""; -- not the same as SeriesNum | ||
local Agency = A['Agency']; | local Agency = A['Agency'] or ''; -- |agency= is supported by {{cite magazine}}, {{cite news}}, {{cite press release}}, {{cite web}}, and certain {{citation}} templates | ||
if utilities.is_set (Agency) then -- this testing done here because {{citation}} supports 'news' citations | |||
if utilities.in_array (config.CitationClass, {'magazine', 'news', 'pressrelease', 'web'}) or ('citation' == config.CitationClass and utilities.in_array (Periodical_origin, {"magazine", "newspaper", "work"})) then | |||
Agency = wrap_msg ('agency', {sepc, Agency}); -- format for rendering | |||
else | |||
Agency = ''; -- unset; not supported | |||
utilities.set_message ('err_parameter_ignored', {'agency'}); -- add error message | |||
end | |||
end | |||
Volume = format_volume_issue (Volume, Issue, ArticleNumber, config.CitationClass, Periodical_origin, sepc, use_lowercase); | Volume = format_volume_issue (Volume, Issue, ArticleNumber, config.CitationClass, Periodical_origin, sepc, use_lowercase); | ||
Line 3,952: | Line 3,981: | ||
local tcommon2; -- used for book cite when |contributor= is set | local tcommon2; -- used for book cite when |contributor= is set | ||
if | if utilities.in_array (config.CitationClass, {"book", "citation"}) and not utilities.is_set (Periodical) then -- special cases for book cites | ||
if utilities.is_set (Contributors) then -- when we are citing foreword, preface, introduction, etc. | if utilities.is_set (Contributors) then -- when we are citing foreword, preface, introduction, etc. | ||
tcommon = safe_join( {Title, TitleNote}, sepc ); | tcommon = safe_join ({Title, TitleNote}, sepc); -- author and other stuff will come after this and before tcommon2 | ||
tcommon2 = safe_join( { | tcommon2 = safe_join ({TitleType, Series, Language, Volume, Others, Edition, Publisher}, sepc); | ||
else | else | ||
tcommon = safe_join( {Title, TitleNote | tcommon = safe_join ({Title, TitleNote, TitleType, Series, Language, Volume, Others, Edition, Publisher}, sepc); | ||
end | end | ||
elseif 'map' == config.CitationClass then -- special cases for cite map | elseif 'map' == config.CitationClass then -- special cases for cite map | ||
if utilities.is_set (Chapter) then -- map in a book; TitleType is part of Chapter | if utilities.is_set (Chapter) then -- map in a book; TitleType is part of Chapter | ||
tcommon = safe_join( {Title | tcommon = safe_join ({Title, Edition, Scale, Series, Language, Cartography, Others, Publisher, Volume}, sepc); | ||
elseif utilities.is_set (Periodical) then -- map in a periodical | elseif utilities.is_set (Periodical) then -- map in a periodical | ||
tcommon = safe_join( {Title, TitleType | tcommon = safe_join ({Title, TitleType, Periodical, Scale, Series, Language, Cartography, Others, Publisher, Volume}, sepc); | ||
else -- a sheet or stand-alone map | else -- a sheet or stand-alone map | ||
tcommon = safe_join( {Title, TitleType | tcommon = safe_join ({Title, TitleType, Edition, Scale, Series, Language, Cartography, Others, Publisher}, sepc); | ||
end | end | ||
elseif 'episode' == config.CitationClass then -- special case for cite episode | elseif 'episode' == config.CitationClass then -- special case for cite episode | ||
tcommon = safe_join( {Title, TitleNote, TitleType, Series, Language, Edition, Publisher}, sepc ); | tcommon = safe_join ({Title, TitleNote, TitleType, Series, Language, Edition, Publisher}, sepc); | ||
else -- all other CS1 templates | else -- all other CS1 templates | ||
tcommon = safe_join( {Title, TitleNote, Conference, Periodical | tcommon = safe_join ({Title, TitleNote, Conference, Periodical, TitleType, Series, Language, Volume, Others, Edition, Publisher, Agency}, sepc); | ||
end | end | ||
Line 4,070: | Line 4,092: | ||
end | end | ||
end | end | ||
if utilities.is_set (PostScript) and PostScript ~= sepc then | if utilities.is_set (PostScript) and PostScript ~= sepc then | ||
text = safe_join( {text, sepc}, sepc ); -- Deals with italics, spaces, etc. | text = safe_join( {text, sepc}, sepc ); -- Deals with italics, spaces, etc. | ||
text = text: | if '.' == sepc then -- remove final seperator if present | ||
text = text:gsub ('%' .. sepc .. '$', ''); -- dot must be escaped here | |||
else | |||
text = mw.ustring.gsub (text, sepc .. '$', ''); -- using ustring for non-dot sepc (likely a non-Latin character) | |||
end | |||
end | end | ||
Line 4,226: | Line 4,252: | ||
return nil; | return nil; | ||
end | end | ||
-- replace | -- replace enumerator digit(s) with # (|last25= becomes |last#=) (mw.ustring because non-Western 'local' digits) | ||
enum_name = mw.ustring.gsub (name, '%d+$', '#'); -- where enumerator is last charaters in parameter name (these to protect |s2cid=) | enum_name = mw.ustring.gsub (name, '%d+$', '#'); -- where enumerator is last charaters in parameter name (these to protect |s2cid=) | ||
enum_name = mw.ustring.gsub (enum_name, '%d+([%-l])', '#%1'); -- where enumerator is in the middle of the parameter name; |author#link= is the oddity | enum_name = mw.ustring.gsub (enum_name, '%d+([%-l])', '#%1'); -- where enumerator is in the middle of the parameter name; |author#link= is the oddity |