Module:Citation/CS1: Difference between revisions
sync to sandbox, mostly code cleaning / organization. Also, ref = none, layurl as alias for laysummary, tweaks to COinS output, and changes to bareurl error.
m>Dragons flight (sync with sandbox, merge cite_web_title to bare_url, better style control on translations, category suppression by config, tweak display authors) |
m>Dragons flight (sync to sandbox, mostly code cleaning / organization. Also, ref = none, layurl as alias for laysummary, tweaks to COinS output, and changes to bareurl error.) |
||
Line 5: | Line 5: | ||
} | } | ||
-- Include translation message hooks, ID and error handling configuration settings. | |||
local | -- Note that require has tested to be significantly faster than loadData for this | ||
-- usage. This might be a side effect of the unnecessary cloning described | |||
-- in bugzilla 47300. | |||
local cfg = require( 'Module:Citation/CS1/Configuration/sandbox' ); | |||
-- Contains a list of all recognized parameters | -- Contains a list of all recognized parameters | ||
local whitelist = mw.loadData( 'Module:Citation/CS1/Whitelist' ); | local whitelist = mw.loadData( 'Module:Citation/CS1/Whitelist' ); | ||
-- | -- Whether variable is set or not | ||
-- | function is_set( var ) | ||
function | return not (var == nil or var == ''); | ||
if | end | ||
return | |||
-- First set variable or nil if none | |||
function first_set(...) | |||
local list = {...}; | |||
for _, var in pairs(list) do | |||
if is_set( var ) then | |||
return var; | |||
end | |||
end | |||
end | |||
-- Whether needle is in haystack | |||
function inArray( needle, haystack ) | |||
if needle == nil then | |||
return false; | |||
end | |||
for n,v in ipairs( haystack ) do | |||
if v == needle then | |||
return n; | |||
end | |||
end | end | ||
return false; | |||
end | |||
-- Populates numbered arguments in a message string using an argument table. | |||
function substitute( msg, args ) | |||
return args and tostring( mw.message.newRawMessage( msg, args ) ) or msg; | |||
end | end | ||
-- Wraps a string using a message_list configuration taking one argument | -- Wraps a string using a message_list configuration taking one argument | ||
function wrap( | function wrap( key, str ) | ||
if str | if not is_set( str ) then | ||
return ""; | return ""; | ||
elseif inArray( key, { 'italic-title', 'trans-italic-title' } ) then | |||
str = safeforitalics( str ); | str = safeforitalics( str ); | ||
end | end | ||
return substitute( cfg. | return substitute( cfg.messages[key], {str} ); | ||
end | end | ||
Line 48: | Line 63: | ||
]] | ]] | ||
function argument_wrapper( args ) | function argument_wrapper( args ) | ||
local origin = {}; | |||
local | |||
local | return setmetatable({ | ||
__index = function ( tbl, k ) | ORIGIN = function( self, k ) | ||
if | local dummy = self[k]; --force the variable to be loaded. | ||
return origin[k]; | |||
end | |||
}, | |||
{ | |||
__index = function ( tbl, k ) | |||
if origin[k] ~= nil then | |||
return nil; | return nil; | ||
end | end | ||
local list = cfg. | local args, list, v = args, cfg.aliases[k]; | ||
if list == nil then | if list == nil then | ||
error( cfg. | error( cfg.messages['unknown_argument_map'] ); | ||
elseif type( list ) == 'string' then | elseif type( list ) == 'string' then | ||
v = | v, origin[k] = args[list], list; | ||
else | else | ||
v = selectone( | v, origin[k] = selectone( args, list, 'redundant_parameters' ); | ||
' | if origin[k] == nil then | ||
origin[k] = ''; --Empty string, not nil; | |||
end | |||
end | end | ||
if v == nil then | if v == nil then | ||
v = cfg. | v = cfg.defaults[k] or ""; | ||
origin[k] = ''; --Empty string, not nil; | |||
end | end | ||
tbl = rawset( tbl, k, v ); | tbl = rawset( tbl, k, v ); | ||
return v; | return v; | ||
end, | end, | ||
} | }); | ||
end | end | ||
Line 100: | Line 122: | ||
-- Formats a comment for error trapping | -- Formats a comment for error trapping | ||
function errorcomment( content, hidden ) | function errorcomment( content, hidden ) | ||
return wrap( hidden and 'hidden-error' or 'visible-error', content ); | |||
end | end | ||
Line 113: | Line 131: | ||
function seterror( error_id, arguments, raw, prefix, suffix ) | function seterror( error_id, arguments, raw, prefix, suffix ) | ||
local error_state = cfg.error_conditions[ error_id ]; | local error_state = cfg.error_conditions[ error_id ]; | ||
prefix = prefix or ""; | prefix = prefix or ""; | ||
suffix = suffix or ""; | suffix = suffix or ""; | ||
if error_state == nil then | if error_state == nil then | ||
error( cfg. | error( cfg.messages['undefined_error'] ); | ||
elseif is_set( error_state.category ) then | |||
table.insert( z.error_categories, error_state.category ); | |||
end | end | ||
local message = substitute( error_state.message, arguments ); | |||
message = message .. " ([[" .. cfg.messages['help page link'] .. | |||
"#" .. error_state.anchor .. "|" .. | "#" .. error_state.anchor .. "|" .. | ||
cfg. | cfg.messages['help page label'] .. "]])"; | ||
z.error_ids[ error_id ] = true; | z.error_ids[ error_id ] = true; | ||
if (error_id | if inArray( error_id, { 'bare_url_missing_title', 'trans_missing_title' } ) | ||
and z.error_ids['citation_missing_title'] then | and z.error_ids['citation_missing_title'] then | ||
return '', false; | return '', false; | ||
end | end | ||
message = prefix | message = table.concat({ prefix, message, suffix }); | ||
if raw == true then | if raw == true then | ||
Line 144: | Line 160: | ||
return errorcomment( message, error_state.hidden ); | return errorcomment( message, error_state.hidden ); | ||
end | end | ||
-- Formats a wiki style external link | -- Formats a wiki style external link | ||
function externallinkid(options) | function externallinkid(options) | ||
local url_string = options.id; | |||
local url_string = options.id | |||
if options.encode == true or options.encode == nil then | if options.encode == true or options.encode == nil then | ||
url_string = mw.uri.encode( url_string ); | url_string = mw.uri.encode( url_string ); | ||
end | end | ||
return mw.ustring.format( '[[%s|%s]]%s[%s%s%s %s]', | |||
return | options.link, options.label, options.separator or " ", | ||
options.prefix, url_string, options.suffix or "", | |||
mw.text.nowiki(options.id) | |||
); | |||
end | end | ||
-- Formats a wiki style internal link | -- Formats a wiki style internal link | ||
function internallinkid(options) | function internallinkid(options) | ||
return mw.ustring.format( '[[%s|%s]]%s[[%s%s%s|%s]]', | |||
options.link, options.label, options.separator or " ", | |||
options.prefix, options.id, options.suffix or "", | |||
mw.text.nowiki(options.id) | |||
); | |||
end | end | ||
-- Format an external link with error checking | -- Format an external link with error checking | ||
function externallink( URL, label ) | function externallink( URL, label, source ) | ||
local error_str = ""; | local error_str = ""; | ||
if label | if not is_set( label ) then | ||
label = URL; | label = URL; | ||
error_str = seterror( 'bare_url_missing_title', {}, false, " " ); | if is_set( source ) then | ||
error_str = seterror( 'bare_url_missing_title', { wrap( 'parameter', source ) }, false, " " ); | |||
else | |||
error( cfg.messages["bare_url_no_origin"] ); | |||
end | |||
end | end | ||
if not checkurl( URL ) then | if not checkurl( URL ) then | ||
error_str = seterror( 'bad_url', {}, false, " " ) .. error_str; | error_str = seterror( 'bad_url', {}, false, " " ) .. error_str; | ||
end | end | ||
return table.concat({ "[", URL, " ", safeforurl( label ), "]", error_str }); | |||
return "[" | |||
end | end | ||
-- Formats a link to Amazon | -- Formats a link to Amazon | ||
function amazon(id, domain) | function amazon(id, domain) | ||
if ( | if not is_set(domain) then | ||
domain = "com" | domain = "com" | ||
elseif ( "jp" == domain or "uk" == domain ) then | elseif ( "jp" == domain or "uk" == domain ) then | ||
Line 213: | Line 220: | ||
local text; | local text; | ||
if ( inactive | if is_set(inactive) then | ||
text = "[[" .. handler.link .. "|" .. handler.label .. "]]:" .. id; | 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 = " (" .. cfg. | inactive = " (" .. cfg.messages['inactive'] .. " " .. inactive .. ")" | ||
else | else | ||
text = externallinkid({link = handler.link, label = handler.label, | text = externallinkid({link = handler.link, label = handler.label, | ||
Line 261: | Line 268: | ||
]] | ]] | ||
function checkurl( url_str ) | function checkurl( url_str ) | ||
-- Protocol-relative or URL scheme | |||
return url_str:sub(1,2) == "//" or url_str:match( "^[^/]*:" ) ~= nil; | |||
end | end | ||
Line 312: | Line 311: | ||
-- Gets the display text for a wikilink like [[A|B]] or [[B]] gives B | -- Gets the display text for a wikilink like [[A|B]] or [[B]] gives B | ||
function removewikilink( str ) | function removewikilink( str ) | ||
return (str:gsub( "%[%[([^%[%]]*)%]%]", function(l) | |||
return l:gsub( "^[^|]*|(.*)$", "%1" ):gsub("^%s*(.-)%s*$", "%1"); | |||
end)); | |||
end | end | ||
Line 324: | Line 323: | ||
return str:gsub( '[%[%]\n]', { | return str:gsub( '[%[%]\n]', { | ||
['['] = '[', | ['['] = '[', | ||
[']'] = ']', | [']'] = ']', | ||
['\n'] = ' ' } ); | ['\n'] = ' ' } ); | ||
end | end | ||
Line 331: | Line 330: | ||
-- Converts a hyphen to a dash | -- Converts a hyphen to a dash | ||
function hyphentodash( str ) | function hyphentodash( str ) | ||
if str | if not is_set(str) or str:match( "[%[%]{}<>]" ) ~= nil then | ||
return str; | return str; | ||
end | end | ||
Line 347: | Line 343: | ||
tend to interact poorly under Mediawiki's HTML tidy. ]] | tend to interact poorly under Mediawiki's HTML tidy. ]] | ||
if str | if not is_set(str) then | ||
return str; | return str; | ||
else | else | ||
Line 439: | Line 435: | ||
-- Is the input a simple number? | -- Is the input a simple number? | ||
local num = tonumber( str ); | local num = tonumber( str ); | ||
if num ~= nil and num > 0 and num < 2100 and num == math. | if num ~= nil and num > 0 and num < 2100 and num == math.floor(num) then | ||
return str; | return str; | ||
else | else | ||
Line 467: | Line 463: | ||
function listpeople(control, people) | function listpeople(control, people) | ||
local sep = control.sep; | local sep = control.sep; | ||
local namesep = control.namesep | local namesep = control.namesep | ||
local format = control.format | local format = control.format | ||
Line 474: | Line 469: | ||
local text = {} | local text = {} | ||
local etal = false; | local etal = false; | ||
if maximum < 1 then return "", 0; end | |||
if sep:sub(-1,-1) ~= " " then sep = sep .. " " end | |||
if maximum ~= nil and maximum < 1 then return "", 0; end | |||
for i,person in ipairs(people) do | for i,person in ipairs(people) do | ||
if (person.last | if is_set(person.last) then | ||
local mask = person.mask | local mask = person.mask | ||
local one | local one | ||
local sep_one = sep; | local sep_one = sep; | ||
if | if maximum ~= nil and i > maximum then | ||
etal = true; | etal = true; | ||
break; | break; | ||
Line 494: | Line 492: | ||
one = person.last | one = person.last | ||
local first = person.first | local first = person.first | ||
if (first | if is_set(first) then | ||
if ( "vanc" == format ) then first = reducetoinitials(first) end | if ( "vanc" == format ) then first = reducetoinitials(first) end | ||
one = one .. namesep .. first | one = one .. namesep .. first | ||
end | end | ||
if (person.link | if is_set(person.link) then one = "[[" .. person.link .. "|" .. one .. "]]" end | ||
end | end | ||
table.insert( text, one ) | table.insert( text, one ) | ||
Line 507: | Line 505: | ||
local count = #text / 2; | local count = #text / 2; | ||
if count > 0 then | if count > 0 then | ||
if count > 1 and lastauthoramp | if count > 1 and is_set(lastauthoramp) and not etal then | ||
text[#text-2] = " & "; | text[#text-2] = " & "; | ||
end | end | ||
Line 515: | Line 513: | ||
local result = table.concat(text) -- construct list | local result = table.concat(text) -- construct list | ||
if etal then | if etal then | ||
local etal_text = cfg. | local etal_text = cfg.messages['et al']; | ||
result = result .. " " .. etal_text; | result = result .. " " .. etal_text; | ||
end | end | ||
Line 528: | Line 526: | ||
-- Generates a CITEREF anchor ID. | -- Generates a CITEREF anchor ID. | ||
function anchorid( options ) | function anchorid( options ) | ||
return "CITEREF" .. | return "CITEREF" .. table.concat( options ); | ||
end | end | ||
Line 538: | Line 536: | ||
while true do | while true do | ||
last = selectone( args, cfg. | last = selectone( args, cfg.aliases[list_name .. '-Last'], 'redundant_parameters', i ); | ||
if ( | if not is_set(last) then | ||
-- just in case someone passed in an empty parameter | |||
break; | break; | ||
end | end | ||
names[i] = { | |||
last = last, | |||
first = selectone( args, cfg.aliases[list_name .. '-First'], 'redundant_parameters', i ), | |||
link = selectone( args, cfg.aliases[list_name .. '-Link'], 'redundant_parameters', i ), | |||
mask = selectone( args, cfg.aliases[list_name .. '-Mask'], 'redundant_parameters', i ) | |||
}; | |||
i = i + 1; | i = i + 1; | ||
end | end | ||
Line 557: | Line 555: | ||
function extractids( args ) | function extractids( args ) | ||
local id_list = {}; | local id_list = {}; | ||
for k, v in pairs( cfg.id_handlers ) do | for k, v in pairs( cfg.id_handlers ) do | ||
v = selectone( args, v.parameters, 'redundant_parameters' ); | |||
if is_set(v) then id_list[k] = v; end | |||
end | end | ||
return id_list; | return id_list; | ||
end | end | ||
Line 567: | Line 564: | ||
-- Takes a table of IDs and turns it into a table of formatted ID outputs. | -- Takes a table of IDs and turns it into a table of formatted ID outputs. | ||
function buildidlist( id_list, options ) | function buildidlist( id_list, options ) | ||
local handler; | local new_list, handler = {}; | ||
function fallback(k) return { __index = function(t,i) return cfg.id_handlers[k][i] end } end; | |||
for k, v in pairs( id_list ) do | for k, v in pairs( id_list ) do | ||
-- fallback to read-only cfg | |||
handler = setmetatable( { ['id'] = v }, fallback(k) ); | |||
-- | |||
if handler.mode == 'external' then | if handler.mode == 'external' then | ||
table.insert( new_list, {handler.label, externallinkid( handler ) } ); | table.insert( new_list, {handler.label, externallinkid( handler ) } ); | ||
elseif handler.mode == 'internal' then | elseif handler.mode == 'internal' then | ||
table.insert( new_list, {handler.label, internallinkid( handler ) } ); | table.insert( new_list, {handler.label, internallinkid( handler ) } ); | ||
elseif handler.mode | elseif handler.mode ~= 'manual' then | ||
error( cfg.messages['unknown_ID_mode'] ); | |||
elseif 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 ) and not is_set(options.IgnoreISBN) then | |||
ISBN = ISBN .. seterror( 'bad_isbn', {}, false, " ", "" ); | |||
end | |||
table.insert( new_list, {handler.label, ISBN } ); | |||
else | else | ||
error( cfg. | error( cfg.messages['unknown_manual_ID'] ); | ||
end | end | ||
end | end | ||
function comp( a, b ) | function comp( a, b ) | ||
return a[1] < b[1]; | return a[1] < b[1]; | ||
end | end | ||
table.sort( new_list, comp ); | table.sort( new_list, comp ); | ||
for k, v in ipairs( new_list ) do | for k, v in ipairs( new_list ) do | ||
Line 622: | Line 613: | ||
local selected = ''; | local selected = ''; | ||
local error_list = {}; | local error_list = {}; | ||
if index ~= nil then index = tostring(index); end | if index ~= nil then index = tostring(index); end | ||
Line 628: | Line 620: | ||
for _, v in ipairs( possible ) do | for _, v in ipairs( possible ) do | ||
v = v:gsub( "#", "" ); | v = v:gsub( "#", "" ); | ||
if args[v] | if is_set(args[v]) then | ||
if value ~= nil and selected ~= v then | if value ~= nil and selected ~= v then | ||
table.insert( error_list, v ); | table.insert( error_list, v ); | ||
Line 638: | Line 630: | ||
end | end | ||
end | end | ||
for _, v in ipairs( possible ) do | for _, v in ipairs( possible ) do | ||
if index ~= nil then | if index ~= nil then | ||
v = v:gsub( "#", index ); | v = v:gsub( "#", index ); | ||
end | end | ||
if args[v] | if is_set(args[v]) then | ||
if value ~= nil then | if value ~= nil and selected ~= v then | ||
table.insert( error_list, v ); | table.insert( error_list, v ); | ||
else | else | ||
Line 652: | Line 644: | ||
end | end | ||
end | end | ||
if #error_list > 0 then | if #error_list > 0 then | ||
local error_str = ""; | local error_str = ""; | ||
for _, k in ipairs( error_list ) do | for _, k in ipairs( error_list ) do | ||
if error_str ~= "" then error_str = error_str .. | if error_str ~= "" then error_str = error_str .. cfg.messages['parameter-separator'] end | ||
error_str = error_str .. | error_str = error_str .. wrap( 'parameter', k ); | ||
end | end | ||
if #error_list > 1 then | if #error_list > 1 then | ||
error_str = error_str .. | error_str = error_str .. cfg.messages['parameter-final-separator']; | ||
else | else | ||
error_str = error_str .. | error_str = error_str .. cfg.messages['parameter-pair-separator']; | ||
end | end | ||
error_str = error_str .. | error_str = error_str .. wrap( 'parameter', selected ); | ||
table.insert( z.message_tail, { seterror( error_condition, {error_str}, true ) } ); | table.insert( z.message_tail, { seterror( error_condition, {error_str}, true ) } ); | ||
end | end | ||
return value, selected; | return value, selected; | ||
end | |||
-- COinS metadata (see <http://ocoins.info/>) allows automated tools to parse | |||
-- the citation information. | |||
function COinS(data) | |||
if 'table' ~= type(data) or nil == next(data) then | |||
return ''; | |||
end | |||
local ctx_ver = "Z39.88-2004"; | |||
-- treat table strictly as an array with only set values. | |||
local OCinSoutput = setmetatable( {}, { | |||
__newindex = function(self, key, value) | |||
if is_set(value) then | |||
rawset( self, #self+1, table.concat{ key, '=', mw.uri.encode( removewikilink( value ) ) } ); | |||
end | |||
end | |||
}); | |||
if is_set(data.Chapter) then | |||
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:book"; | |||
OCinSoutput["rft.genre"] = "bookitem"; | |||
OCinSoutput["rft.btitle"] = data.Chapter; | |||
OCinSoutput["rft.atitle"] = data.Title; | |||
elseif is_set(data.Periodical) then | |||
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:journal"; | |||
OCinSoutput["rft.genre"] = "article"; | |||
OCinSoutput["rft.jtitle"] = data.Periodical; | |||
OCinSoutput["rft.atitle"] = data.Title; | |||
else | |||
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:book"; | |||
OCinSoutput["rft.genre"] = "book" | |||
OCinSoutput["rft.btitle"] = data.Title; | |||
end | |||
OCinSoutput["rft.place"] = data.PublicationPlace; | |||
OCinSoutput["rft.date"] = data.Date; | |||
OCinSoutput["rft.series"] = data.Series; | |||
OCinSoutput["rft.volume"] = data.Volume; | |||
OCinSoutput["rft.issue"] = data.Issue; | |||
OCinSoutput["rft.pages"] = data.Pages; | |||
OCinSoutput["rft.edition"] = data.Edition; | |||
OCinSoutput["rft.pub"] = data.PublisherName; | |||
for k, v in pairs( data.ID_list ) do | |||
local id, value = cfg.id_handlers[k].COinS; | |||
if k == 'ISBN' then value = cleanisbn( v ); else value = v; end | |||
if string.sub( id or "", 1, 4 ) == 'info' then | |||
OCinSoutput["rft_id"] = table.concat{ id, "/", v }; | |||
else | |||
OCinSoutput[ id ] = value; | |||
end | |||
end | |||
local last, first; | |||
for k, v in ipairs( data.Authors ) do | |||
last, first = v.last, v.first; | |||
if k == 1 then | |||
if is_set(last) then | |||
OCinSoutput["rft.aulast"] = last; | |||
end | |||
if is_set(first) then | |||
OCinSoutput["rft.aufirst"] = first; | |||
end | |||
end | |||
if is_set(last) and is_set(first) then | |||
OCinSoutput["rft.au"] = table.concat{ last, ", ", first }; | |||
elseif is_set(last) then | |||
OCinSoutput["rft.au"] = last; | |||
end | |||
end | |||
OCinSoutput.rft_id = data.URL; | |||
OCinSoutput.rfr_id = table.concat{ "info:sid/", mw.site.server:match( "[^/]*$" ), ":", data.RawPage }; | |||
OCinSoutput = setmetatable( OCinSoutput, nil ); | |||
-- sort with version string always first, and combine. | |||
table.sort( OCinSoutput ); | |||
table.insert( OCinSoutput, 1, "ctx_ver=" .. ctx_ver ); -- such as "Z39.88-2004" | |||
return table.concat(OCinSoutput, "&"); | |||
end | end | ||
Line 686: | Line 759: | ||
local PPrefix = A['PPrefix'] | local PPrefix = A['PPrefix'] | ||
local PPPrefix = A['PPPrefix'] | local PPPrefix = A['PPPrefix'] | ||
if ( | if is_set( A['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 | ||
Line 715: | Line 788: | ||
local TitleType = A['TitleType']; | local TitleType = A['TitleType']; | ||
local ArchiveURL = A['ArchiveURL']; | local ArchiveURL = A['ArchiveURL']; | ||
local URL = A['URL']; | local URL = A['URL'] | ||
local URLorigin = A:ORIGIN('URL'); | |||
local ChapterURL = A['ChapterURL']; | local ChapterURL = A['ChapterURL']; | ||
local ChapterURLorigin = A:ORIGIN('ChapterURL'); | |||
local ConferenceURL = A['ConferenceURL']; | local ConferenceURL = A['ConferenceURL']; | ||
local ConferenceURLorigin = A:ORIGIN('ConferenceURL'); | |||
local Periodical = A['Periodical']; | local Periodical = A['Periodical']; | ||
if ( config.CitationClass == "encyclopaedia" ) then | if ( config.CitationClass == "encyclopaedia" ) then | ||
if ( Chapter | if not is_set(Chapter) then | ||
if (Title | if not is_set(Title) then | ||
Title = Periodical; | Title = Periodical; | ||
Periodical = | Periodical = ''; | ||
else | else | ||
Chapter = Title | Chapter = Title | ||
TransChapter = TransTitle | TransChapter = TransTitle | ||
Title = | Title = ''; | ||
TransTitle = | TransTitle = ''; | ||
end | end | ||
end | end | ||
Line 737: | Line 813: | ||
local Volume = A['Volume']; | local Volume = A['Volume']; | ||
local Issue = A['Issue']; | local Issue = A['Issue']; | ||
local Position = | local Position = ''; | ||
local Page, Pages, At, page_type; | local Page, Pages, At, page_type; | ||
Line 743: | Line 819: | ||
Pages = hyphentodash( A['Pages'] ); | Pages = hyphentodash( A['Pages'] ); | ||
At = A['At']; | At = A['At']; | ||
if Page | |||
if Pages | if is_set(Page) then | ||
if is_set(Pages) or is_set(At) then | |||
Page = Page .. " " .. seterror('extra_pages'); | Page = Page .. " " .. seterror('extra_pages'); | ||
Pages = | Pages = ''; | ||
At = | At = ''; | ||
end | end | ||
elseif Pages | elseif is_set(Pages) then | ||
if At | if is_set(At) then | ||
Pages = Pages .. " " .. seterror('extra_pages'); | Pages = Pages .. " " .. seterror('extra_pages'); | ||
At = | At = ''; | ||
end | end | ||
end | end | ||
local Edition = A['Edition']; | local Edition = A['Edition']; | ||
local PublicationPlace = A['PublicationPlace'] | local PublicationPlace = A['PublicationPlace'] | ||
local Place = A['Place']; | local Place = A['Place']; | ||
if PublicationPlace | |||
if not is_set(PublicationPlace) and is_set(Place) then | |||
PublicationPlace = Place; | PublicationPlace = Place; | ||
end | end | ||
if PublicationPlace == Place then Place = | |||
if PublicationPlace == Place then Place = ''; end | |||
local PublisherName = A['PublisherName']; | local PublisherName = A['PublisherName']; | ||
Line 772: | Line 851: | ||
local DeadURL = A['DeadURL'] | local DeadURL = A['DeadURL'] | ||
local Language = A['Language']; | local Language = A['Language']; | ||
local Format = A['Format'] | local Format = A['Format']; | ||
local Ref = A['Ref'] | local Ref = A['Ref']; | ||
local DoiBroken = A['DoiBroken'] | local DoiBroken = A['DoiBroken']; | ||
local ID = A['ID']; | local ID = A['ID']; | ||
local ASINTLD = A['ASINTLD']; | local ASINTLD = A['ASINTLD']; | ||
local IgnoreISBN = A['IgnoreISBN'] | local IgnoreISBN = A['IgnoreISBN']; | ||
local ID_list = extractids( args ); | local ID_list = extractids( args ); | ||
local Quote = A['Quote']; | local Quote = A['Quote']; | ||
local PostScript = A['PostScript'] | local PostScript = A['PostScript']; | ||
local | local LayURL = A['LayURL']; | ||
local LaySource = A['LaySource']; | local LaySource = A['LaySource']; | ||
local Transcript = A['Transcript']; | local Transcript = A['Transcript']; | ||
local TranscriptURL = A['TranscriptURL']; | local TranscriptURL = A['TranscriptURL'] | ||
local sepc = A['Separator'] | local TranscriptURLorigin = A:ORIGIN('TranscriptURL'); | ||
local LastAuthorAmp = A['LastAuthorAmp'] | local sepc = A['Separator']; | ||
local no_tracking_cats = A['NoTracking'] | local LastAuthorAmp = A['LastAuthorAmp']; | ||
local no_tracking_cats = A['NoTracking']; | |||
local this_page = mw.title.getCurrentTitle(); --Also used for COinS | local this_page = mw.title.getCurrentTitle(); --Also used for COinS | ||
if no_tracking_cats | |||
if not is_set(no_tracking_cats) then | |||
for k, v in pairs( cfg.uncategorized_namespaces ) do | for k, v in pairs( cfg.uncategorized_namespaces ) do | ||
if this_page.nsText == v then | if this_page.nsText == v then | ||
Line 802: | Line 883: | ||
end | end | ||
if ( config.CitationClass == "journal" ) then | if ( config.CitationClass == "journal" ) then | ||
if (URL | if not is_set(URL) and is_set(ID_list['PMC']) then | ||
local Embargo = A['Embargo']; | |||
if is_set(Embargo) 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']; | |||
URLorigin = cfg.id_handlers['PMC'].parameters[1]; | |||
end | end | ||
else | |||
URL = "http://www.ncbi.nlm.nih.gov/pmc/articles/PMC" .. ID_list['PMC']; | |||
URLorigin = cfg.id_handlers['PMC'].parameters[1]; | |||
end | end | ||
end | end | ||
Line 825: | Line 906: | ||
-- Account for the oddity that is {{cite conference}}, before generation of COinS data. | -- Account for the oddity that is {{cite conference}}, before generation of COinS data. | ||
if ( BookTitle ) then | if is_set(BookTitle) then | ||
Chapter = Title | Chapter = Title; | ||
ChapterLink = TitleLink | ChapterLink = TitleLink; | ||
TransChapter = TransTitle | TransChapter = TransTitle; | ||
Title = BookTitle | Title = BookTitle; | ||
TitleLink = | TitleLink = ''; | ||
TransTitle = | TransTitle = ''; | ||
end | end | ||
-- Account for the oddity that is {{cite episode}}, before generation of COinS data. | -- Account for the oddity that is {{cite episode}}, before generation of COinS data. | ||
if config.CitationClass == "episode" then | if config.CitationClass == "episode" then | ||
local AirDate = A['AirDate'] | local AirDate = A['AirDate']; | ||
local SeriesLink = A['SeriesLink'] | local SeriesLink = A['SeriesLink']; | ||
local Season = A['Season'] | local Season = A['Season']; | ||
local SeriesNumber = A['SeriesNumber'] | local SeriesNumber = A['SeriesNumber']; | ||
local Network = A['Network'] | local Network = A['Network']; | ||
local Station = A['Station'] | local Station = A['Station']; | ||
local s = {} | local s, n = {}, {}; | ||
if Issue | local Sep = (first_set(A["SeriesSeparator"], A["Separator"]) or "") .. " "; | ||
if Season | |||
if SeriesNumber | if is_set(Issue) then table.insert(s, cfg.messages["episode"] .. " " .. Issue); Issue = ''; end | ||
if is_set(Season) then table.insert(s, cfg.messages["season"] .. " " .. Season); end | |||
if Network | if is_set(SeriesNumber) then table.insert(s, cfg.messages["series"] .. " " .. SeriesNumber); end | ||
if Station | if is_set(Network) then table.insert(n, Network); end | ||
Date = Date or AirDate | if is_set(Station) then table.insert(n, Station); end | ||
Chapter = Title | |||
ChapterLink = TitleLink | Date = Date or AirDate; | ||
TransChapter = TransTitle | Chapter = Title; | ||
Title = Series | ChapterLink = TitleLink; | ||
TitleLink = SeriesLink | TransChapter = TransTitle; | ||
TransTitle = | Title = Series; | ||
TitleLink = SeriesLink; | |||
Series = table.concat(s, Sep) | TransTitle = ''; | ||
ID = table.concat(n, Sep | |||
Series = table.concat(s, Sep); | |||
ID = table.concat(n, Sep); | |||
end | end | ||
-- COinS metadata (see <http://ocoins.info/>) for | |||
-- automated parsing of citation information. | |||
local OCinSoutput = COinS{ | |||
local | ['Periodical'] = Periodical, | ||
['Chapter'] = Chapter, | |||
['Title'] = Title, | |||
['PublicationPlace'] = PublicationPlace, | |||
['Date'] = first_set(Date, Year, PublicationDate), | |||
['Series'] = Series, | |||
['Volume'] = Volume, | |||
['Issue'] = Issue, | |||
['Pages'] = first_set(Page, Pages, At), | |||
['Edition'] = Edition, | |||
['PublisherName'] = PublisherName, | |||
['URL'] = first_set( URL, ChapterURL ), | |||
['Authors'] = a, | |||
['ID_list'] = ID_list, | |||
['RawPage'] = this_page.prefixedText, | |||
}; | |||
if is_set(Periodical) and not is_set(Chapter) and is_set(Title) then | |||
Chapter = Title; | |||
ChapterLink = TitleLink; | |||
TransChapter = TransTitle; | |||
Title = ''; | |||
TitleLink = ''; | |||
TransTitle = ''; | |||
if (Periodical | |||
end | end | ||
Line 955: | Line 975: | ||
-- We also add leading spaces and surrounding markup and punctuation to the | -- We also add leading spaces and surrounding markup and punctuation to the | ||
-- various parts of the citation, but only when they are non-nil. | -- various parts of the citation, but only when they are non-nil. | ||
if ( Authors | if not is_set(Authors) then | ||
local Maximum = tonumber( A['DisplayAuthors'] ); | local Maximum = tonumber( A['DisplayAuthors'] ); | ||
-- Preserve old-style implicit et al. | -- Preserve old-style implicit et al. | ||
if Maximum | if not is_set(Maximum) and #a == 9 then | ||
Maximum = 8; | Maximum = 8; | ||
table.insert( z.message_tail, { seterror('implict_etal_author', {}, true ) } ); | table.insert( z.message_tail, { seterror('implict_etal_author', {}, true ) } ); | ||
elseif Maximum | elseif not is_set(Maximum) then | ||
Maximum = #a + 1; | Maximum = #a + 1; | ||
end | end | ||
Line 968: | Line 988: | ||
local control = { | local control = { | ||
sep = A["AuthorSeparator"] .. " ", | sep = A["AuthorSeparator"] .. " ", | ||
namesep = (A["AuthorNameSeparator"] | namesep = (first_set(A["AuthorNameSeparator"], A["NameSeparator"]) or "") .. " ", | ||
format = A["AuthorFormat"], | format = A["AuthorFormat"], | ||
maximum = Maximum, | maximum = Maximum, | ||
lastauthoramp = LastAuthorAmp | lastauthoramp = LastAuthorAmp | ||
} | }; | ||
-- If the coauthor field is also used, prevent ampersand and et al. formatting. | -- If the coauthor field is also used, prevent ampersand and et al. formatting. | ||
if Coauthors | if is_set(Coauthors) then | ||
control.lastauthoramp = nil; | control.lastauthoramp = nil; | ||
control.maximum = #a + 1; | control.maximum = #a + 1; | ||
end | end | ||
Authors = listpeople(control, a) | Authors = listpeople(control, a) | ||
end | end | ||
local EditorCount | local EditorCount | ||
if ( Editors | if not is_set(Editors) then | ||
local Maximum = tonumber( A['DisplayEditors'] ); | local Maximum = tonumber( A['DisplayEditors'] ); | ||
-- Preserve old-style implicit et al. | -- Preserve old-style implicit et al. | ||
if Maximum | if not is_set(Maximum) and #e == 4 then | ||
Maximum = 3; | Maximum = 3; | ||
table.insert( z.message_tail, { seterror('implict_etal_editor', {}, true) } ); | table.insert( z.message_tail, { seterror('implict_etal_editor', {}, true) } ); | ||
elseif Maximum | elseif not is_set(Maximum) then | ||
Maximum = #e + 1; | Maximum = #e + 1; | ||
end | end | ||
Line 996: | Line 1,016: | ||
local control = { | local control = { | ||
sep = A["EditorSeparator"] .. " ", | sep = A["EditorSeparator"] .. " ", | ||
namesep = (A["EditorNameSeparator"] | namesep = (first_set(A["EditorNameSeparator"], A["NameSeparator"]) or "") .. " ", | ||
format = A['EditorFormat'], | format = A['EditorFormat'], | ||
maximum = Maximum, | maximum = Maximum, | ||
lastauthoramp = LastAuthorAmp | lastauthoramp = LastAuthorAmp | ||
}; | |||
Editors, EditorCount = listpeople(control, e) | Editors, EditorCount = listpeople(control, e); | ||
else | else | ||
EditorCount = 1; | EditorCount = 1; | ||
end | end | ||
if not is_set(Date) then | |||
Date = Year; | |||
if is_set(Date) then | |||
local Month = A['Month']; | |||
if is_set(Month) then | |||
Date = Month .. " " .. Date; | |||
Date = Year | |||
if ( Date | |||
local Month = A['Month'] | |||
if ( Month | |||
Date = Month .. " " .. Date | |||
local Day = A['Day'] | local Day = A['Day'] | ||
if ( Day | if is_set(Day) then Date = Day .. " " .. Date end | ||
end | end | ||
end | end | ||
end | end | ||
if ( PublicationDate | |||
if | if inArray(PublicationDate, {Date, Year}) then PublicationDate = ''; end | ||
if not is_set(Date) and is_set(PublicationDate) then | |||
Date = PublicationDate; | Date = PublicationDate; | ||
PublicationDate = | PublicationDate = ''; | ||
end | end | ||
-- Captures the value for Date prior to adding parens or other textual transformations | -- Captures the value for Date prior to adding parens or other textual transformations | ||
local DateIn = Date | local DateIn = Date; | ||
if ( URL | if not is_set(URL) and | ||
not is_set(ChapterURL) and | |||
not is_set(ArchiveURL) and | |||
not is_set(ConferenceURL) and | |||
not is_set(TranscriptURL) then | |||
-- 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.message_tail, { seterror( 'cite_web_url', {}, true ) } ); | 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 | if is_set(AccessDate) then | ||
table.insert( z.message_tail, { seterror( 'accessdate_missing_url', {}, true ) } ); | table.insert( z.message_tail, { seterror( 'accessdate_missing_url', {}, true ) } ); | ||
AccessDate = | AccessDate = ''; | ||
end | end | ||
-- Test if format is given without giving a URL | -- Test if format is given without giving a URL | ||
if ( Format | if is_set(Format) then | ||
Format = Format .. seterror( 'format_missing_url' ); | Format = Format .. seterror( 'format_missing_url' ); | ||
end | end | ||
end | end | ||
-- Test if citation has no title | -- Test if citation has no title | ||
if ( Chapter | if not is_set(Chapter) and | ||
not is_set(Title) and | |||
not is_set(Periodical) and | |||
not is_set(Conference) and | |||
not is_set(TransTitle) and | |||
not is_set(TransChapter) then | |||
table.insert( z.message_tail, { seterror( 'citation_missing_title', {}, true ) } ); | table.insert( z.message_tail, { seterror( 'citation_missing_title', {}, true ) } ); | ||
end | end | ||
Format = is_set(Format) and " (" .. Format .. ")" or ""; | |||
local OriginalURL = URL | local OriginalURL = URL | ||
Line 1,089: | Line 1,090: | ||
end | end | ||
end | end | ||
-- Format chapter / article title | -- Format chapter / article title | ||
if ( Chapter | if is_set(Chapter) and is_set(ChapterLink) then | ||
Chapter = "[[" .. ChapterLink .. "|" .. Chapter .. "]]"; | Chapter = "[[" .. ChapterLink .. "|" .. Chapter .. "]]"; | ||
end | end | ||
if ( | if is_set(Periodical) and is_set(Title) then | ||
Chapter = wrap( 'italic-title', Chapter ); | Chapter = wrap( 'italic-title', Chapter ); | ||
TransChapter = wrap( 'trans-italic-title', TransChapter ); | TransChapter = wrap( 'trans-italic-title', TransChapter ); | ||
Line 1,103: | Line 1,104: | ||
local TransError = "" | local TransError = "" | ||
if TransChapter | if is_set(TransChapter) then | ||
if not is_set(Chapter) then | |||
TransError = " " .. seterror( 'trans_missing_chapter' ); | |||
else | |||
TransChapter = " " .. TransChapter; | |||
end | |||
end | end | ||
Chapter = Chapter .. TransChapter; | |||
if Chapter | if is_set(Chapter) then | ||
if ( ChapterLink | if not is_set(ChapterLink) then | ||
if ( | if is_set(ChapterURL) then | ||
Chapter = externallink( ChapterURL, Chapter ) .. TransError; | Chapter = externallink( ChapterURL, Chapter ) .. TransError; | ||
if URL | if not is_set(URL) then | ||
Chapter = Chapter .. Format; | Chapter = Chapter .. Format; | ||
Format = ""; | Format = ""; | ||
end | end | ||
elseif ( | elseif is_set(URL) then | ||
Chapter = externallink( URL, Chapter ) .. TransError .. Format; | Chapter = externallink( URL, Chapter ) .. TransError .. Format; | ||
URL = | URL = ""; | ||
Format = "" | Format = ""; | ||
else | else | ||
Chapter = Chapter .. TransError; | Chapter = Chapter .. TransError; | ||
end | end | ||
elseif ChapterURL | elseif is_set(ChapterURL) then | ||
Chapter = Chapter .. " " .. externallink( ChapterURL ) .. | Chapter = Chapter .. " " .. externallink( ChapterURL, nil, ChapterURLorigin ) .. | ||
TransError; | TransError; | ||
else | else | ||
Line 1,132: | Line 1,136: | ||
end | end | ||
Chapter = Chapter .. sepc .. " " -- with end-space | Chapter = Chapter .. sepc .. " " -- with end-space | ||
elseif ChapterURL | elseif is_set(ChapterURL) then | ||
Chapter = " " .. externallink( ChapterURL ) .. sepc .. " "; | Chapter = " " .. externallink( ChapterURL, nil, ChapterURLorigin ) .. sepc .. " "; | ||
end | end | ||
-- Format main title. | -- Format main title. | ||
if ( TitleLink and | if is_set(TitleLink) and is_set(Title) then | ||
Title = "[[" .. TitleLink .. "|" .. Title .. "]]" | |||
end | end | ||
if ( | if is_set(Periodical) then | ||
Title = wrap( 'quoted-title', Title ); | Title = wrap( 'quoted-title', Title ); | ||
TransTitle = wrap( 'trans-quoted-title', TransTitle ); | TransTitle = wrap( 'trans-quoted-title', TransTitle ); | ||
elseif ( config.CitationClass | elseif inArray(config.CitationClass, {"web","news","pressrelease"}) and | ||
not is_set(Chapter) then | |||
Chapter | |||
Title = wrap( 'quoted-title', Title ); | Title = wrap( 'quoted-title', Title ); | ||
TransTitle = wrap( 'trans-quoted-title', TransTitle ); | TransTitle = wrap( 'trans-quoted-title', TransTitle ); | ||
Line 1,157: | Line 1,157: | ||
end | end | ||
TransError = ""; | |||
if TransTitle | if is_set(TransTitle) then | ||
if not is_set(Title) then | |||
TransError = " " .. seterror( 'trans_missing_title' ); | |||
else | |||
TransTitle = " " .. TransTitle; | |||
end | |||
end | end | ||
Title = Title .. TransTitle; | |||
if Title | if is_set(Title) then | ||
if ( TitleLink | if not is_set(TitleLink) and is_set(URL) then | ||
Title = externallink( URL, Title ) .. TransError .. Format | Title = externallink( URL, Title ) .. TransError .. Format | ||
URL = | URL = ""; | ||
Format = | Format = ""; | ||
else | else | ||
Title = Title .. TransError; | Title = Title .. TransError; | ||
end | end | ||
end | end | ||
if ( Place | if is_set(Place) then | ||
if sepc == '.' then | if sepc == '.' then | ||
Place = " " .. wrap( 'written', Place ) .. sepc .. " "; | Place = " " .. wrap( 'written', Place ) .. sepc .. " "; | ||
else | else | ||
Place = " " .. substitute( cfg. | Place = " " .. substitute( cfg.messages['written']:lower(), {Place} ) .. sepc .. " "; | ||
end | end | ||
end | end | ||
if ( Conference | if is_set(Conference) then | ||
if ( ConferenceURL | if is_set(ConferenceURL) then | ||
Conference = externallink( ConferenceURL, Conference ); | Conference = externallink( ConferenceURL, Conference ); | ||
end | end | ||
Conference = " " .. Conference | Conference = " " .. Conference | ||
elseif ConferenceURL | elseif is_set(ConferenceURL) then | ||
Conference = " " .. externallink( ConferenceURL ); | Conference = " " .. externallink( ConferenceURL, nil, ConferenceURLorigin ); | ||
end | end | ||
if ( | if not is_set(Position) then | ||
local Minutes = A['Minutes']; | local Minutes = A['Minutes']; | ||
if ( | if is_set(Minutes) then | ||
Position = " " .. Minutes .. " " .. cfg. | Position = " " .. Minutes .. " " .. cfg.messages['minutes']; | ||
else | else | ||
local Time = A['Time']; | local Time = A['Time']; | ||
if ( | if is_set(Time) then | ||
local TimeCaption = A['TimeCaption'] | local TimeCaption = A['TimeCaption'] | ||
if TimeCaption | if not is_set(TimeCaption) then | ||
TimeCaption = cfg. | TimeCaption = cfg.messages['event']; | ||
if sepc ~= '.' then | if sepc ~= '.' then | ||
TimeCaption = TimeCaption:lower(); | TimeCaption = TimeCaption:lower(); | ||
end | end | ||
end | end | ||
Position = " " .. TimeCaption .. " " .. Time | Position = " " .. TimeCaption .. " " .. Time; | ||
end | end | ||
end | end | ||
else | else | ||
Position = " " .. Position | Position = " " .. Position; | ||
At = ''; | |||
end | end | ||
if ( | |||
if not is_set(Page) then | |||
if ( | if is_set(Pages) then | ||
if is_set(Periodical) and | |||
not inArray(config.CitationClass, {"encyclopaedia","web","book","news"}) then | |||
Pages = ": " .. Pages; | |||
elseif tonumber(Pages) ~= nil then | |||
Pages = sepc .." " .. PPrefix .. Pages; | |||
else | |||
Pages = sepc .." " .. PPPrefix .. Pages; | |||
else Pages = sepc .." " .. PPPrefix .. Pages | |||
end | end | ||
end | end | ||
else | else | ||
if is_set(Periodical) and | |||
if ( Periodical | not inArray(config.CitationClass, {"encyclopaedia","web","book","news"}) then | ||
Page = ": " .. Page; | |||
Page = ": " .. Page | |||
else | else | ||
Page = sepc .." " .. PPrefix .. Page | Page = sepc .." " .. PPrefix .. Page; | ||
end | end | ||
end | end | ||
At = is_set(At) and (sepc .. " " .. At) or ""; | |||
Others = is_set(Others) and (sepc .. " " .. Others) or ""; | |||
TitleType = is_set(TitleType) and (" (" .. TitleType .. ")") or ""; | |||
TitleNote = is_set(TitleNote) and (sepc .. " " .. TitleNote) or ""; | |||
Language = is_set(Language) and (" " .. wrap( 'language', Language )) or ""; | |||
Edition = is_set(Edition) and (" " .. wrap( 'edition', Edition )) or ""; | |||
Issue = is_set(Issue) and (" (" .. Issue .. ")") or ""; | |||
Series = is_set(Series) and (sepc .. " " .. Series) or ""; | |||
OrigYear = is_set(OrigYear) and (" [" .. OrigYear .. "]") or ""; | |||
Agency = is_set(Agency) and (sepc .. " " .. Agency) or ""; | |||
if is_set(Volume) then | |||
then | |||
if ( mw.ustring.len(Volume) > 4 ) | if ( mw.ustring.len(Volume) > 4 ) | ||
then Volume = sepc .." " .. Volume | then Volume = sepc .." " .. Volume; | ||
else Volume = " <b>" .. hyphentodash(Volume) .. "</b>" | else Volume = " <b>" .. hyphentodash(Volume) .. "</b>"; | ||
end | end | ||
end | |||
------------------------------------ totally unrelated data | ------------------------------------ totally unrelated data | ||
if ( | if is_set(Via) then Via = " " .. wrap( 'via', Via ); end | ||
if is_set(AccessDate) then | |||
local retrv_text = " " .. cfg.messages['retrieved'] | |||
if ( AccessDate | if (sepc ~= ".") then retrv_text = retrv_text:lower() end | ||
AccessDate = '<span class="reference-accessdate">' .. sepc | |||
.. substitute( retrv_text, {AccessDate} ) .. '</span>' | |||
end | |||
if is_set(SubscriptionRequired) then | |||
if ( SubscriptionRequired | SubscriptionRequired = sepc .. " " .. cfg.messages['subscription']; | ||
SubscriptionRequired = sepc .. " " .. cfg. | |||
end | end | ||
if ( ID | |||
if is_set(ID) then ID = sepc .." ".. ID; end | |||
ID_list = buildidlist( ID_list, {DoiBroken = DoiBroken, ASINTLD = ASINTLD, IgnoreISBN = IgnoreISBN} ); | ID_list = buildidlist( ID_list, {DoiBroken = DoiBroken, ASINTLD = ASINTLD, IgnoreISBN = IgnoreISBN} ); | ||
if ( URL | if is_set(URL) then | ||
URL = " " .. externallink( URL ); | URL = " " .. externallink( URL, nil, URLorigin ); | ||
end | end | ||
if ( Quote | if is_set(Quote) then | ||
if Quote:sub(1,1) == '"' and Quote:sub(-1,-1) == '"' then | if Quote:sub(1,1) == '"' and Quote:sub(-1,-1) == '"' then | ||
Quote = Quote:sub(2,-2); | Quote = Quote:sub(2,-2); | ||
end | end | ||
Quote = sepc .." " .. wrap( 'quoted-text', Quote ); | Quote = sepc .." " .. wrap( 'quoted-text', Quote ); | ||
PostScript = "" | PostScript = ""; | ||
elseif PostScript:lower() == "none" then | |||
PostScript = ""; | |||
end | end | ||
local Archived | local Archived | ||
if ( | if is_set(ArchiveURL) then | ||
if ( ArchiveDate | if not is_set(ArchiveDate) then | ||
ArchiveDate = seterror('archive_missing_date'); | ArchiveDate = seterror('archive_missing_date'); | ||
end | end | ||
if | if "no" == DeadURL then | ||
local arch_text = cfg. | local arch_text = cfg.messages['archived']; | ||
if | if sepc ~= "." then arch_text = arch_text:lower() end | ||
Archived = sepc .. " " .. substitute( cfg. | Archived = sepc .. " " .. substitute( cfg.messages['archived-not-dead'], | ||
{ externallink( ArchiveURL, arch_text ), ArchiveDate } ); | { externallink( ArchiveURL, arch_text ), ArchiveDate } ); | ||
if OriginalURL | if not is_set(OriginalURL) then | ||
Archived = Archived .. " " .. seterror('archive_missing_url'); | Archived = Archived .. " " .. seterror('archive_missing_url'); | ||
end | end | ||
elseif is_set(OriginalURL) then | |||
local arch_text = cfg.messages['archived-dead']; | |||
if sepc ~= "." then arch_text = arch_text:lower() end | |||
Archived = sepc .. " " .. substitute( arch_text, | |||
{ externallink( OriginalURL, cfg.messages['original'] ), ArchiveDate } ); | |||
else | else | ||
local arch_text = cfg.messages['archived-missing']; | |||
if sepc ~= "." then arch_text = arch_text:lower() end | |||
Archived = sepc .. " " .. substitute( arch_text, | |||
{ seterror('archive_missing_url'), ArchiveDate } ); | |||
end | end | ||
else | else | ||
Archived = "" | Archived = "" | ||
end | end | ||
local Lay | local Lay | ||
if ( | if is_set(LayURL) then | ||
if ( LayDate | if is_set(LayDate) then LayDate = " (" .. LayDate .. ")" end | ||
if ( LaySource | if is_set(LaySource) then | ||
LaySource = " – ''" .. safeforitalics(LaySource) .. "''" | LaySource = " – ''" .. safeforitalics(LaySource) .. "''"; | ||
else | else | ||
LaySource = "" | LaySource = ""; | ||
end | end | ||
if sepc == '.' then | if sepc == '.' then | ||
Lay = sepc .. " " .. externallink( | Lay = sepc .. " " .. externallink( LayURL, cfg.messages['lay summary'] ) .. LaySource .. LayDate | ||
else | else | ||
Lay = sepc .. " " .. externallink( | Lay = sepc .. " " .. externallink( LayURL, cfg.messages['lay summary']:lower() ) .. LaySource .. LayDate | ||
end | end | ||
else | else | ||
Lay = "" | Lay = ""; | ||
end | end | ||
if ( | |||
if ( TranscriptURL | if is_set(Transcript) then | ||
elseif TranscriptURL | if is_set(TranscriptURL) then Transcript = externallink( TranscriptURL, Transcript ); end | ||
Transcript = externallink( TranscriptURL ) | elseif is_set(TranscriptURL) then | ||
Transcript = externallink( TranscriptURL, nil, TranscriptURLorigin ); | |||
end | end | ||
local Publisher | |||
if ( Periodical | local Publisher; | ||
if is_set(Periodical) and | |||
not inArray(config.CitationClass, {"encyclopaedia","web","pressrelease"}) then | |||
if is_set(PublisherName) then | |||
if ( PublisherName | if is_set(PublicationPlace) then | ||
if (PublicationPlace | |||
Publisher = PublicationPlace .. ": " .. PublisherName; | Publisher = PublicationPlace .. ": " .. PublisherName; | ||
else | else | ||
Publisher = PublisherName; | Publisher = PublisherName; | ||
end | end | ||
elseif (PublicationPlace | elseif is_set(PublicationPlace) then | ||
Publisher= PublicationPlace; | Publisher= PublicationPlace; | ||
else | else | ||
Publisher = ""; | Publisher = ""; | ||
end | end | ||
if ( PublicationDate | if is_set(PublicationDate) then | ||
if Publisher | if is_set(Publisher) then | ||
Publisher = Publisher .. ", " .. wrap( 'published', PublicationDate ); | Publisher = Publisher .. ", " .. wrap( 'published', PublicationDate ); | ||
else | else | ||
Line 1,387: | Line 1,358: | ||
end | end | ||
end | end | ||
if Publisher | if is_set(Publisher) then | ||
Publisher = " (" .. Publisher .. ")"; | Publisher = " (" .. Publisher .. ")"; | ||
end | end | ||
else | else | ||
if ( PublicationDate | if is_set(PublicationDate) then | ||
PublicationDate = " (" .. wrap( 'published', PublicationDate ) .. ")" | PublicationDate = " (" .. wrap( 'published', PublicationDate ) .. ")"; | ||
end | end | ||
if ( PublisherName | if is_set(PublisherName) then | ||
if (PublicationPlace | if is_set(PublicationPlace) then | ||
Publisher = sepc .. " " .. PublicationPlace .. ": " .. PublisherName .. PublicationDate; | Publisher = sepc .. " " .. PublicationPlace .. ": " .. PublisherName .. PublicationDate; | ||
else | else | ||
Publisher = sepc .. " " .. PublisherName .. PublicationDate; | Publisher = sepc .. " " .. PublisherName .. PublicationDate; | ||
end | end | ||
elseif (PublicationPlace | elseif is_set(PublicationPlace) then | ||
Publisher= sepc .. " " .. PublicationPlace .. PublicationDate; | Publisher= sepc .. " " .. PublicationPlace .. PublicationDate; | ||
else | else | ||
Line 1,408: | Line 1,377: | ||
end | end | ||
end | end | ||
-- Several of the above rely upon detecting this as nil, so do it last. | -- Several of the above rely upon detecting this as nil, so do it last. | ||
if ( Periodical | if is_set(Periodical) then | ||
if ( Title | if is_set(Title) or is_set(TitleNote) then | ||
Periodical = sepc .. " " .. wrap( 'italic-title', Periodical ) | Periodical = sepc .. " " .. wrap( 'italic-title', Periodical ) | ||
else | else | ||
Periodical = wrap( 'italic-title', Periodical ) | Periodical = wrap( 'italic-title', Periodical ) | ||
end | end | ||
end | |||
-- Piece all bits together at last. Here, all should be non-nil. | -- Piece all bits together at last. Here, all should be non-nil. | ||
Line 1,422: | Line 1,392: | ||
local tcommon | local tcommon | ||
if | if inArray(config.CitationClass, {"journal","citation"}) and is_set(Periodical) then | ||
if is_set(Others) then Others = Others .. sepc .. " " end | |||
if (Others | |||
tcommon = safejoin( {Others, Title, TitleNote, Conference, Periodical, Format, TitleType, Series, | tcommon = safejoin( {Others, Title, TitleNote, Conference, Periodical, Format, TitleType, Series, | ||
Language, Edition, Publisher, Agency, Volume, Issue, Position}, sepc ); | Language, Edition, Publisher, Agency, Volume, Issue, Position}, sepc ); | ||
Line 1,436: | Line 1,405: | ||
else | else | ||
ID_list = ID; | ID_list = ID; | ||
end | end | ||
local idcommon = safejoin( { ID_list, URL, Archived, AccessDate, Via, SubscriptionRequired, Lay, Quote }, sepc ); | 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 ( | if is_set(Authors) then | ||
if (Coauthors | if is_set(Coauthors) then | ||
Authors = Authors .. A['AuthorSeparator'] .. " " .. Coauthors | |||
end | end | ||
if ( | if is_set(Date) then | ||
Date = " ("..Date..")" .. OrigYear .. sepc .. " " | |||
elseif string.sub(Authors,-1,-1) == sepc then | |||
Authors = Authors .. " " | |||
else | |||
Authors = Authors .. sepc .. " " | |||
end | end | ||
if ( | if is_set(Editors) then | ||
local in_text = " in " | local in_text = " " .. cfg.messages['in'] .. " " | ||
if (sepc | if (sepc ~= '.') then in_text = in_text:lower() end | ||
if (string.sub(Editors,-1,-1) == sepc) | if (string.sub(Editors,-1,-1) == sepc) | ||
then Editors = in_text .. Editors .. " " | then Editors = in_text .. Editors .. " " | ||
Line 1,464: | Line 1,432: | ||
text = safejoin( {Authors, Date, Chapter, Place, Editors, tcommon }, sepc ); | text = safejoin( {Authors, Date, Chapter, Place, Editors, tcommon }, sepc ); | ||
text = safejoin( {text, pgtext, idcommon}, sepc ); | text = safejoin( {text, pgtext, idcommon}, sepc ); | ||
elseif ( | elseif is_set(Editors) then | ||
if ( | if is_set(Date) then | ||
if EditorCount <= 1 then | if EditorCount <= 1 then | ||
Editors = Editors .. ", " .. cfg. | Editors = Editors .. ", " .. cfg.messages['editor']; | ||
else | else | ||
Editors = Editors .. ", " .. cfg. | Editors = Editors .. ", " .. cfg.messages['editors']; | ||
end | end | ||
Date = " (" .. Date ..")" .. OrigYear .. sepc .. " " | Date = " (" .. Date ..")" .. OrigYear .. sepc .. " " | ||
else | else | ||
if EditorCount <= 1 then | if EditorCount <= 1 then | ||
Editors = Editors .. " (" .. cfg. | Editors = Editors .. " (" .. cfg.messages['editor'] .. ")" .. sepc .. " " | ||
else | else | ||
Editors = Editors .. " (" .. cfg. | Editors = Editors .. " (" .. cfg.messages['editors'] .. ")" .. sepc .. " " | ||
end | end | ||
end | end | ||
Line 1,482: | Line 1,450: | ||
text = safejoin( {text, pgtext, idcommon}, sepc ); | text = safejoin( {text, pgtext, idcommon}, sepc ); | ||
else | else | ||
if ( | if is_set(Date) then | ||
if ( string.sub(tcommon,-1,-1) ~= sepc ) | if ( string.sub(tcommon,-1,-1) ~= sepc ) | ||
then Date = sepc .." " .. Date .. OrigYear | then Date = sepc .." " .. Date .. OrigYear | ||
else Date = " " .. Date .. OrigYear | else Date = " " .. Date .. OrigYear | ||
end | end | ||
end | end | ||
if | if config.CitationClass=="journal" and is_set(Periodical) then | ||
text = safejoin( {Chapter, Place, tcommon}, sepc ); | |||
text = safejoin( {text, pgtext, Date, idcommon}, sepc ); | |||
else | else | ||
text = safejoin( {Chapter, Place, tcommon, Date}, sepc ); | |||
text = safejoin( {text, pgtext, idcommon}, sepc ); | |||
end | end | ||
end | end | ||
if PostScript | if is_set(PostScript) and PostScript ~= sepc then | ||
text = safejoin( {text, sepc}, sepc ); --Deals with italics, spaces, etc. | text = safejoin( {text, sepc}, sepc ); --Deals with italics, spaces, etc. | ||
text = text:sub(1,-2); --Remove final seperator | text = text:sub(1,-2); --Remove final seperator | ||
Line 1,505: | Line 1,473: | ||
-- Now enclose the whole thing in a <span/> element | -- Now enclose the whole thing in a <span/> element | ||
if ( Year | if not is_set(Year) then | ||
if ( DateIn | if is_set(DateIn) then | ||
Year = selectyear( DateIn ) | Year = selectyear( DateIn ); | ||
elseif( PublicationDate | elseif is_set(PublicationDate) then | ||
Year = selectyear( PublicationDate ) | Year = selectyear( PublicationDate ); | ||
end | end | ||
end | end | ||
local | |||
if ( config.CitationClass ~= "citation" | local options = {}; | ||
if is_set(config.CitationClass) and config.CitationClass ~= "citation" then | |||
if ( Ref ~= | options.class = "citation " .. config.CitationClass; | ||
else | |||
options.class = "citation"; | |||
end | |||
if is_set(Ref) and Ref:lower() ~= "none" then | |||
local id = Ref | local id = Ref | ||
if ( "harv" == Ref ) then | if ( "harv" == Ref ) then | ||
local names = {} --table of last names & year | local names = {} --table of last names & year | ||
if ( | if is_set(Authors) then | ||
for i,v in ipairs(a) do | for i,v in ipairs(a) do | ||
names[i] = v.last | names[i] = v.last | ||
if i == 4 then break end | if i == 4 then break end | ||
end | end | ||
elseif ( | elseif is_set(Editors) then | ||
for i,v in ipairs(e) do | for i,v in ipairs(e) do | ||
names[i] = v.last | names[i] = v.last | ||
Line 1,545: | Line 1,516: | ||
end | end | ||
if options.id | if is_set(options.id) then | ||
text = '<span id="' .. | text = '<span id="' .. mw.uri.anchorEncode(options.id) ..'" class="' .. mw.text.nowiki(options.class) .. '">' .. text .. "</span>"; | ||
else | else | ||
text = '<span class="' .. | text = '<span class="' .. mw.text.nowiki(options.class) .. '">' .. text .. "</span>"; | ||
end | end | ||
Line 1,554: | Line 1,525: | ||
-- Note: Using display: none on then COinS span breaks some clients. | -- Note: Using display: none on then COinS span breaks some clients. | ||
local OCinS = '<span title="' .. | local OCinS = '<span title="' .. OCinSoutput .. '" class="Z3988">' .. empty_span .. '</span>'; | ||
text = text .. OCinS; | text = text .. OCinS; | ||
Line 1,560: | Line 1,531: | ||
text = text .. " "; | text = text .. " "; | ||
for i,v in ipairs( z.message_tail ) do | for i,v in ipairs( z.message_tail ) do | ||
if v[1] | if is_set(v[1]) then | ||
if i == #z.message_tail then | if i == #z.message_tail then | ||
text = text .. errorcomment( v[1], v[2] ); | text = text .. errorcomment( v[1], v[2] ); | ||
Line 1,571: | Line 1,542: | ||
no_tracking_cats = no_tracking_cats:lower(); | no_tracking_cats = no_tracking_cats:lower(); | ||
if no_tracking_cats | if inArray(no_tracking_cats, {"", "no", "false", "n"}) then | ||
for _, v in ipairs( z.error_categories ) do | for _, v in ipairs( z.error_categories ) do | ||
text = text .. '[[Category:' .. v ..']]'; | text = text .. '[[Category:' .. v ..']]'; | ||
Line 1,588: | Line 1,558: | ||
local suggestions = {}; | local suggestions = {}; | ||
local error_text, error_state; | local error_text, error_state; | ||
local config = {}; | |||
for k, v in pairs( frame.args ) do | |||
config[k] = v; | |||
args[k] = v; | |||
end | |||
for k, v in pairs( pframe.args ) do | for k, v in pairs( pframe.args ) do | ||
if v ~= '' then | if v ~= '' then | ||
Line 1,612: | Line 1,589: | ||
table.insert( z.message_tail, {error_text, error_state} ); | table.insert( z.message_tail, {error_text, error_state} ); | ||
end | end | ||
end | end | ||
args[k] = v; | args[k] = v; | ||
elseif | elseif args[k] ~= nil or (k == 'postscript') then | ||
args[k] = v; | args[k] = v; | ||
end | end |