Module:Citation/CS1: Difference between revisions
sync to sandbox, very large update addressing configuration, error handling, id handling, and others
m>Dragons flight (sync to sandbox, fixes COinS author list) |
m>Dragons flight (sync to sandbox, very large update addressing configuration, error handling, id handling, and others) |
||
Line 4: | Line 4: | ||
} | } | ||
-- Include translation message hooks, ID and error handling configuration settings. | |||
local cfg = mw.loadData( 'Module:Citation/CS1/Configuration' ); | |||
-- Contains a list of all recognized parameters | |||
local whitelist = mw.loadData( 'Module:Citation/CS1/Whitelist' ); | local whitelist = mw.loadData( 'Module:Citation/CS1/Whitelist' ); | ||
Line 25: | Line 29: | ||
end | end | ||
-- Formats a | -- Formats a comment for error trapping | ||
function | function errorcomment( content, hidden ) | ||
return '<span style="display: none;" class="citation-comment">' .. content .. '</span>'; | if hidden then | ||
return '<span style="display:none;font-size:100%" class="error citation-comment">' .. content .. '</span>'; | |||
else | |||
return '<span style="font-size:100%" class="error">' .. content .. '</span>'; | |||
end | |||
end | |||
--[[ | |||
Sets an error condition and returns the appropriate error message. The actual placement | |||
of the error message in the output is the responsibility of the calling function. | |||
]] | |||
function seterror( error_id, args, raw ) | |||
local error_state = cfg.error_conditions[ error_id ]; | |||
if error_state == nil then | |||
error( cfg.message_list['undefined_error'] ); | |||
end | |||
if error_state.category ~= nil and error_state.category ~= "" then | |||
table.insert( z.error_categories, error_state.category ); | |||
end | |||
local message = error_state.message; | |||
if args ~= nil then | |||
for k, m in ipairs( args ) do | |||
message = message:gsub( "$" .. k .. "(%D)", m .. "%1" ); | |||
end | |||
end | |||
message = wikiescape(message) .. " ([[" .. cfg.message_list['help page link'] .. | |||
"#" .. error_state.anchor .. "|" .. | |||
cfg.message_list['help page label'] .. "]])"; | |||
if raw == true then | |||
return message, error_state.hidden; | |||
end | |||
return errorcomment( message, error_state.hidden ); | |||
end | end | ||
Line 41: | Line 82: | ||
['}'] = '}' } ); | ['}'] = '}' } ); | ||
return text; | return text; | ||
end | end | ||
Line 104: | Line 94: | ||
return "[[" .. options.link .. "|" .. options.label .. "]]" .. sep .. "[" .. | return "[[" .. options.link .. "|" .. options.label .. "]]" .. sep .. "[" .. | ||
options.prefix .. url_string .. options.suffix .. " " .. nowiki(options.id) .. "]" | options.prefix .. url_string .. options.suffix .. " " .. mw.text.nowiki(options.id) .. "]" | ||
end | end | ||
Line 112: | Line 102: | ||
options.suffix = options.suffix or "" | options.suffix = options.suffix or "" | ||
return "[[" .. options.link .. "|" .. options.label .. "]]" .. sep .. "[[" .. | return "[[" .. options.link .. "|" .. options.label .. "]]" .. sep .. "[[" .. | ||
options.prefix .. options.id .. options.suffix .. "|" .. nowiki(options.id) .. "]]" | options.prefix .. options.id .. options.suffix .. "|" .. mw.text.nowiki(options.id) .. "]]" | ||
end | end | ||
Line 122: | Line 112: | ||
domain = "co." .. domain | domain = "co." .. domain | ||
end | end | ||
return externallinkid({link= | local handler = cfg.id_handlers['ASIN']; | ||
label= | return externallinkid({link = handler.link, | ||
label=handler.label , prefix="//www.amazon."..domain.."/dp/",id=id, | |||
encode=handler.encode, separator = handler.separator}) | |||
end | end | ||
Line 129: | Line 121: | ||
function doi(id, inactive) | function doi(id, inactive) | ||
local cat = "" | local cat = "" | ||
local handler = cfg.id_handlers['DOI']; | |||
local text; | local text; | ||
if ( inactive ~= nil ) then | if ( inactive ~= nil ) then | ||
text = "[[ | text = "[[" .. handler.link .. "|" .. handler.label .. "]]:" .. id; | ||
table.insert( z.error_categories, "Pages with DOIs inactive since " .. selectyear(inactive) ); | table.insert( z.error_categories, "Pages with DOIs inactive since " .. selectyear(inactive) ); | ||
inactive = " (inactive " .. inactive .. ")" | inactive = " (" .. cfg.message_list['inactive'] .. " " .. inactive .. ")" | ||
else | else | ||
text = externallinkid({link= | text = externallinkid({link = handler.link, label = handler.label, | ||
prefix= | prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode}) | ||
inactive = "" | inactive = "" | ||
end | end | ||
if ( string.sub(id,1,3) ~= "10." ) then | if ( string.sub(id,1,3) ~= "10." ) then | ||
cat = seterror( 'bad_doi' ); | |||
cat = ' | |||
end | end | ||
return text .. inactive .. cat | return text .. inactive .. cat | ||
end | end | ||
-- Formats an OpenLibrary link, and checks for associated errors. | |||
function openlibrary(id) | |||
local code = id:sub(-1,-1) | |||
local handler = cfg.id_handlers['OL']; | |||
if ( code == "A" ) then | |||
return externallinkid({link=handler.link, label=handler.label, | |||
prefix="http://openlibrary.org/authors/OL",id=id, separator=handler.separator, | |||
encode = handler.encode}) | |||
elseif ( code == "M" ) then | |||
return externallinkid({link=handler.link, label=handler.label, | |||
prefix="http://openlibrary.org/books/OL",id=id, separator=handler.separator, | |||
encode = handler.encode}) | |||
elseif ( code == "W" ) then | |||
return externallinkid({link=handler.link, label=handler.label, | |||
prefix= "http://openlibrary.org/works/OL",id=id, separator=handler.separator, | |||
encode = handler.encode}) | |||
else | |||
return externallinkid({link=handler.link, label=handler.label, | |||
prefix= "http://openlibrary.org/OL",id=id, separator=handler.separator, | |||
encode = handler.encode}) .. | |||
' ' .. seterror( 'bad_ol' ); | |||
end | |||
end | |||
-- Determines whether an ISBN string is valid | |||
function checkisbn( isbn_str ) | |||
isbn_str = isbn_str:gsub("[- ]", ""):upper(); | |||
local len = isbn_str:len(); | |||
if len ~= 10 and len ~= 13 then | |||
return false; | |||
end | |||
local temp = 0; | |||
if len == 10 then | |||
if isbn_str:match( "^%d*X?$" ) == nil then return false; end | |||
isbn_str = { isbn_str:byte(1, len) }; | |||
for i, v in ipairs( isbn_str ) do | |||
if v == string.byte( "X" ) then | |||
temp = temp + 10*( 11 - i ); | |||
else | |||
temp = temp + tonumber( string.char(v) )*(11-i); | |||
end | |||
end | |||
return temp % 11 == 0; | |||
else | |||
if isbn_str:match( "^%d*$" ) == nil then return false; end | |||
isbn_str = { isbn_str:byte(1, len) }; | |||
for i, v in ipairs( isbn_str ) do | |||
temp = temp + (3 - 2*(i % 2)) * tonumber( string.char(v) ); | |||
end | |||
return temp % 10 == 0; | |||
end | |||
end | |||
-- Escape sequences for content that will be used for URL descriptions | -- Escape sequences for content that will be used for URL descriptions | ||
function safeforurl( str ) | function safeforurl( str ) | ||
if str:match( "%[%[.-%]%]" ) ~= nil then | if str:match( "%[%[.-%]%]" ) ~= nil then | ||
table.insert( z. | table.insert( z.message_tail, { seterror( 'wikilink_in_url', {}, true ) } ); | ||
end | end | ||
Line 281: | Line 327: | ||
return ""; | return ""; | ||
end | end | ||
end | end | ||
end | end | ||
Line 356: | Line 382: | ||
local result = table.concat(text, sep) -- construct list | local result = table.concat(text, sep) -- construct list | ||
if etal then | if etal then | ||
local etal_text = | local etal_text = cfg.message_list['et al']; | ||
result = result .. " " .. etal_text; | result = result .. " " .. etal_text; | ||
end | end | ||
-- if necessary wrap result in <span> tag to format in Small Caps | -- if necessary wrap result in <span> tag to format in Small Caps | ||
if ( "scap" == format ) then result= | if ( "scap" == format ) then result = | ||
'<span class="smallcaps" style="font-variant:small-caps">' .. result .. '</span>'; | |||
end | |||
return result, count | return result, count | ||
end | end | ||
Line 389: | Line 415: | ||
local i = 1; | local i = 1; | ||
local last; | local last; | ||
while true do | while true do | ||
last = args | if i == 1 then | ||
last = selectone( args, {"author" .. i .. "-last", "author-last" .. i, | |||
"last" .. i, "surname" .. i, "Author" .. i, "author" .. i, | |||
"author-last", "last", "surname", "Author", "author", "authors"}, 'redundant_parameters' ); | |||
else | |||
last = selectone( args, {"author" .. i .. "-last", "author-last" .. i, | |||
"last" .. i, "surname" .. i, "Author" .. i, "author" .. i}, 'redundant_parameters' ); | |||
end | |||
if ( last and "" < last ) then -- just in case someone passed in an empty parameter | if ( last and "" < last ) then -- just in case someone passed in an empty parameter | ||
authors[i] = { | if i == 1 then | ||
authors[i] = { | |||
last = last, | |||
first = selectone( args, {"author" .. i .. "-first", "author-first" .. i, | |||
"first" .. i, "given" .. i, "author-first", | |||
"first", "given"}, 'redundant_parameters' ), | |||
link = selectone( args, {"author" .. i .. "-link", "author-link" .. i, | |||
"author" .. i .. "link", "authorlink" .. i, "author-link", | |||
"authorlink"}, 'redundant_parameters' ), | |||
mask = selectone( args, {"author" .. i .. "-mask", "author-mask" .. i, | |||
"author" .. i .. "mask", "authormask" .. i, "author-mask", | |||
"authormask" }, 'redundant_parameters' ) | |||
} | |||
else | |||
authors[i] = { | |||
last = last, | |||
first = selectone( args, {"author" .. i .. "-first", "author-first" .. i, | |||
"first" .. i, "given" .. i}, 'redundant_parameters' ), | |||
link = selectone( args, {"author" .. i .. "-link", "author-link" .. i, | |||
"author" .. i .. "link", "authorlink" .. i}, 'redundant_parameters' ), | |||
mask = selectone( args, {"author" .. i .. "-mask", "author-mask" .. i, | |||
"author" .. i .. "mask", "authormask" .. i}, 'redundant_parameters' ) | |||
} | |||
end | |||
else | else | ||
break; | break; | ||
Line 418: | Line 464: | ||
while true do | while true do | ||
last = args | if i == 1 then | ||
last = selectone( args, {"editor" .. i .. "-last", "editor-last" .. i, | |||
"EditorSurname" .. i, "Editor" .. i, "editor" .. i, "editor-last", | |||
"EditorSurname", "Editor", "editor", "editors"}, 'redundant_parameters' ); | |||
else | |||
last = selectone( args, {"editor" .. i .. "-last", "editor-last" .. i, | |||
"EditorSurname" .. i, "Editor" .. i, "editor" .. i}, 'redundant_parameters' ); | |||
end | |||
if ( last and "" < last ) then -- just in case someone passed in an empty parameter | if ( last and "" < last ) then -- just in case someone passed in an empty parameter | ||
editors[i] = { | if i == 1 then | ||
editors[i] = { | |||
last = last, | |||
first = selectone( args, {"editor" .. i .. "-first", | |||
"editor-first" .. i, "EditorGiven" .. i, "editor-first", | |||
"EditorGiven"}, 'redundant_parameters' ), | |||
link = selectone( args, {"editor" .. i .. "-link", "editor-link" .. i, | |||
"editor" .. i .. "link", "editorlink" .. i, "editor-link", | |||
"editorlink"}, 'redundant_parameters' ), | |||
mask = selectone( args, {"editor" .. i .. "-mask", "editor-mask" .. i, | |||
"editor" .. i .. "mask", "editormask" .. i, "editor-mask", | |||
"editormask"}, 'redundant_parameters' ) | |||
} | |||
else | |||
editors[i] = { | |||
last = last, | |||
first = selectone( args, {"editor" .. i .. "-first", | |||
"editor-first" .. i, "EditorGiven" .. i}, 'redundant_parameters' ), | |||
link = selectone( args, {"editor" .. i .. "-link", "editor-link" .. i, | |||
"editor" .. i .. "link", "editorlink" .. i}, 'redundant_parameters' ), | |||
mask = selectone( args, {"editor" .. i .. "-mask", "editor-mask" .. i, | |||
"editor" .. i .. "mask", "editormask" .. i}, 'redundant_parameters' ) | |||
} | |||
end | |||
else | else | ||
break; | break; | ||
Line 435: | Line 503: | ||
end | end | ||
return editors; | return editors; | ||
end | |||
-- Populates ID table from arguments using configuration settings | |||
function extractids( args ) | |||
local id_list = {}; | |||
for k, v in pairs( cfg.id_handlers ) do | |||
id_list[k] = selectone( args, v.parameters, 'redundant_parameters' ); | |||
end | |||
return id_list; | |||
end | |||
-- Takes a table of IDs and turns it into a table of formatted ID outputs. | |||
function buildidlist( id_list, options ) | |||
local handler; | |||
local new_list = {}; | |||
for k, v in pairs( id_list ) do | |||
handler = {}; | |||
--Becasue cfg is read-only we have to copy it the hard way. | |||
for k2, v2 in pairs( cfg.id_handlers[k] ) do | |||
handler[k2] = v2; | |||
end | |||
handler['id'] = v; | |||
if handler.mode == 'external' then | |||
table.insert( new_list, {handler.label, externallinkid( handler ) } ); | |||
elseif handler.mode == 'internal' then | |||
table.insert( new_list, {handler.label, internallinkid( handler ) } ); | |||
elseif handler.mode == 'manual' then | |||
if k == 'DOI' then | |||
table.insert( new_list, {handler.label, doi( v, options.DoiBroken ) } ); | |||
elseif k == 'ASIN' then | |||
table.insert( new_list, {handler.label, amazon( v, options.ASINTLD ) } ); | |||
elseif k == 'OL' then | |||
table.insert( new_list, {handler.label, openlibrary( v ) } ); | |||
elseif k == 'ISBN' then | |||
local ISBN = internallinkid( handler ); | |||
if not checkisbn( v ) then | |||
ISBN = ISBN .. seterror( 'bad_isbn' ); | |||
end | |||
table.insert( new_list, {handler.label, ISBN } ); | |||
else | |||
error( cfg.message_list['unknown_manual_ID'] ); | |||
end | |||
else | |||
error( cfg.message_list['unknown_ID_mode'] ); | |||
end | |||
end | |||
function comp( a, b ) | |||
return a[1] < b[1]; | |||
end | |||
table.sort( new_list, comp ); | |||
for k, v in ipairs( new_list ) do | |||
new_list[k] = v[2]; | |||
end | |||
return new_list; | |||
end | |||
-- Chooses one matching parameter from a list of parameters to consider | |||
-- Generates an error if more than one match is present. | |||
function selectone( args, possible, error_condition ) | |||
local value = nil; | |||
local selected = ''; | |||
local error_list = {}; | |||
for _, v in ipairs( possible ) do | |||
if args[v] ~= nil then | |||
if value ~= nil then | |||
table.insert( error_list, v ); | |||
else | |||
value = args[v]; | |||
selected = v; | |||
end | |||
end | |||
end | |||
if #error_list > 0 then | |||
local error_str = ""; | |||
for _, k in ipairs( error_list ) do | |||
if error_str ~= "" then error_str = error_str .. ", " end | |||
error_str = error_str .. "<code>|" .. k .. "=</code>"; | |||
end | |||
if #error_list > 1 then | |||
error_str = error_str .. ", and "; | |||
else | |||
error_str = error_str .. " and "; | |||
end | |||
error_str = error_str .. "<code>|" .. selected .. "=</code>"; | |||
table.insert( z.message_tail, { seterror( error_condition, {error_str}, true ) } ); | |||
end | |||
return value, selected; | |||
end | end | ||
Line 444: | Line 610: | ||
-- Load Input Parameters | -- Load Input Parameters | ||
local i | |||
local PPrefix = config.PPrefix or "p. " | local PPrefix = config.PPrefix or "p. " | ||
local PPPrefix = config.PPPrefix or "pp. " | local PPPrefix = config.PPPrefix or "pp. " | ||
if ( nil ~= args.nopp ) then PPPrefix = "" PPrefix = "" end | if ( nil ~= args.nopp ) then PPPrefix = "" PPrefix = "" end | ||
-- Pick out the relevant fields from the arguments. Different citation templates | -- Pick out the relevant fields from the arguments. Different citation templates | ||
-- define different field names for the same underlying things. | -- define different field names for the same underlying things. | ||
local Authors = args.authors | local Authors = args.authors | ||
local a = extractauthors( args ); | local a = extractauthors( args ); | ||
local Coauthors = args.coauthors or args.coauthor | local Coauthors = args.coauthors or args.coauthor | ||
local Others = args.others | local Others = args.others | ||
local Editors = args.editors | local Editors = args.editors | ||
local e = extracteditors( args ); | local e = extracteditors( args ); | ||
Line 488: | Line 637: | ||
local TitleNote = args.department | local TitleNote = args.department | ||
local TitleLink = args.titlelink or args.episodelink | local TitleLink = args.titlelink or args.episodelink | ||
local Chapter = args | local Chapter = selectone( args, {'chapter', 'contribution', 'entry' }, 'redundant_parameters' ); | ||
local ChapterLink = args.chapterlink | local ChapterLink = args.chapterlink | ||
local TransChapter = args["trans-chapter"] or args.trans_chapter | local TransChapter = args["trans-chapter"] or args.trans_chapter | ||
Line 496: | Line 645: | ||
local ChapterURL = args["chapter-url"] or args.chapterurl or args["contribution-url"] | local ChapterURL = args["chapter-url"] or args.chapterurl or args["contribution-url"] | ||
local ConferenceURL = args["conference-url"] or args.conferenceurl | local ConferenceURL = args["conference-url"] or args.conferenceurl | ||
local Periodical = args | local Periodical = selectone( args, {'journal', 'newspaper', 'magazine', 'work', 'website', | ||
'periodical', 'encyclopedia', 'encyclopaedia'}, 'redundant_parameters' ); | |||
if ( config.CitationClass == "encyclopaedia" ) then | if ( config.CitationClass == "encyclopaedia" ) then | ||
Line 518: | Line 667: | ||
end | end | ||
end | end | ||
local Series = args | local Series = selectone( args, {'series', 'version'}, 'redundant_parameters' ); | ||
local Volume = args.volume | local Volume = args.volume | ||
local Issue = args | local Issue = selectone( args, {'issue', 'number'}, 'redundant_parameters' ); | ||
local Position = nil | local Position = nil | ||
local Page | local Page, Pages, At, page_type; | ||
Page, page_type = selectone( args, {'p', 'page', 'pp', 'pages', 'at'}, | |||
if | 'extra_pages' ); | ||
if page_type == 'pp' or page_type == 'pages' then | |||
Pages = hyphentodash( Page ); | |||
Page = nil; | |||
elseif page_type == 'at' then | |||
elseif | At = Page; | ||
Page = nil; | |||
end | end | ||
local Edition = args.edition | local Edition = args.edition | ||
local PublicationPlace = args["publication-place"] or args.publicationplace | local PublicationPlace = args["publication-place"] or args.publicationplace | ||
local Place = selectone( args, {'place', 'location'}, 'redundant_parameters' ); | |||
if PublicationPlace == nil and Place ~= nil then | |||
if PublicationPlace == Place then Place = nil | PublicationPlace = Place; | ||
end | |||
if PublicationPlace == Place then Place = nil end | |||
local PublisherName = args.publisher | local PublisherName = args.publisher | ||
Line 553: | Line 698: | ||
local Agency = args.agency | local Agency = args.agency | ||
local DeadURL = args.deadurl or "yes" -- Only used is ArchiveURL is present. | local DeadURL = args.deadurl or "yes" -- Only used is ArchiveURL is present. | ||
local Language = args | local Language = selectone( args, {'language', 'in'}, 'redundant_parameters' ); | ||
local Format = args.format | local Format = args.format | ||
local Ref = args.ref or args.Ref | local Ref = args.ref or args.Ref | ||
local | |||
local | local DoiBroken = args.doi_inactivedate or args.doi_brokendate or args.DoiBroken | ||
local ID = selectone( args, {'id', 'ID', 'docket'}, 'redundant_parameters' ); | |||
local ASINTLD = args["ASIN-TLD"] or args["asin-tld"] | local ASINTLD = args["ASIN-TLD"] or args["asin-tld"] | ||
local ID_list = extractids( args ); | |||
local Quote = selectone( args, {'quote', 'quotation'}, 'redundant_parameters' ); | |||
local | |||
local Quote = args | |||
local PostScript = args.postscript or "." | local PostScript = args.postscript or "." | ||
local LaySummary = args.laysummary | local LaySummary = args.laysummary | ||
Line 588: | Line 719: | ||
args.notracking or args["no-tracking"] or ""; | args.notracking or args["no-tracking"] or ""; | ||
if ( config.CitationClass == "journal" ) then | if ( config.CitationClass == "journal" ) then | ||
if (URL == nil or URL == "") then | if (URL == nil or URL == "") then | ||
if (ID_list['PMC'] ~= nil) then | |||
local Embargo = args.embargo or args.Embargo; | |||
if Embargo ~= nil then | |||
local lang = mw.getContentLanguage(); | |||
local good1, result1, good2, result2; | |||
good1, result1 = pcall( lang.formatDate, lang, 'U', Embargo ); | |||
good2, result2 = pcall( lang.formatDate, lang, 'U' ); | |||
if good1 and good2 and tonumber( result1 ) < tonumber( result2 ) then | |||
URL = "http://www.ncbi.nlm.nih.gov/pmc/articles/PMC" .. ID_list['PMC']; | |||
end | |||
else | |||
URL = "http://www.ncbi.nlm.nih.gov/pmc/articles/PMC" .. ID_list['PMC']; | |||
end | |||
end | |||
end | end | ||
end | end | ||
Line 617: | Line 759: | ||
local Station = args.station | local Station = args.station | ||
local s = {} | local s = {} | ||
if Issue ~= nil then table.insert(s, "episode " .. Issue) Issue = nil end | if Issue ~= nil then table.insert(s, cfg.message_list["episode"] .. " " .. Issue) Issue = nil end | ||
if Season ~= nil then table.insert(s, "season " .. Season) end | if Season ~= nil then table.insert(s, cfg.message_list["season"] .. " " .. Season) end | ||
if SeriesNumber ~= nil then table.insert(s, "series " .. SeriesNumber) end | if SeriesNumber ~= nil then table.insert(s, cfg.message_list["series"] .. " " .. SeriesNumber) end | ||
local n = {} | local n = {} | ||
if Network ~= nil then table.insert(n, Network) end | if Network ~= nil then table.insert(n, Network) end | ||
Line 663: | Line 805: | ||
OCinSdata["rft.edition"] = Edition | OCinSdata["rft.edition"] = Edition | ||
OCinSdata["rft.pub"] = PublisherName | OCinSdata["rft.pub"] = PublisherName | ||
for k, v in pairs( ID_list ) do | |||
if string.sub( cfg.id_handlers[k].COinS or "info", 1, 4 ) ~= 'info' then | |||
OCinSdata[ cfg.id_handlers[k].COinS ] = v; | |||
end | |||
end | |||
OCinSdata.rft_id = URL or ChapterURL | OCinSdata.rft_id = URL or ChapterURL | ||
Line 692: | Line 835: | ||
local OCinSids = {} -- COinS data only for id, bibcode, doi, pmid, etc. | local OCinSids = {} -- COinS data only for id, bibcode, doi, pmid, etc. | ||
for k, v in pairs( ID_list ) do | |||
if string.sub( cfg.id_handlers[k].COinS or "", 1, 4 ) == 'info' then | |||
OCinSids[ cfg.id_handlers[k].COinS ] = v; | |||
end | |||
end | |||
local OCinStitle = "ctx_ver=" .. ctx_ver -- such as "Z39.88-2004" | local OCinStitle = "ctx_ver=" .. ctx_ver -- such as "Z39.88-2004" | ||
for name,value in pairs(OCinSdata) do | for name,value in pairs(OCinSdata) do | ||
Line 716: | Line 853: | ||
local this_page = mw.title.getCurrentTitle(); | local this_page = mw.title.getCurrentTitle(); | ||
OCinStitle = OCinStitle .. "&rfr_id=info:sid/ | OCinStitle = OCinStitle .. "&rfr_id=info:sid/" .. mw.site.server:match( "[^/]*$" ) .. ":" | ||
.. this_page.prefixedText -- end COinS data by page's non-encoded pagename | .. this_page.prefixedText -- end COinS data by page's non-encoded pagename | ||
Line 739: | Line 876: | ||
if Maximum == nil and #a == 9 then | if Maximum == nil and #a == 9 then | ||
Maximum = 8; | Maximum = 8; | ||
table.insert( z. | table.insert( z.message_tail, { seterror('implict_etal_author', {}, true ) } ); | ||
elseif Maximum == nil then | elseif Maximum == nil then | ||
Maximum = #a + 1; | Maximum = #a + 1; | ||
Line 768: | Line 904: | ||
if Maximum == nil and #e == 4 then | if Maximum == nil and #e == 4 then | ||
Maximum = 3; | Maximum = 3; | ||
table.insert( z. | table.insert( z.message_tail, { seterror('implict_etal_editor', {}, true) } ); | ||
elseif Maximum == nil then | elseif Maximum == nil then | ||
Maximum = #e + 1; | Maximum = #e + 1; | ||
Line 834: | Line 969: | ||
-- Test if cite web is called without giving a URL | -- Test if cite web is called without giving a URL | ||
if ( config.CitationClass == "web" ) then | if ( config.CitationClass == "web" ) then | ||
table.insert( z. | table.insert( z.message_tail, { seterror( 'cite_web_url', {}, true ) } ); | ||
end | end | ||
-- Test if accessdate is given without giving a URL | -- Test if accessdate is given without giving a URL | ||
if ( AccessDate ~= nil and AccessDate ~= '' ) then | if ( AccessDate ~= nil and AccessDate ~= '' ) then | ||
table.insert( z. | table.insert( z.message_tail, { seterror( 'accessdate_missing_url', {}, true ) } ); | ||
AccessDate = nil; | AccessDate = nil; | ||
end | end | ||
Line 847: | Line 980: | ||
-- Test if format is given without giving a URL | -- Test if format is given without giving a URL | ||
if ( Format ~= nil and Format ~= '' ) then | if ( Format ~= nil and Format ~= '' ) then | ||
Format = Format .. seterror( 'format_missing_url' ); | |||
Format = Format .. | |||
end | end | ||
end | end | ||
Line 859: | Line 991: | ||
( TransTitle == nil or TransTitle == "" ) and | ( TransTitle == nil or TransTitle == "" ) and | ||
( TransChapter == nil or TransChapter == "" ) then | ( TransChapter == nil or TransChapter == "" ) then | ||
table.insert( z. | table.insert( z.message_tail, { seterror( 'citation_missing_title', {}, true ) } ); | ||
end | end | ||
Line 890: | Line 1,021: | ||
end | end | ||
if TransChapter ~= "" and Chapter == "" then | if TransChapter ~= "" and Chapter == "" then | ||
TransChapter = TransChapter .. seterror( 'trans_missing_chapter' ); | |||
TransChapter = TransChapter .. | |||
end | end | ||
Chapter = Chapter .. TransChapter | Chapter = Chapter .. TransChapter | ||
Line 907: | Line 1,037: | ||
Format = "" | Format = "" | ||
end | end | ||
elseif ChapterURL ~= nil and ChapterURL ~= "" then | |||
Chapter = Chapter .. " [" .. ChapterURL .. " " .. safeforurl( ChapterURL ) .. "]" .. | |||
seterror( 'bare_url_missing_title' ); | |||
end | end | ||
Chapter = Chapter .. sepc .. " " -- with end-space | Chapter = Chapter .. sepc .. " " -- with end-space | ||
end | elseif ChapterURL ~= nil and ChapterURL ~= "" then | ||
Chapter = " [" .. ChapterURL .. " " .. safeforurl( ChapterURL ) .. "]" .. | |||
seterror( 'bare_url_missing_title' ) .. sepc .. " "; | |||
end | |||
-- Format main title. | -- Format main title. | ||
Line 929: | Line 1,065: | ||
end | end | ||
if TransTitle ~= "" and Title == "" then | if TransTitle ~= "" and Title == "" then | ||
TransTitle = TransTitle .. seterror( 'trans_missing_title' ); | |||
TransTitle = TransTitle .. | |||
end | end | ||
Title = Title .. TransTitle | Title = Title .. TransTitle | ||
Line 943: | Line 1,078: | ||
if ( Place ~= nil and Place ~= "" ) then | if ( Place ~= nil and Place ~= "" ) then | ||
if sepc == '.' then | if sepc == '.' then | ||
Place = " | Place = " " .. cfg.message_list['written'] .. " " .. Place .. sepc .. " "; | ||
else | else | ||
Place = " written | Place = " " .. cfg.message_list['written']:lower() .. " " .. Place .. sepc .. " "; | ||
end | end | ||
else | else | ||
Line 956: | Line 1,091: | ||
end | end | ||
Conference = " " .. Conference | Conference = " " .. Conference | ||
else | elseif ConferenceURL ~= nil and ConferenceURL ~= "" then | ||
Conference = " [" .. ConferenceURL .. " " .. safeforurl( ConferenceURL ) .. "]" .. | |||
seterror( 'bare_url_missing_title' ); | |||
else | |||
Conference = "" | Conference = "" | ||
end | end | ||
Line 963: | Line 1,101: | ||
local Minutes = args.minutes | local Minutes = args.minutes | ||
if ( nil ~= Minutes ) then | if ( nil ~= Minutes ) then | ||
Position = " " .. Minutes .. " minutes | Position = " " .. Minutes .. " " .. cfg.message_list['minutes']; | ||
else | else | ||
local Time = args.time | local Time = args.time | ||
if ( nil ~= Time ) then | if ( nil ~= Time ) then | ||
local TimeCaption = args.timecaption | local TimeCaption = args.timecaption | ||
if TimeCaption == nil then | |||
TimeCaption = cfg.message_list['event']; | |||
if sepc ~= '.' then | |||
TimeCaption = TimeCaption:lower(); | |||
end | |||
end | |||
Position = " " .. TimeCaption .. " " .. Time | Position = " " .. TimeCaption .. " " .. Time | ||
else | else | ||
Line 1,014: | Line 1,158: | ||
TitleNote = sepc .. " " .. TitleNote else TitleNote = "" end | TitleNote = sepc .. " " .. TitleNote else TitleNote = "" end | ||
if ( Language ~= nil and Language ~="" ) then | if ( Language ~= nil and Language ~="" ) then | ||
Language = " (in " .. Language .. ")" else Language = "" end | Language = " (" .. cfg.message_list['in'] .. " " .. Language .. ")" else Language = "" end | ||
if ( Edition ~= nil and Edition ~="" ) then | if ( Edition ~= nil and Edition ~="" ) then | ||
Edition = " (" .. Edition .. " | Edition = " (" .. Edition .. " " .. cfg.message_list['edition'] .. ")" else Edition = "" end | ||
if ( Volume ~= nil and Volume ~="" ) | if ( Volume ~= nil and Volume ~="" ) | ||
then | then | ||
Line 1,035: | Line 1,179: | ||
if ( Date ~= nil ) then Date = Date else Date = "" end | if ( Date ~= nil ) then Date = Date else Date = "" end | ||
if ( Via ~= nil and Via ~="" ) then | if ( Via ~= nil and Via ~="" ) then | ||
Via = " — via " .. Via else Via = "" end | Via = " — " .. cfg.message_list['via'] .. " " .. Via else Via = "" end | ||
if ( AccessDate ~= nil and AccessDate ~="" ) | if ( AccessDate ~= nil and AccessDate ~="" ) | ||
then local retrv_text = " retrieved " | then local retrv_text = " " .. cfg.message_list['retrieved'] .. " " | ||
if (sepc | if (sepc ~= ".") then retrv_text = retrv_text:lower() end | ||
AccessDate = '<span class="reference-accessdate">' .. sepc | AccessDate = '<span class="reference-accessdate">' .. sepc | ||
.. retrv_text .. AccessDate .. '</span>' | .. retrv_text .. AccessDate .. '</span>' | ||
Line 1,044: | Line 1,188: | ||
if ( SubscriptionRequired ~= nil and | if ( SubscriptionRequired ~= nil and | ||
SubscriptionRequired ~= "" ) then | SubscriptionRequired ~= "" ) then | ||
SubscriptionRequired = sepc .. " " .. | SubscriptionRequired = sepc .. " " .. cfg.message_list['subscription']; | ||
else | else | ||
SubscriptionRequired = "" | SubscriptionRequired = "" | ||
end | end | ||
if ( ID ~= nil and ID ~="") then ID = sepc .." ".. ID else ID="" end | if ( ID ~= nil and ID ~="") then ID = sepc .." ".. ID else ID="" end | ||
ID_list = buildidlist( ID_list, {DoiBroken = DoiBroken, ASINTLD = ASINTLD} ); | |||
if ( URL ~= nil and URL ~="") then | if ( URL ~= nil and URL ~="") then | ||
URL = " " .. "[" .. URL .. " " .. nowiki(URL) .. "]"; | URL = " " .. "[" .. URL .. " " .. mw.text.nowiki(URL) .. "]"; | ||
local error_text = seterror( 'bare_url_missing_title' ); | |||
if config.CitationClass == "web" then | if config.CitationClass == "web" then | ||
URL = URL .. " " .. seterror( 'cite_web_title' ); | |||
else | else | ||
URL = URL .. | URL = URL .. error_text; | ||
end | end | ||
else | else | ||
Line 1,132: | Line 1,225: | ||
ArchiveDate = " " .. ArchiveDate | ArchiveDate = " " .. ArchiveDate | ||
else | else | ||
ArchiveDate = " | ArchiveDate = " " .. seterror('archive_missing_date') .. " " | ||
end | end | ||
local arch_text = " archived | local arch_text = " " .. cfg.message_list['archived']; | ||
if (sepc | if (sepc ~= ".") then arch_text = arch_text:lower() end | ||
if ( "no" == DeadURL ) then | if ( "no" == DeadURL ) then | ||
Archived = sepc .. " [" .. ArchiveURL .. arch_text .. "] from | Archived = sepc .. " [" .. ArchiveURL .. arch_text .. "] " .. | ||
cfg.message_list['from'] .. " " .. cfg.message_list['original'] .. " " .. | |||
cfg.message_list['on'] .. ArchiveDate | |||
if OriginalURL == nil or OriginalUrl == '' then | if OriginalURL == nil or OriginalUrl == '' then | ||
Archived = Archived .. " " .. seterror('archive_missing_url_not_dead'); | |||
Archived = Archived .. " | |||
end | end | ||
else | else | ||
if OriginalURL ~= nil and OriginalURL ~= '' then | if OriginalURL ~= nil and OriginalURL ~= '' then | ||
Archived = sepc .. arch_text .. " from [" .. OriginalURL .. " | Archived = sepc .. arch_text .. " " .. cfg.message_list['from'] .. " [" .. OriginalURL .. " " .. | ||
cfg.message_list['original'] .. "] " .. cfg.message_list['on'] .. ArchiveDate | |||
else | else | ||
if config.CitationClass ~= 'web' then | if config.CitationClass ~= 'web' then | ||
Archived = sepc .. arch_text .. " from | Archived = sepc .. arch_text .. " " .. cfg.message_list['from'] .. " " .. | ||
seterror('archive_missing_url') .. " " .. cfg.message_list['on'] .. ArchiveDate | |||
else | else | ||
Archived = sepc .. arch_text .. " from | Archived = sepc .. arch_text .. " " .. cfg.message_list['from'] .. | ||
" " .. cfg.message_list['original'] .. " " .. | |||
cfg.message_list['on'] .. ArchiveDate | |||
end | end | ||
end | end | ||
Line 1,170: | Line 1,263: | ||
end | end | ||
if sepc == '.' then | if sepc == '.' then | ||
Lay = sepc .. " [" .. LaySummary .. " | Lay = sepc .. " [" .. LaySummary .. " " .. cfg.message_list['lay summary'] .. "]" .. LaySource .. LayDate | ||
else | else | ||
Lay = sepc .. " [" .. LaySummary .. " lay summary]" .. LaySource .. LayDate | Lay = sepc .. " [" .. LaySummary .. " " .. cfg.message_list['lay summary']:lower() .. "]" .. LaySource .. LayDate | ||
end | end | ||
else | else | ||
Line 1,179: | Line 1,272: | ||
if ( nil ~= Transcript and "" ~= Transcript ) then | if ( nil ~= Transcript and "" ~= Transcript ) then | ||
if ( TranscriptURL ~= nil ) then Transcript = "[" .. TranscriptURL .. Transcript .. "]" end | if ( TranscriptURL ~= nil ) then Transcript = "[" .. TranscriptURL .. Transcript .. "]" end | ||
elseif TranscriptURL ~= nil and TranscriptURL ~= "" then | |||
Transcript = "[" .. TranscriptURL .. " " .. safeforurl( TranscriptURL ) .. "]" .. | |||
seterror( 'bare_url_missing_title' ) | |||
else | else | ||
Transcript = "" | Transcript = "" | ||
Line 1,200: | Line 1,296: | ||
if ( PublicationDate and PublicationDate ~="" ) then | if ( PublicationDate and PublicationDate ~="" ) then | ||
if Publisher ~= '' then | if Publisher ~= '' then | ||
Publisher = Publisher .. ", published " .. PublicationDate; | Publisher = Publisher .. ", " .. cfg.message_list['published'] .. " " .. PublicationDate; | ||
else | else | ||
Publisher = PublicationDate; | Publisher = PublicationDate; | ||
Line 1,210: | Line 1,306: | ||
else | else | ||
if ( PublicationDate and PublicationDate ~="" ) then | if ( PublicationDate and PublicationDate ~="" ) then | ||
PublicationDate = " (published " .. PublicationDate .. ")" | PublicationDate = " (" .. cfg.message_list['published'] .. " " .. PublicationDate .. ")" | ||
else | else | ||
PublicationDate = "" | PublicationDate = "" | ||
Line 1,250: | Line 1,346: | ||
end | end | ||
if #ID_list > 0 then | |||
ID_list = safejoin( { sepc .. " ", table.concat( ID_list, sepc .. " " ), ID }, sepc ); | |||
else | |||
ID_list = ID; | |||
end | |||
local idcommon = safejoin( { ID_list, URL, Archived, AccessDate, Via, SubscriptionRequired, Lay, Quote }, sepc ); | |||
local text | local text | ||
local pgtext = Page .. Pages .. At | local pgtext = Page .. Pages .. At | ||
if ( "" ~= Authors ) then | if ( "" ~= Authors ) then | ||
Line 1,285: | Line 1,381: | ||
if ( "" ~= Date ) then | if ( "" ~= Date ) then | ||
if EditorCount <= 1 then | if EditorCount <= 1 then | ||
Editors = Editors .. ", | Editors = Editors .. ", " .. cfg.message_list['editor']; | ||
else | else | ||
Editors = Editors .. ", | Editors = Editors .. ", " .. cfg.message_list['editors']; | ||
end | end | ||
Date = " (" .. Date ..")" .. OrigYear .. sepc .. " " | Date = " (" .. Date ..")" .. OrigYear .. sepc .. " " | ||
else | else | ||
if EditorCount <= 1 then | if EditorCount <= 1 then | ||
Editors = Editors .. " ( | Editors = Editors .. " (" .. cfg.message_list['editor'] .. ")" .. sepc .. " " | ||
else | else | ||
Editors = Editors .. " ( | Editors = Editors .. " (" .. cfg.message_list['editors'] .. ")" .. sepc .. " " | ||
end | end | ||
end | end | ||
Line 1,335: | Line 1,431: | ||
if ( config.CitationClass ~= "citation" ) | if ( config.CitationClass ~= "citation" ) | ||
then classname = "citation " .. (config.CitationClass or "") end | then classname = "citation " .. (config.CitationClass or "") end | ||
local | local options = { class=classname } | ||
if ( Ref ~= nil ) then | if ( Ref ~= nil ) then | ||
local id = Ref | local id = Ref | ||
Line 1,358: | Line 1,454: | ||
id = anchorid(names) | id = anchorid(names) | ||
end | end | ||
options.id = id; | |||
end | end | ||
if string.len(text:gsub("<span[^>/]*>.-</span>", ""):gsub("%b<>","")) <= 2 then | if string.len(text:gsub("<span[^>/]*>.-</span>", ""):gsub("%b<>","")) <= 2 then | ||
z.error_categories = { | z.error_categories = {}; | ||
text = ' | text = seterror('empty_citation'); | ||
z.message_tail = {}; | z.message_tail = {}; | ||
end | end | ||
text = | if options.id ~= nil then | ||
text = '<span id="' .. wikiescape(options.id) ..'" class="' .. wikiescape(options.class) .. '">' .. text .. "</span>"; | |||
else | |||
text = '<span class="' .. wikiescape(options.class) .. '">' .. text .. "</span>"; | |||
end | |||
local empty_span = | local empty_span = '<span style="display: none;"> </span>'; | ||
-- Note: Using display: none on then COinS span breaks some clients. | -- Note: Using display: none on then COinS span breaks some clients. | ||
local OCinS = | local OCinS = '<span title="' .. wikiescape(OCinStitle) .. '" class="Z3988">' .. empty_span .. '</span>'; | ||
text = text .. OCinS; | text = text .. OCinS; | ||
if #z.message_tail ~= 0 then | if #z.message_tail ~= 0 then | ||
text = text .. | for i,v in ipairs( z.message_tail ) do | ||
if i == #z.message_tail then | |||
text = text .. errorcomment( v[1], v[2] ); | |||
else | |||
text = text .. errorcomment( v[1] .. "; ", v[2] ); | |||
end | |||
end | |||
end | end | ||
Line 1,393: | Line 1,499: | ||
local args = {}; | local args = {}; | ||
local suggestions = {}; | |||
local error_text, error_state; | |||
for k, v in pairs( pframe.args ) do | for k, v in pairs( pframe.args ) do | ||
if v ~= '' then | if v ~= '' then | ||
if not validate( k ) then | if not validate( k ) then | ||
if type( k ) ~= 'string' then | if type( k ) ~= 'string' then | ||
-- Exclude empty numbered parameters | -- Exclude empty numbered parameters | ||
if v:match("%S+") ~= nil then | if v:match("%S+") ~= nil then | ||
error_text, error_state = seterror( 'text_ignored', {v}, true ); | |||
end | end | ||
elseif validate( k:lower() ) then | elseif validate( k:lower() ) then | ||
error_text, error_state = seterror( 'parameter_ignored_suggest', {k, k:lower()}, true ); | |||
else | else | ||
if #suggestions == 0 then | |||
table.insert( z. | suggestions = mw.loadData( 'Module:Citation/CS1/Suggestions' ); | ||
end | end | ||
if suggestions[ k:lower() ] ~= nil then | |||
error_text, error_state = seterror( 'parameter_ignored_suggest', {k, suggestions[ k:lower() ]}, true ); | |||
else | |||
error_text, error_state = seterror( 'parameter_ignored', {k}, true ); | |||
end | |||
end | |||
if error_text ~= '' then | |||
table.insert( z.message_tail, {error_text, error_state} ); | |||
end | |||
end | end | ||
args[k] = v; | args[k] = v; |