Module:Citation/CS1: Difference between revisions
Synch from sandbox;
m>Trappist the monk (try again; vauthors generational suffix fix;) |
m>Trappist the monk (Synch from sandbox;) |
||
Line 22: | Line 22: | ||
--[[--------------------------< P A G E S C O P E V A R I A B L E S >-------------------------------------- | --[[--------------------------< P A G E S C O P E V A R I A B L E S >-------------------------------------- | ||
delare variables here that have page-wide scope | delare variables here that have page-wide scope that are not brought in from other modules; thatare created here | ||
and used here | |||
]] | ]] | ||
local | local added_deprecated_cat; -- boolean flag so that the category is added only once | ||
local added_prop_cats = {}; -- list of property categories that have been added to z.properties_cats | |||
local added_vanc_errs; -- boolean flag so we only emit one Vancouver error / category | |||
local Frame; -- holds the module's frame table | |||
--[[--------------------------< F I R S T _ S E T >------------------------------------------------------------ | --[[--------------------------< F I R S T _ S E T >------------------------------------------------------------ | ||
Line 52: | Line 58: | ||
Adds a category to z.properties_cats using names from the configuration file with additional text if any. | Adds a category to z.properties_cats using names from the configuration file with additional text if any. | ||
added_prop_cats is a table declared in page scope variables above | |||
]] | ]] | ||
local function add_prop_cat (key, arguments) | local function add_prop_cat (key, arguments) | ||
if not added_prop_cats [key] then | if not added_prop_cats [key] then | ||
Line 67: | Line 74: | ||
Adds a single Vancouver system error message to the template's output regardless of how many error actually exist. | Adds a single Vancouver system error message to the template's output regardless of how many error actually exist. | ||
To prevent duplication, added_vanc_errs is nil until an error message is emitted. | To prevent duplication, added_vanc_errs is nil until an error message is emitted. | ||
added_vanc_errs is a boolean declared in page scope variables above | |||
]] | ]] | ||
local function add_vanc_error (source) | local function add_vanc_error (source) | ||
if not added_vanc_errs then | if not added_vanc_errs then | ||
Line 407: | Line 415: | ||
offending parameter name to the error message. Only one error message is emitted regardless of the number of deprecated | offending parameter name to the error message. Only one error message is emitted regardless of the number of deprecated | ||
parameters in the citation. | parameters in the citation. | ||
added_deprecated_cat is a boolean declared in page scope variables above | |||
]] | ]] | ||
local function deprecated_parameter(name) | local function deprecated_parameter(name) | ||
if not | if not added_deprecated_cat then | ||
added_deprecated_cat = true; -- note that we've added this category | |||
table.insert( z.message_tail, { set_error( 'deprecated_params', {name}, true ) } ); -- add error message | table.insert( z.message_tail, { set_error( 'deprecated_params', {name}, true ) } ); -- add error message | ||
end | end | ||
Line 425: | Line 434: | ||
" 'Kerned title with leading and trailing single quote marks' " (in real life the kerning isn't as wide as this example) | " 'Kerned title with leading and trailing single quote marks' " (in real life the kerning isn't as wide as this example) | ||
Double single quotes (italic or bold wikimarkup) are not kerned. | Double single quotes (italic or bold wikimarkup) are not kerned. | ||
Replaces unicode quotemarks with typewriter quote marks regardless of the need for kerning. | |||
Call this function for chapter titles, for website titles, etc; not for book titles. | Call this function for chapter titles, for website titles, etc; not for book titles. | ||
Line 433: | Line 444: | ||
local cap=''; | local cap=''; | ||
local cap2=''; | local cap2=''; | ||
-- TODO: move this elswhere so that all title-holding elements get these quote marks replaced? | |||
str= mw.ustring.gsub (str, '[“”]', '\"'); -- replace “” (U+201C & U+201D) with " (typewriter double quote mark) | |||
str= mw.ustring.gsub (str, '[‘’]', '\''); -- replace ‘’ (U+2018 & U+2019) with ' (typewriter single quote mark) | |||
cap, cap2 = str:match ("^([\"\'])([^\'].+)"); -- match leading double or single quote but not double single quotes | cap, cap2 = str:match ("^([\"\'])([^\'].+)"); -- match leading double or single quote but not double single quotes | ||
Line 887: | Line 901: | ||
to use an external editor to maintain this code. | to use an external editor to maintain this code. | ||
\195\128-\195\150 – À-Ö | \195\128-\195\150 – À-Ö (U+00C0–U+00D6 – C0 controls) | ||
\195\152-\195\182 – Ø-ö | \195\152-\195\182 – Ø-ö (U+00D8-U+00F6 – C0 controls) | ||
\195\184-\198\191 – ø-ƿ | \195\184-\198\191 – ø-ƿ (U+00F8-U+01BF – C0 controls, Latin extended A & B) | ||
\199\132-\201\143 – DŽ-ɏ | \199\132-\201\143 – DŽ-ɏ (U+01C4-U+024F – Latin extended B) | ||
]] | ]] | ||
Line 966: | Line 980: | ||
end | end | ||
return table.concat(initials) -- Vancouver format does not include spaces. | return table.concat(initials) -- Vancouver format does not include spaces. | ||
end | end | ||
Line 1,477: | Line 1,486: | ||
end | end | ||
--[[--------------------------< G E T _ V _ N A M E _ T A B L E >---------------------------------------------- | |||
split apart a |vautthors= or |veditors= parameter. This function allows for corporate names, wrapped in doubled | |||
parentheses to also have commas; in the old version of the code, the doubled parnetheses were included in the | |||
rendered citation and in the metadata. | |||
|vauthors=Jones AB, White EB, ((Black, Brown, and Co.)) | |||
This code is experimental and may not be retained. | |||
]] | |||
local function get_v_name_table (vparam, output_table) | |||
local name_table = mw.text.split(vparam, "%s*,%s*"); -- names are separated by commas | |||
local i = 1; | |||
while name_table[i] do | |||
if name_table[i]:match ('^%(%(.*[^%)][^%)]$') then -- first segment of corporate with one or more commas; this segment has the opening doubled parens | |||
local name = name_table[i]; | |||
i=i+1; -- bump indexer to next segment | |||
while name_table[i] do | |||
name = name .. ', ' .. name_table[i]; -- concatenate with previous segments | |||
if name_table[i]:match ('^.*%)%)$') then -- if this table member has the closing doubled parens | |||
break; -- and done reassembling so | |||
end | |||
i=i+1; -- bump indexer | |||
end | |||
table.insert (output_table, name); -- and add corporate name to the output table | |||
else | |||
table.insert (output_table, name_table[i]); -- add this name | |||
end | |||
i = i+1; | |||
end | |||
return output_table; | |||
end | |||
--[[--------------------------< P A R S E _ V A U T H O R S _ V E D I T O R S >-------------------------------- | --[[--------------------------< P A R S E _ V A U T H O R S _ V E D I T O R S >-------------------------------- | ||
Line 1,504: | Line 1,548: | ||
add_vanc_error ('wikilink'); | add_vanc_error ('wikilink'); | ||
end | end | ||
v_name_table = | v_name_table = get_v_name_table (vparam, v_name_table); -- names are separated by commas | ||
for i, v_name in ipairs(v_name_table) do | for i, v_name in ipairs(v_name_table) do | ||
Line 1,544: | Line 1,588: | ||
end | end | ||
else | else | ||
is_good_vanc_name (last, ''); | if not corporate then | ||
is_good_vanc_name (last, ''); | |||
end | |||
end | end | ||
-- this from extract_names () | -- this from extract_names () | ||
link = select_one( args, cfg.aliases[list_name .. '-Link'], 'redundant_parameters', i ); | link = select_one( args, cfg.aliases[list_name .. '-Link'], 'redundant_parameters', i ); | ||
Line 1,555: | Line 1,599: | ||
return names, etal; -- all done, return our list of names | return names, etal; -- all done, return our list of names | ||
end | end | ||
--[[--------------------------< S E L E C T _ A U T H O R _ E D I T O R _ S O U R C E >------------------------ | --[[--------------------------< S E L E C T _ A U T H O R _ E D I T O R _ S O U R C E >------------------------ | ||
Line 1,576: | Line 1,621: | ||
local function select_author_editor_source (vxxxxors, xxxxors, args, list_name) | local function select_author_editor_source (vxxxxors, xxxxors, args, list_name) | ||
local lastfirst = false; | local lastfirst = false; | ||
if select_one( args, cfg.aliases[list_name .. '-Last'], 'none', 1 ) or -- do this twice incase we have a | if select_one( args, cfg.aliases[list_name .. '-Last'], 'none', 1 ) or -- do this twice incase we have a |first1= without a |last1=; this ... | ||
select_one( args, cfg.aliases[list_name .. '-Last'], 'none', 2 ) then | select_one( args, cfg.aliases[list_name .. '-First'], 'none', 1 ) or -- ... also catches the case where |first= is used with |vauthors= | ||
select_one( args, cfg.aliases[list_name .. '-Last'], 'none', 2 ) or | |||
select_one( args, cfg.aliases[list_name .. '-First'], 'none', 2 ) then | |||
lastfirst=true; | lastfirst=true; | ||
end | end | ||
Line 1,661: | Line 1,708: | ||
end | end | ||
end | end | ||
local vol = ''; | local vol = ''; | ||
Line 1,668: | Line 1,715: | ||
vol = substitute (cfg.messages['j-vol'], {sepc, volume}); | vol = substitute (cfg.messages['j-vol'], {sepc, volume}); | ||
else | else | ||
vol = | vol = substitute (cfg.presentation['vol-bold'], {sepc, hyphen_to_dash(volume)}); | ||
end | end | ||
end | end | ||
Line 1,676: | Line 1,723: | ||
return vol; | return vol; | ||
end | end | ||
Line 1,699: | Line 1,742: | ||
end | end | ||
]] | ]] | ||
--[[-------------------------< F O R M A T _ P A G E S _ S H E E T S >----------------------------------------- | --[[-------------------------< F O R M A T _ P A G E S _ S H E E T S >----------------------------------------- | ||
Line 1,795: | Line 1,839: | ||
if url:match('//web%.archive%.org/save/') then -- if a save command url, we don't want to allow saving of the target page | if url:match('//web%.archive%.org/save/') then -- if a save command url, we don't want to allow saving of the target page | ||
err_msg = 'save command'; | |||
if | url = url:gsub ('(//web%.archive%.org)/save/', '%1/*/', 1); -- for preview mode: modify ArchiveURL | ||
else | |||
path, timestamp, flag = url:match('//web%.archive%.org/([^%d]*)(%d+)([^/]*)/'); -- split out some of the url parts for evaluation | |||
if not is_set(timestamp) or 14 ~= timestamp:len() then -- path and flag optional, must have 14-digit timestamp here | |||
err_msg = 'timestamp'; | |||
if '*' ~= flag then | |||
url=url:gsub ('(//web%.archive%.org/[^%d]*%d?%d?%d?%d?%d?%d?)[^/]*', '%1*', 1) -- for preview, modify ts to be yearmo* max (0-6 digits plus splat) | |||
end | |||
elseif is_set(path) and 'web/' ~= path then -- older archive urls do not have the extra 'web/' path element | |||
err_msg = 'path'; | |||
elseif is_set (flag) and not is_set (path) then -- flag not allowed with the old form url (without the 'web/' path element) | |||
err_msg = 'flag'; | |||
elseif is_set (flag) and not flag:match ('%a%a_') then -- flag if present must be two alpha characters and underscore (requires 'web/' path element) | |||
err_msg = 'flag'; | |||
else | else | ||
return | return url, date; -- return archiveURL and ArchiveDate | ||
end | end | ||
end | end | ||
-- if here, something not right so | |||
-- if | table.insert( z.message_tail, { set_error( 'archive_url', {err_msg}, true ) } ); -- add error message and | ||
if is_set (Frame:preprocess('{{REVISIONID}}')) then | |||
return '', ''; -- return empty strings for archiveURL and ArchiveDate | |||
if | |||
else | else | ||
return url, date; -- preview mode so return archiveURL and ArchiveDate | return url, date; -- preview mode so return archiveURL and ArchiveDate | ||
end | end | ||
end | end | ||
Line 1,890: | Line 1,925: | ||
elseif 3 == selected then | elseif 3 == selected then | ||
Authors = A['Authors']; -- use content of |authors= | Authors = A['Authors']; -- use content of |authors= | ||
if 'authors' == A:ORIGIN('Authors') then -- but add a maint cat if the parameter is |authors= | |||
add_maint_cat ('authors'); -- because use of this parameter is discouraged; what to do about the aliases is a TODO: | |||
end | |||
end | end | ||
if is_set (Collaboration) then | if is_set (Collaboration) then | ||
Line 1,912: | Line 1,950: | ||
elseif 3 == selected then | elseif 3 == selected then | ||
Editors = A['Editors']; -- use content of |editors= | Editors = A['Editors']; -- use content of |editors= | ||
add_maint_cat ('editors'); -- but add a maint cat because use of this parameter is discouraged | |||
end | end | ||
end | end | ||
Line 2,178: | Line 2,217: | ||
-- Special case for cite techreport. | -- Special case for cite techreport. | ||
if (config.CitationClass == "techreport") then -- special case for cite techreport | if (config.CitationClass == "techreport") then -- special case for cite techreport | ||
if is_set(A['Number']) then | if is_set(A['Number']) then -- cite techreport uses 'number', which other citations alias to 'issue' | ||
if not is_set(ID) then -- can we use ID for the "number"? | if not is_set(ID) then -- can we use ID for the "number"? | ||
ID = A['Number']; | ID = A['Number']; -- yes, use it | ||
else -- ID has a value so emit error message | else -- ID has a value so emit error message | ||
table.insert( z.message_tail, { set_error('redundant_parameters', {wrap_style ('parameter', 'id') .. ' and ' .. wrap_style ('parameter', 'number')}, true )}); | table.insert( z.message_tail, { set_error('redundant_parameters', {wrap_style ('parameter', 'id') .. ' and ' .. wrap_style ('parameter', 'number')}, true )}); | ||
Line 2,187: | Line 2,226: | ||
end | end | ||
-- special case for cite interview | -- special case for cite interview -- TODO: make cite interveiw not need special cases | ||
if (config.CitationClass == "interview") then | if (config.CitationClass == "interview") then | ||
if is_set(Program) then | if is_set(Program) then | ||
Line 2,209: | Line 2,248: | ||
if is_set(Others) then | if is_set(Others) then | ||
if is_set(TitleType) then | if is_set(TitleType) then | ||
Others = ' ' | Others = substitute (cfg.messages['interview-type'], {TitleType, Others}); | ||
TitleType = ''; | TitleType = ''; | ||
else | else | ||
Others = | Others = substitute (cfg.messages['interview'], Others) | ||
end | end | ||
else | else | ||
Others = ' | Others = cfg.title_types ['interview']; | ||
end | end | ||
end | end | ||
Line 2,342: | Line 2,381: | ||
end | end | ||
if first_set ({AccessDate, At, Chapter, Format, Page, Pages, Periodical, PublisherName, URL, -- a crude list of parameters that are not supported by cite arxiv | if first_set ({AccessDate, At, Authors, Chapter, Format, Page, Pages, Periodical, PublisherName, URL, -- a crude list of parameters that are not supported by cite arxiv | ||
ID_list['ASIN'], ID_list['BIBCODE'], ID_list['DOI'], ID_list['ISBN'], ID_list['ISSN'], | ID_list['ASIN'], ID_list['BIBCODE'], ID_list['DOI'], ID_list['ISBN'], ID_list['ISSN'], -- TODO: find a better way to do this | ||
ID_list['JFM'], ID_list['JSTOR'], ID_list['LCCN'], ID_list['MR'], ID_list['OCLC'], ID_list['OL'], | ID_list['JFM'], ID_list['JSTOR'], ID_list['LCCN'], ID_list['MR'], ID_list['OCLC'], ID_list['OL'], | ||
ID_list['OSTI'], ID_list['PMC'], ID_list['PMID'], ID_list['RFC'], ID_list['SSRN'], ID_list['USENETID'], ID_list['ZBL']},27) then | ID_list['OSTI'], ID_list['PMC'], ID_list['PMID'], ID_list['RFC'], ID_list['SSRN'], ID_list['USENETID'], ID_list['ZBL']},27) then | ||
table.insert( z.message_tail, { set_error( 'arxiv_params_not_supported', {}, true ) } ); -- add error message | table.insert( z.message_tail, { set_error( 'arxiv_params_not_supported', {}, true ) } ); -- add error message | ||
AccessDate= ''; | AccessDate = ''; -- set these to empty string; not supported in cite arXiv | ||
Authors = ''; | |||
PublisherName = ''; -- (if the article has been published, use cite journal, or other) | PublisherName = ''; -- (if the article has been published, use cite journal, or other) | ||
Chapter = ''; | Chapter = ''; | ||
Line 2,362: | Line 2,402: | ||
TitleType = set_titletype (config.CitationClass, TitleType); | TitleType = set_titletype (config.CitationClass, TitleType); | ||
if is_set(Degree) and "Thesis" == TitleType then -- special case for cite thesis | if is_set(Degree) and "Thesis" == TitleType then -- special case for cite thesis | ||
TitleType = Degree .. | TitleType = Degree .. ' ' .. cfg.title_types ['thesis']:lower(); | ||
end | end | ||
end | end | ||
Line 2,370: | Line 2,410: | ||
end | end | ||
-- legacy: | -- legacy: promote PublicationDate to Date if neither Date nor Year are set. | ||
if not is_set (Date) then | if not is_set (Date) then | ||
Date = Year; -- promote Year to Date | Date = Year; -- promote Year to Date | ||
Line 2,430: | Line 2,470: | ||
table.insert( z.message_tail, { set_error( 'bad_date', {error_message}, true ) } ); -- add this error message | table.insert( z.message_tail, { set_error( 'bad_date', {error_message}, true ) } ); -- add this error message | ||
end | end | ||
end -- end of do | end -- end of do | ||
Line 2,453: | Line 2,480: | ||
URL=cfg.id_handlers['PMC'].prefix .. ID_list['PMC']; -- set url to be the same as the PMC external link if not embargoed | URL=cfg.id_handlers['PMC'].prefix .. ID_list['PMC']; -- set url to be the same as the PMC external link if not embargoed | ||
URLorigin = cfg.id_handlers['PMC'].parameters[1]; -- set URLorigin to parameter name for use in error message if citation is missing a |title= | URLorigin = cfg.id_handlers['PMC'].parameters[1]; -- set URLorigin to parameter name for use in error message if citation is missing a |title= | ||
if is_set(AccessDate) then -- access date requires |url=; pmc created url is not |url= | |||
table.insert( z.message_tail, { set_error( 'accessdate_missing_url', {}, true ) } ); | |||
AccessDate = ''; -- unset | |||
end | |||
end | end | ||
end | end | ||
Line 2,541: | Line 2,573: | ||
do | do | ||
local last_first_list; | local last_first_list; | ||
local control = { | local control = { | ||
format = NameListFormat, -- empty string or 'vanc' | format = NameListFormat, -- empty string or 'vanc' | ||
Line 2,631: | Line 2,662: | ||
end | end | ||
local OriginalURL, OriginalURLorigin, OriginalFormat; | local OriginalURL, OriginalURLorigin, OriginalFormat; | ||
DeadURL = DeadURL:lower(); -- used later when assembling archived text | DeadURL = DeadURL:lower(); -- used later when assembling archived text | ||
if is_set( ArchiveURL ) then | if is_set( ArchiveURL ) then | ||
if is_set (ChapterURL) then | if is_set (ChapterURL) then -- URL not set so if chapter-url is set apply archive url to it | ||
OriginalURL = ChapterURL; -- save copy of source chapter's url for archive text | OriginalURL = ChapterURL; -- save copy of source chapter's url for archive text | ||
OriginalURLorigin = ChapterURLorigin; -- name of chapter-url parameter for error messages | OriginalURLorigin = ChapterURLorigin; -- name of chapter-url parameter for error messages | ||
Line 2,708: | Line 2,739: | ||
Title = kern_quotes (Title); -- if necessary, separate title's leading and trailing quote marks from Module provided quote marks | Title = kern_quotes (Title); -- if necessary, separate title's leading and trailing quote marks from Module provided quote marks | ||
Title = wrap_style ('quoted-title', Title); | Title = wrap_style ('quoted-title', Title); | ||
Title = script_concatenate (Title, ScriptTitle); -- <bdi> tags, lang atribute, categorization, etc; must be done after title is wrapped | Title = script_concatenate (Title, ScriptTitle); -- <bdi> tags, lang atribute, categorization, etc; must be done after title is wrapped | ||
TransTitle= wrap_style ('trans-quoted-title', TransTitle ); | TransTitle= wrap_style ('trans-quoted-title', TransTitle ); | ||
Line 2,822: | Line 2,852: | ||
if is_set (Translators) then | if is_set (Translators) then | ||
Others = sepc .. ' ' .. wrap_msg ('translated', Translators, use_lowercase) .. Others; | Others = sepc .. ' ' .. wrap_msg ('translated', Translators, use_lowercase) .. Others; | ||
end | end | ||
Line 2,908: | Line 2,937: | ||
local arch_text = cfg.messages['archived-dead']; | local arch_text = cfg.messages['archived-dead']; | ||
if sepc ~= "." then arch_text = arch_text:lower() end | if sepc ~= "." then arch_text = arch_text:lower() end | ||
if in_array (DeadURL, {'unfit', 'usurped'}) then | if in_array (DeadURL, {'unfit', 'usurped', 'bot: unknown'}) then | ||
Archived = sepc .. " " .. 'Archived from the original on ' .. ArchiveDate; -- format already styled | Archived = sepc .. " " .. 'Archived from the original on ' .. ArchiveDate; -- format already styled | ||
if 'bot: unknown' == DeadURL then | |||
add_maint_cat ('bot:_unknown'); -- and add a category if not already added | |||
else | |||
add_maint_cat ('unfit'); -- and add a category if not already added | |||
end | |||
else -- DeadURL is empty, 'yes', 'true', or 'y' | else -- DeadURL is empty, 'yes', 'true', or 'y' | ||
Archived = sepc .. " " .. substitute( arch_text, | Archived = sepc .. " " .. substitute( arch_text, | ||
Line 2,953: | Line 2,987: | ||
local Publisher; | local Publisher; | ||
if is_set( | if is_set(PublicationDate) then | ||
PublicationDate = wrap_msg ('published', PublicationDate); | |||
end | |||
if is_set(PublisherName) then | |||
if is_set(PublicationPlace) then | |||
Publisher = sepc .. " " .. PublicationPlace .. ": " .. PublisherName .. PublicationDate; | |||
else | |||
Publisher = sepc .. " " .. PublisherName .. PublicationDate; | |||
end | |||
elseif is_set(PublicationPlace) then | |||
Publisher= sepc .. " " .. PublicationPlace .. PublicationDate; | |||
else | |||
Publisher = PublicationDate; | |||
if is_set( | |||
end | end | ||
Line 3,232: | Line 3,241: | ||
function cs1.citation(frame) | function cs1.citation(frame) | ||
Frame = frame; -- save a copy incase we need to display an error message in preview mode | |||
local pframe = frame:getParent() | local pframe = frame:getParent() | ||
local validation, utilities, identifiers, metadata; | local validation, utilities, identifiers, metadata; | ||
Line 3,283: | Line 3,293: | ||
COinS = metadata.COinS; | COinS = metadata.COinS; | ||
local args = {}; | local args = {}; | ||
local suggestions = {}; | local suggestions = {}; |