Module:Citation/CS1: Difference between revisions

3,282 bytes removed ,  11 years ago
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:
}
}


local SEEN = {};
-- Include translation message hooks, ID and error handling configuration settings.
local DATA = {};
-- 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' );


-- Include translation message hooks, ID and error handling configuration settings.
local cfg = require( 'Module:Citation/CS1/Configuration' );
-- 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' );


-- Populates numbered arguments in a message string using
-- Whether variable is set or not
-- an argument table.
function is_set( var )
function substitute( message, arguments )
    return not (var == nil or var == '');
     if arguments == nil then  
end
         return message;
 
-- 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;
    message = message .. " ";
end
    for k, v in ipairs( arguments ) do
 
        v = v:gsub( "%%", "%%%%" );
-- Populates numbered arguments in a message string using an argument table.
        message = message:gsub( "$" .. k .. "(%D)", v .. "%1" );
function substitute( msg, args )
    end   
    return args and tostring( mw.message.newRawMessage( msg, args ) ) or msg;
    message = message:sub(1,-2);
    return message;
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( message_key, str )
function wrap( key, str )
     if str == nil or str == "" then
     if not is_set( str ) then
         return "";
         return "";
     end
     elseif inArray( key, { 'italic-title', 'trans-italic-title' } ) then
    if message_key == 'italic-title' or
            message_key == 'trans-italic-title' then
         str = safeforitalics( str );
         str = safeforitalics( str );
     end
     end
     return substitute( cfg.message_list[message_key], {str} );
     return substitute( cfg.messages[key], {str} );
end
end


Line 48: Line 63:
]]
]]
function argument_wrapper( args )
function argument_wrapper( args )
    DATA = args;
     local origin = {};
     local tbl = {};
      
      
     local mt = {
     return setmetatable({
         __index = function ( tbl, k )          
        ORIGIN = function( self, k )
             if SEEN[k] then
            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.argument_map[k];                  
             local args, list, v = args, cfg.aliases[k];
 
           
             if list == nil then
             if list == nil then
                 error( cfg.message_list['unknown_argument_map'] );
                 error( cfg.messages['unknown_argument_map'] );
             elseif type( list ) == 'string' then
             elseif type( list ) == 'string' then
                 v = DATA[list];
                 v, origin[k] = args[list], list;
             else                  
             else
                 v = selectone( DATA, cfg.argument_map[k],
                 v, origin[k] = selectone( args, list, 'redundant_parameters' );
                     '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.default_values[k];
                 v = cfg.defaults[k] or "";
                origin[k] = '';  --Empty string, not nil;
             end
             end
             SEEN[k] = true;
              
             tbl = rawset( tbl, k, v );
             tbl = rawset( tbl, k, v );
           
             return v;
             return v;
         end,
         end,
     }
     });
    return setmetatable( tbl, mt );
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 )
     if hidden then
     return wrap( hidden and 'hidden-error' or 'visible-error', content );
        return wrap( 'hidden-error', content );
    else
        return wrap( 'visible-error', content );
    end       
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.message_list['undefined_error'] );
         error( cfg.messages['undefined_error'] );
    elseif is_set( error_state.category ) then
        table.insert( z.error_categories, error_state.category );
     end
     end
      
      
     if error_state.category ~= nil and error_state.category ~= "" then
     local message = substitute( error_state.message, arguments );
        table.insert( z.error_categories, error_state.category );
    end
      
      
     local message = error_state.message;
     message = message .. " ([[" .. cfg.messages['help page link'] ..  
    message = substitute( message, arguments );
 
    message = wikiescape(message) .. " ([[" .. cfg.message_list['help page link'] ..  
         "#" .. error_state.anchor .. "|" ..
         "#" .. error_state.anchor .. "|" ..
         cfg.message_list['help page label'] .. "]])";
         cfg.messages['help page label'] .. "]])";
 
   
     z.error_ids[ error_id ] = true;
     z.error_ids[ error_id ] = true;
     if (error_id == 'bare_url_missing_title' or error_id == 'trans_missing_title')
     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 .. suffix;
     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
-- This returns a string with HTML character entities for wikitext markup characters.
function wikiescape(text)
    text = text:gsub( '[&\'%[%]{|}]', {   
            ['&'] = '&',   
            ["'"] = ''',   
            ['['] = '[',   
            [']'] = ']',   
            ['{'] = '{',   
            ['|'] = '|',   
            ['}'] = '}' } );
    return text;
end
end


-- Formats a wiki style external link
-- Formats a wiki style external link
function externallinkid(options)
function externallinkid(options)
    local sep = options.separator or " "
     local url_string = options.id;
    options.suffix = options.suffix or ""
     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 .. "]]" .. sep .. "[" ..
        options.link, options.label, options.separator or " ",
            options.prefix .. url_string .. options.suffix .. " " .. mw.text.nowiki(options.id) .. "]"
        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)
     local sep = options.separator or " "
     return mw.ustring.format( '[[%s|%s]]%s[[%s%s%s|%s]]',
    options.suffix = options.suffix or ""
        options.link, options.label, options.separator or " ",
    return "[[" .. options.link .. "|" .. options.label .. "]]" .. sep .. "[[" ..
        options.prefix, options.id, options.suffix or "",
            options.prefix .. options.id .. options.suffix .. "|" .. mw.text.nowiki(options.id) .. "]]"
        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 == nil or label == "" then
     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 "[" .. URL .. ' ' .. safeforurl( label ) .. "]" .. error_str;
end
end


-- Formats a link to Amazon
-- Formats a link to Amazon
function amazon(id, domain)
function amazon(id, domain)
     if ( nil == domain ) then  
     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 ~= nil ) then  
     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.message_list['inactive'] .. " " .. inactive .. ")"  
         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 )
     if url_str:sub(1,2) == "//" then 
     -- Protocol-relative or URL scheme
        -- Protocol-less URLs
    return url_str:sub(1,2) == "//" or url_str:match( "^[^/]*:" ) ~= nil;
        return true;
    elseif url_str:match( "^[^/]*:" ) ~= nil then 
        -- Look for ":" prefix and assume it is a URI scheme
        return true;
    else
        -- Anything else is an error
        return false;
    end
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 )
     str = str:gsub( "%[%[[^|%]]*|([^%]]*)%]%]", "%1" );
     return (str:gsub( "%[%[([^%[%]]*)%]%]", function(l)
    str = str:gsub( "%[%[([^%]]*)%]%]", "%1" );  
        return l:gsub( "^[^|]*|(.*)$", "%1" ):gsub("^%s*(.-)%s*$", "%1");
     return str
     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 == nil then
     if not is_set(str) or str:match( "[%[%]{}<>]" ) ~= nil then
        return nil;
    end   
    if 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 == nil or str == '' then
     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.abs(num) then
     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;
    if sep:sub(-1,-1) ~= " " then sep = sep .. " " end
     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 ~= nil or person.last ~= "") then
         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 ( maximum ~= nil and i > maximum ) then
             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 ~= nil and first ~= '') then  
                 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 ~= nil and person.link ~= "") then one = "[[" .. person.link .. "|" .. one .. "]]" end
                 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 ~= nil and lastauthoramp ~= "" and not etal then
         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.message_list['et al'];
         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" .. mw.uri.anchorEncode( table.concat( options ) );
     return "CITEREF" .. table.concat( options );
end
end


Line 538: Line 536:
      
      
     while true do
     while true do
         last = selectone( args, cfg.argument_map[list_name .. '-Last'], 'redundant_parameters', i );
         last = selectone( args, cfg.aliases[list_name .. '-Last'], 'redundant_parameters', i );
         if ( last and "" < last ) then -- just in case someone passed in an empty parameter
         if not is_set(last) then
            names[i] = {
            -- just in case someone passed in an empty parameter
                last = last,
                first = selectone( args, cfg.argument_map[list_name .. '-First'], 'redundant_parameters', i ),
                link = selectone( args, cfg.argument_map[list_name .. '-Link'], 'redundant_parameters', i ),
                mask = selectone( args, cfg.argument_map[list_name .. '-Mask'], 'redundant_parameters', i )
            }               
        else
             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     
         id_list[k] = selectone( args, v.parameters, 'redundant_parameters' );
         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 = {};
     local new_list = {};
      
    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
        handler = {};
         -- fallback to read-only cfg
       
         handler = setmetatable( { ['id'] = v }, fallback(k) );
         --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      
         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 == 'manual' then
         elseif handler.mode ~= 'manual' then
             if k == 'DOI' then
             error( cfg.messages['unknown_ID_mode'] );
                table.insert( new_list, {handler.label, doi( v, options.DoiBroken ) } );
        elseif k == 'DOI' then
            elseif k == 'ASIN' then
            table.insert( new_list, {handler.label, doi( v, options.DoiBroken ) } );
                table.insert( new_list, {handler.label, amazon( v, options.ASINTLD ) } );  
        elseif k == 'ASIN' then
            elseif k == 'OL' then
            table.insert( new_list, {handler.label, amazon( v, options.ASINTLD ) } );  
                table.insert( new_list, {handler.label, openlibrary( v ) } );
        elseif k == 'OL' then
            elseif k == 'ISBN' then
            table.insert( new_list, {handler.label, openlibrary( v ) } );
                local ISBN = internallinkid( handler );
        elseif k == 'ISBN' then
                if not checkisbn( v ) and ( options.IgnoreISBN == nil or options.IgnoreISBN == "" ) then  
            local ISBN = internallinkid( handler );
                    ISBN = ISBN .. seterror( 'bad_isbn', {}, false, " ", "" );
            if not checkisbn( v ) and not is_set(options.IgnoreISBN) then
                end
                ISBN = ISBN .. seterror( 'bad_isbn', {}, false, " ", "" );
                table.insert( new_list, {handler.label, ISBN } );                 
            end
            else
            table.insert( new_list, {handler.label, ISBN } );                 
                error( cfg.message_list['unknown_manual_ID'] );
            end           
         else
         else
             error( cfg.message_list['unknown_ID_mode'] );
             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] ~= nil then
             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] ~= nil then
         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 .. ", " end
             if error_str ~= "" then error_str = error_str .. cfg.messages['parameter-separator'] end
             error_str = error_str .. "<code>|" .. k .. "=</code>";
             error_str = error_str .. wrap( 'parameter', k );
         end
         end
         if #error_list > 1 then
         if #error_list > 1 then
             error_str = error_str .. ", and ";
             error_str = error_str .. cfg.messages['parameter-final-separator'];
         else
         else
             error_str = error_str .. " and ";
             error_str = error_str .. cfg.messages['parameter-pair-separator'];
         end
         end
         error_str = error_str .. "<code>|" .. selected .. "=</code>";
         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 ( nil ~= A['NoPP'] ) then PPPrefix = "" PPrefix = "" end
     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 == nil or Chapter == '' ) then  
         if not is_set(Chapter) then
             if (Title == nil or Title == "") then
             if not is_set(Title) then
                 Title = Periodical;
                 Title = Periodical;
                 Periodical = nil;
                 Periodical = '';
             else
             else
                 Chapter = Title
                 Chapter = Title
                 TransChapter = TransTitle
                 TransChapter = TransTitle
                 Title = nil
                 Title = '';
                 TransTitle = nil
                 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 = nil
     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 ~= nil then
   
         if Pages ~= nil or At ~= nil then
     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 = nil;
             Pages = '';
             At = nil;
             At = '';
         end
         end
     elseif Pages ~= nil then
     elseif is_set(Pages) then
         if At ~= nil then
         if is_set(At) then
             Pages = Pages .. " " .. seterror('extra_pages');
             Pages = Pages .. " " .. seterror('extra_pages');
             At = nil;
             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 == nil and Place ~= nil then  
   
     if not is_set(PublicationPlace) and is_set(Place) then
         PublicationPlace = Place;
         PublicationPlace = Place;
     end
     end
     if PublicationPlace == Place then Place = nil end
   
     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 LaySummary = A['LaySummary']
     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'] or "";
     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 == "" then
   
     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 == nil or URL == "") then
         if not is_set(URL) and is_set(ID_list['PMC']) then
            if (ID_list['PMC'] ~= nil) then  
            local Embargo = A['Embargo'];
                local Embargo = A['Embargo'];
            if is_set(Embargo) then
                if Embargo ~= nil then
                local lang = mw.getContentLanguage();
                    local lang = mw.getContentLanguage();
                local good1, result1, good2, result2;
                    local good1, result1, good2, result2;
                good1, result1 = pcall( lang.formatDate, lang, 'U', Embargo );
                    good1, result1 = pcall( lang.formatDate, lang, 'U', Embargo );
                good2, result2 = pcall( lang.formatDate, lang, 'U' );
                    good2, result2 = pcall( lang.formatDate, lang, 'U' );
               
 
                if good1 and good2 and tonumber( result1 ) < tonumber( result2 ) then  
                    if good1 and good2 and tonumber( result1 ) < tonumber( result2 ) then  
                    URL = "http://www.ncbi.nlm.nih.gov/pmc/articles/PMC" .. ID_list['PMC'];
                        URL = "http://www.ncbi.nlm.nih.gov/pmc/articles/PMC" .. ID_list['PMC'];
                     URLorigin = cfg.id_handlers['PMC'].parameters[1];
                     end
                else
                    URL = "http://www.ncbi.nlm.nih.gov/pmc/articles/PMC" .. ID_list['PMC'];          
                 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 = nil
         TitleLink = '';
         TransTitle = nil
         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 ~= nil then table.insert(s, cfg.message_list["episode"] .. " " .. Issue) Issue = nil end
        local Sep = (first_set(A["SeriesSeparator"], A["Separator"]) or "") .. " ";
         if Season ~= nil then table.insert(s, cfg.message_list["season"] .. " " .. Season) end
       
         if SeriesNumber ~= nil then table.insert(s, cfg.message_list["series"] .. " " .. SeriesNumber) end
         if is_set(Issue) then table.insert(s, cfg.messages["episode"] .. " " .. Issue); Issue = ''; end
        local n = {}
         if is_set(Season) then table.insert(s, cfg.messages["season"] .. " " .. Season); end
         if Network ~= nil then table.insert(n, Network) end
         if is_set(SeriesNumber) then table.insert(s, cfg.messages["series"] .. " " .. SeriesNumber); end
         if Station ~= nil then table.insert(n, Station) end
         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 = nil
         Title = Series;
         local Sep = (A["SeriesSeparator"] or A["Separator"]) .. " "
         TitleLink = SeriesLink;
         Series = table.concat(s, Sep)
         TransTitle = '';
         ID = table.concat(n, Sep)
          
    end
         Series = table.concat(s, Sep);
   
         ID = table.concat(n, Sep);
    -- These data form a COinS tag (see <http://ocoins.info/>) which allows
    -- automated tools to parse the citation information.
    local OCinSdata = {} -- COinS metadata excluding id, bibcode, doi, etc.
    local ctx_ver = "Z39.88-2004"
    OCinSdata.rft_val_fmt = "info:ofi/fmt:kev:mtx:book"
    if ( nil ~= Periodical ) then
        OCinSdata.rft_val_fmt = "info:ofi/fmt:kev:mtx:journal"
        OCinSdata["rft.genre"] = "article"
        OCinSdata["rft.jtitle"] = Periodical
        if ( nil ~= Title ) then OCinSdata["rft.atitle"] = Title end
    end
    if ( nil ~= Chapter and "" ~= Chapter) then
        OCinSdata.rft_val_fmt = "info:ofi/fmt:kev:mtx:book"
        OCinSdata["rft.genre"] = "bookitem"
        OCinSdata["rft.btitle"] = Chapter
        if ( nil ~= Title ) then OCinSdata["rft.atitle"] = Title end
    else
        OCinSdata["rft.genre"] = "book"
        if ( nil ~= Title ) then OCinSdata["rft.btitle"] = Title end
    end
    OCinSdata["rft.place"] = PublicationPlace
    OCinSdata["rft.date"] = Date or Year or PublicationDate
    OCinSdata["rft.series"] = Series
    OCinSdata["rft.volume"] = Volume
    OCinSdata["rft.issue"] = Issue
    OCinSdata["rft.pages"] = Page or Pages or At
    OCinSdata["rft.edition"] = Edition
    OCinSdata["rft.pub"] = PublisherName
   
    for k, v in pairs( ID_list ) do
        if k == 'ISBN' then
            v = cleanisbn( v );
        end
        if string.sub( cfg.id_handlers[k].COinS or "info", 1, 4 ) ~= 'info' then
            OCinSdata[ cfg.id_handlers[k].COinS ] = v;
        end
     end
     end
      
      
     OCinSdata.rft_id = URL or ChapterURL
     -- COinS metadata (see <http://ocoins.info/>) for
 
     -- automated parsing of citation information.
     local last, first;
     local OCinSoutput = COinS{
     local OCinSauthors = {};
        ['Periodical'] = Periodical,
    for k, v in ipairs( a ) do
         ['Chapter'] = Chapter,
         last = v.last;
         ['Title'] = Title,
         first = v.first;
         ['PublicationPlace'] = PublicationPlace,
         if k == 1 then
        ['Date'] = first_set(Date, Year, PublicationDate),
            if last ~= nil then
        ['Series'] = Series,
                OCinSdata["rft.aulast"] = last;
        ['Volume'] = Volume,
            end
        ['Issue'] = Issue,
            if first ~= nil then
         ['Pages'] = first_set(Page, Pages, At),
                OCinSdata["rft.aufirst"] = first;
        ['Edition'] = Edition,
            end
         ['PublisherName'] = PublisherName,
         end
        ['URL'] = first_set( URL, ChapterURL ),
        if last ~= nil and first ~= nil then
         ['Authors'] = a,
            table.insert( OCinSauthors, last .. ", " .. first );
        ['ID_list'] = ID_list,
    elseif last ~= nil then
        ['RawPage'] = this_page.prefixedText,
            table.insert( OCinSauthors, last );
     };
         end
    end
 
    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"
     if is_set(Periodical) and not is_set(Chapter) and is_set(Title) then
    for name,value in pairs(OCinSdata) do
        Chapter = Title;
        OCinStitle = OCinStitle .. "&" .. name .. "=" .. mw.uri.encode( removewikilink(value) );
        ChapterLink = TitleLink;
    end
        TransChapter = TransTitle;
    for _, value in ipairs(OCinSauthors) do
        Title = '';
        OCinStitle = OCinStitle .. "&rft.au=" .. mw.uri.encode( removewikilink(value) );
        TitleLink = '';
    end
        TransTitle = '';
    for name,value in pairs(OCinSids) do
        OCinStitle = OCinStitle .. "&rft_id=" .. mw.uri.encode(name .. "/" .. removewikilink(value) );
    end
   
    OCinStitle = OCinStitle .. "&rfr_id=info:sid/" .. mw.site.server:match( "[^/]*$" ) .. ":"
      .. this_page.prefixedText  -- end COinS data by page's non-encoded pagename
 
     if (Periodical ~= nil and Periodical ~= "") and
        (Chapter == nil or Chapter == '') and
        (Title ~= nil and Title ~= "") then
            Chapter = Title
            ChapterLink = TitleLink
            TransChapter = TransTitle
            Title = nil
            TitleLink = nil
            TransTitle = nil           
     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 == nil ) then  
     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 == nil and #a == 9 then  
         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 == nil then
         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"] or A["NameSeparator"]) .. " ",
             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 ~= nil and Coauthors ~= "" then
         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 == nil ) then  
     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 == nil and #e == 4 then  
         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 == nil then
         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"] or A["NameSeparator"]) .. " ",
             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 ( Date == nil or Date == "") then
      
--  there's something hinky with how this adds dashes to perfectly-good free-standing years
    if not is_set(Date) then
--[[        Date = Year
         Date = Year;
        if ( Date ~= nil ) then
         if is_set(Date) then
            local Month = args.month
             local Month = A['Month'];
            if ( Month == nil ) then  
             if is_set(Month) then  
                local Began = args.began
                 Date = Month .. " " .. Date;
                local Ended = args.ended
                if Began ~= nil and Ended ~= nil then
                    Month = Began .. "&ndash;" .. Ended
                else
                    Month = "&ndash;"
                end
            end
            Date = Month .. " " .. Date
            local Day = args.day
            if ( Day ~= nil ) then Date = Day .. " " .. Date end
        end
]] -- so let's use the original version for now
         Date = Year
         if ( Date ~= nil and Date ~="") then
             local Month = A['Month']
             if ( Month ~= nil and Month ~= "") then  
                 Date = Month .. " " .. Date  
                 local Day = A['Day']
                 local Day = A['Day']
                 if ( Day ~= nil ) then Date = Day .. " " .. Date end
                 if is_set(Day) then Date = Day .. " " .. Date end
                else Month = ""
             end
             end
            else Date = ""
         end
         end
     end
     end
     if ( PublicationDate == Date or PublicationDate == Year ) then PublicationDate = nil end
   
     if( (Date == nil or Date == "") and PublicationDate ~= nil ) then  
     if inArray(PublicationDate, {Date, Year}) then PublicationDate = ''; end
     if not is_set(Date) and is_set(PublicationDate) then
         Date = PublicationDate;
         Date = PublicationDate;
         PublicationDate = nil;
         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 == nil or URL == '' ) and
     if not is_set(URL) and
            ( ChapterURL == nil or ChapterURL == '' ) and
        not is_set(ChapterURL) and
            ( ArchiveURL == nil or ArchiveURL == '' ) and              
        not is_set(ArchiveURL) and
            ( ConferenceURL == nil or ConferenceURL == '' ) and              
        not is_set(ConferenceURL) and
            ( TranscriptURL == nil or TranscriptURL == '' ) then
        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 ~= nil and AccessDate ~= '' ) then
         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 = nil;
             AccessDate = '';
         end    
         end
   
       
         -- 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 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 == nil or Chapter == "" ) and  
     if not is_set(Chapter) and
            ( Title == nil or Title == "" ) and
        not is_set(Title) and
            ( Periodical == nil or Periodical == "" ) and
        not is_set(Periodical) and
            ( Conference == nil or Conference == "" ) and  
        not is_set(Conference) and
            ( TransTitle == nil or TransTitle == "" ) and
        not is_set(TransTitle) and
            ( TransChapter == nil or TransChapter == "" ) then
        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
 
   
     if ( Format ~= nil and Format ~="" ) then
     Format = is_set(Format) and " (" .. Format .. ")" or "";
        Format = " (" .. Format .. ")" else Format = "" end
      
      
     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 ~= nil and Chapter ~= "" ) and ( ChapterLink and "" < ChapterLink ) then  
     if is_set(Chapter) and is_set(ChapterLink) then  
         Chapter = "[[" .. ChapterLink .. "|" .. Chapter .. "]]";
         Chapter = "[[" .. ChapterLink .. "|" .. Chapter .. "]]";
     end
     end
     if ( Periodical and "" < Periodical ) and (Title ~= nil and Title ~= "" ) then
     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 ~= "" and Chapter == "" then
     if is_set(TransChapter) then
        TransError = " " .. seterror( 'trans_missing_chapter' );
        if not is_set(Chapter) then
            TransError = " " .. seterror( 'trans_missing_chapter' );
        else
            TransChapter = " " .. TransChapter;
        end
     end
     end
      
      
     if TransChapter ~= "" and Chapter ~= "" then TransChapter = " " .. TransChapter; end
     Chapter = Chapter .. TransChapter;
    Chapter = Chapter .. TransChapter
      
      
     if Chapter ~= "" then
     if is_set(Chapter) then
         if ( ChapterLink == nil ) then
         if not is_set(ChapterLink) then
             if ( ChapterURL and "" < ChapterURL ) then              
             if is_set(ChapterURL) then
                 Chapter = externallink( ChapterURL, Chapter ) .. TransError;
                 Chapter = externallink( ChapterURL, Chapter ) .. TransError;
                 if URL == nil or URL == "" then
                 if not is_set(URL) then
                     Chapter = Chapter .. Format;
                     Chapter = Chapter .. Format;
                     Format = "";
                     Format = "";
                 end
                 end
             elseif ( URL and "" < URL ) then  
             elseif is_set(URL) then  
                 Chapter = externallink( URL, Chapter ) .. TransError .. Format;
                 Chapter = externallink( URL, Chapter ) .. TransError .. Format;
                 URL = nil
                 URL = "";
                 Format = ""
                 Format = "";
             else
             else
                 Chapter = Chapter .. TransError;
                 Chapter = Chapter .. TransError;
             end             
             end             
         elseif ChapterURL ~= nil and ChapterURL ~= "" then
         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 ~= nil and ChapterURL ~= "" then
     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 "" < TitleLink ) then
     if is_set(TitleLink) and is_set(Title) then
        if ( Title and "" < Title ) then
        Title = "[[" .. TitleLink .. "|" .. Title .. "]]"
            Title = "[[" .. TitleLink .. "|" .. Title .. "]]"  
        end
     end
     end
 
   
     if ( Periodical and "" < Periodical ) then
     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 == "web"
     elseif inArray(config.CitationClass, {"web","news","pressrelease"}) and
            or config.CitationClass == "news"  
             not is_set(Chapter) then
            or config.CitationClass == "pressrelease" ) and  
             Chapter == "" then
         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
      
      
     local TransError = "";
     TransError = "";
     if TransTitle ~= "" and Title == "" then
     if is_set(TransTitle) then
        TransError = " " .. seterror( 'trans_missing_title' );
        if not is_set(Title) then
            TransError = " " .. seterror( 'trans_missing_title' );
        else
            TransTitle = " " .. TransTitle;
        end
     end
     end
      
      
     if TransTitle ~= "" and Title ~= "" then TransTitle = " " .. TransTitle; end
     Title = Title .. TransTitle;
    Title = Title .. TransTitle
      
      
     if Title ~= "" then
     if is_set(Title) then
         if ( TitleLink == nil and URL and "" < URL ) then  
         if not is_set(TitleLink) and is_set(URL) then  
             Title = externallink( URL, Title ) .. TransError .. Format       
             Title = externallink( URL, Title ) .. TransError .. Format       
             URL = nil
             URL = "";
             Format = ''
             Format = "";
         else
         else
             Title = Title .. TransError;
             Title = Title .. TransError;
         end
         end
     end
     end
 
   
     if ( Place ~= nil and Place ~= "" ) then
     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.message_list['written']:lower(), {Place} ) .. sepc .. " ";
             Place = " " .. substitute( cfg.messages['written']:lower(), {Place} ) .. sepc .. " ";
         end          
         end
    else
        Place = "";
     end
     end
      
      
     if ( Conference ~= nil and Conference ~="" ) then
     if is_set(Conference) then
         if ( ConferenceURL ~= nil ) then
         if is_set(ConferenceURL) then
             Conference = externallink( ConferenceURL, Conference );
             Conference = externallink( ConferenceURL, Conference );
         end
         end
         Conference = " " .. Conference
         Conference = " " .. Conference
     elseif ConferenceURL ~= nil and ConferenceURL ~= "" then
     elseif is_set(ConferenceURL) then
         Conference = " " .. externallink( ConferenceURL );
         Conference = " " .. externallink( ConferenceURL, nil, ConferenceURLorigin );
    else
        Conference = ""
     end
     end
     if ( nil ~= Position or nil ~= Page or nil ~= Pages ) then At = nil end
      
     if ( nil == Position and "" ~= Position ) then
     if not is_set(Position) then
         local Minutes = A['Minutes'];
         local Minutes = A['Minutes'];
         if ( nil ~= Minutes ) then
         if is_set(Minutes) then
             Position = " " .. Minutes .. " " .. cfg.message_list['minutes'];
             Position = " " .. Minutes .. " " .. cfg.messages['minutes'];
         else
         else
             local Time = A['Time'];
             local Time = A['Time'];
             if ( nil ~= Time ) then
             if is_set(Time) then
                 local TimeCaption = A['TimeCaption']
                 local TimeCaption = A['TimeCaption']
                 if TimeCaption == nil then
                 if not is_set(TimeCaption) then
                     TimeCaption = cfg.message_list['event'];
                     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;
            else
                Position = ""
             end
             end
         end
         end
     else
     else
         Position = " " .. Position
         Position = " " .. Position;
        At = '';
     end
     end
     if ( nil == Page or "" == Page ) then  
   
        Page = ""
     if not is_set(Page) then
         if ( nil == Pages or "" == Pages) then  
         if is_set(Pages) then
             Pages = ""
             if is_set(Periodical) and
        elseif ( Periodical ~= nil and Periodical ~= "" and
                not inArray(config.CitationClass, {"encyclopaedia","web","book","news"}) then
                config.CitationClass ~= "encyclopaedia" and
                Pages = ": " .. Pages;
                config.CitationClass ~= "web" and
             elseif tonumber(Pages) ~= nil then
                config.CitationClass ~= "book" and
                Pages = sepc .." " .. PPrefix .. Pages;
                config.CitationClass ~= "news") then
             else
            Pages = ": " .. Pages
                Pages = sepc .." " .. PPPrefix .. Pages;
        else
             if ( tonumber(Pages) ~= nil ) then
              Pages = sepc .." " .. PPrefix .. Pages
             else Pages = sepc .." " .. PPPrefix .. Pages
             end
             end
         end
         end
     else
     else
        Pages = ""
         if is_set(Periodical) and
         if ( Periodical ~= nil and Periodical ~= "" and
            not inArray(config.CitationClass, {"encyclopaedia","web","book","news"}) then
            config.CitationClass ~= "encyclopaedia" and
             Page = ": " .. Page;
            config.CitationClass ~= "web" and
            config.CitationClass ~= "book" and
            config.CitationClass ~= "news") then
             Page = ": " .. Page
         else
         else
             Page = sepc .." " .. PPrefix .. Page
             Page = sepc .." " .. PPrefix .. Page;
         end
         end
     end
     end
     if ( At ~= nil and At ~="") then At = sepc .. " " .. At
      
    else At = "" end
    At = is_set(At) and (sepc .. " " .. At) or "";
    if ( Coauthors == nil ) then Coauthors = "" end
     Others = is_set(Others) and (sepc .. " " .. Others) or "";
     if ( Others ~= nil and Others ~="" ) then
     TitleType = is_set(TitleType) and (" (" .. TitleType .. ")") or "";
        Others = sepc .. " " .. Others else Others = "" end
     TitleNote = is_set(TitleNote) and (sepc .. " " .. TitleNote) or "";
     if ( TitleType ~= nil and TitleType ~="" ) then
     Language = is_set(Language) and (" " .. wrap( 'language', Language )) or "";
        TitleType = " (" .. TitleType .. ")" else TitleType = "" end
     Edition = is_set(Edition) and (" " .. wrap( 'edition', Edition )) or "";
     if ( TitleNote ~= nil and TitleNote ~="" ) then
    Issue = is_set(Issue) and (" (" .. Issue .. ")") or "";
        TitleNote = sepc .. " " .. TitleNote else TitleNote = "" end
     Series = is_set(Series) and (sepc .. " " .. Series) or "";
     if ( Language ~= nil and Language ~="" ) then
    OrigYear = is_set(OrigYear) and (" [" .. OrigYear .. "]") or "";
        Language = " " .. wrap( 'language', Language ) else Language = "" end
    Agency = is_set(Agency) and (sepc .. " " .. Agency) or "";
     if ( Edition ~= nil and Edition ~="" ) then
   
        Edition = " " .. wrap( 'edition', Edition ) else Edition = "" end
     if is_set(Volume) then
     if ( Volume ~= nil and Volume ~="" )
     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
     else Volume = "" end
     end
     if ( Issue ~= nil and Issue ~="" ) then
      
        Issue = " (" .. Issue .. ")" else Issue = "" end
    if ( Series ~= nil and Series ~="" ) then
        Series = sepc .. " " .. Series else Series = "" end
    if ( OrigYear ~= nil and OrigYear ~="" ) then
        OrigYear = " [" .. OrigYear .. "]" else OrigYear = "" end
    if ( Agency ~= nil and Agency ~="" ) then
        Agency = sepc .. " " .. Agency else Agency = "" end
     ------------------------------------ totally unrelated data
     ------------------------------------ totally unrelated data
     if ( Date ~= nil ) then Date = Date else Date = "" end
     if is_set(Via) then Via = " " .. wrap( 'via', Via ); end
    if ( Via ~= nil and Via ~="" ) then
     if is_set(AccessDate) then
        Via = " " .. wrap( 'via', Via ) else Via = "" end
        local retrv_text = " " .. cfg.messages['retrieved']
     if ( AccessDate ~= nil and AccessDate ~="" )
        if (sepc ~= ".") then retrv_text = retrv_text:lower() end
    then local retrv_text = " " .. cfg.message_list['retrieved']
        AccessDate = '<span class="reference-accessdate">' .. sepc
        if (sepc ~= ".") then retrv_text = retrv_text:lower() end
            .. substitute( retrv_text, {AccessDate} ) .. '</span>'
        AccessDate = '<span class="reference-accessdate">' .. sepc
     end
            .. substitute( retrv_text, {AccessDate} ) .. '</span>'
   
     else AccessDate = "" end
     if is_set(SubscriptionRequired) then
     if ( SubscriptionRequired ~= nil and
         SubscriptionRequired = sepc .. " " .. cfg.messages['subscription'];
        SubscriptionRequired ~= "" ) then
         SubscriptionRequired = sepc .. " " .. cfg.message_list['subscription'];
    else
        SubscriptionRequired = ""
     end
     end
     if ( ID ~= nil and ID ~="") then ID = sepc .." ".. ID else ID="" end
   
 
     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 ~= nil and URL ~="") then
     if is_set(URL) then
         URL = " " .. externallink( URL );
         URL = " " .. externallink( URL, nil, URLorigin );
    else
        URL = ""
     end
     end


     if ( Quote and Quote ~="" ) then  
     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 = "";
     else
     elseif PostScript:lower() == "none" then
        if ( PostScript == nil) then PostScript = "" end
         PostScript = "";
         Quote = ""  
     end
     end
      
      
     local Archived
     local Archived
     if ( nil ~= ArchiveURL and "" ~= ArchiveURL ) then
     if is_set(ArchiveURL) then
         if ( ArchiveDate == nil or ArchiveDate =="" ) then
         if not is_set(ArchiveDate) then
             ArchiveDate = seterror('archive_missing_date');
             ArchiveDate = seterror('archive_missing_date');
         end
         end
         if ( "no" == DeadURL ) then
         if "no" == DeadURL then
             local arch_text = cfg.message_list['archived'];
             local arch_text = cfg.messages['archived'];
             if (sepc ~= ".") then arch_text = arch_text:lower() end
             if sepc ~= "." then arch_text = arch_text:lower() end
             Archived = sepc .. " " .. substitute( cfg.message_list['archived-not-dead'],
             Archived = sepc .. " " .. substitute( cfg.messages['archived-not-dead'],
                 { externallink( ArchiveURL, arch_text ), ArchiveDate } );
                 { externallink( ArchiveURL, arch_text ), ArchiveDate } );
             if OriginalURL == nil or OriginalUrl == '' then
             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
             if OriginalURL ~= nil and OriginalURL ~= '' then
             local arch_text = cfg.messages['archived-missing'];
                local arch_text = cfg.message_list['archived-dead'];
            if sepc ~= "." then arch_text = arch_text:lower() end
                if (sepc ~= ".") then arch_text = arch_text:lower() end
            Archived = sepc .. " " .. substitute( arch_text,  
                Archived = sepc .. " " .. substitute( arch_text,
                 { seterror('archive_missing_url'), ArchiveDate } );
                    { externallink( OriginalURL, cfg.message_list['original'] ), ArchiveDate } );
            else
                 local arch_text = cfg.message_list['archived-missing'];
                if (sepc ~= ".") then arch_text = arch_text:lower() end
                Archived = sepc .. " " .. substitute( arch_text,
                    { seterror('archive_missing_url'), ArchiveDate } );
            end               
         end
         end
     else
     else
         Archived = ""
         Archived = ""
     end
     end
   
     local Lay
     local Lay
     if ( nil ~= LaySummary and "" ~= LaySummary ) then
     if is_set(LayURL) then
         if ( LayDate ~= nil ) then LayDate = " (" .. LayDate .. ")" else LayDate = "" end
         if is_set(LayDate) then LayDate = " (" .. LayDate .. ")" end
         if ( LaySource ~= nil ) then  
         if is_set(LaySource) then  
             LaySource = " &ndash; ''" .. safeforitalics(LaySource) .. "''"  
             LaySource = " &ndash; ''" .. safeforitalics(LaySource) .. "''";
         else  
         else
             LaySource = ""  
             LaySource = "";
         end
         end
         if sepc == '.' then
         if sepc == '.' then
             Lay = sepc .. " " .. externallink( LaySummary, cfg.message_list['lay summary'] ) .. LaySource .. LayDate
             Lay = sepc .. " " .. externallink( LayURL, cfg.messages['lay summary'] ) .. LaySource .. LayDate
         else
         else
             Lay = sepc .. " " .. externallink( LaySummary, cfg.message_list['lay summary']:lower() ) .. LaySource .. LayDate
             Lay = sepc .. " " .. externallink( LayURL, cfg.messages['lay summary']:lower() ) .. LaySource .. LayDate
         end             
         end             
     else
     else
         Lay = ""
         Lay = "";
     end
     end
     if ( nil ~= Transcript and "" ~= Transcript ) then
   
         if ( TranscriptURL ~= nil ) then Transcript = externallink( TranscriptURL, Transcript ) end
     if is_set(Transcript) then
     elseif TranscriptURL ~= nil and TranscriptURL ~= "" then
         if is_set(TranscriptURL) then Transcript = externallink( TranscriptURL, Transcript ); end
         Transcript = externallink( TranscriptURL )    
     elseif is_set(TranscriptURL) then
    else
         Transcript = externallink( TranscriptURL, nil, TranscriptURLorigin );
        Transcript = ""
     end
     end
     local Publisher = ""
   
     if ( Periodical and Periodical ~= "" and
     local Publisher;
        config.CitationClass ~= "encyclopaedia" and
     if is_set(Periodical) and
        config.CitationClass ~= "web" and
        not inArray(config.CitationClass, {"encyclopaedia","web","pressrelease"}) then
        config.CitationClass ~= "pressrelease" ) then
         if is_set(PublisherName) then
         if ( PublisherName ~= nil and PublisherName ~="" ) then
             if is_set(PublicationPlace) then
             if (PublicationPlace ~= nil and PublicationPlace ~= '') then
                 Publisher = PublicationPlace .. ": " .. PublisherName;
                 Publisher = PublicationPlace .. ": " .. PublisherName;
             else
             else
                 Publisher = PublisherName;   
                 Publisher = PublisherName;   
             end          
             end
         elseif (PublicationPlace ~= nil and PublicationPlace ~= '') then  
         elseif is_set(PublicationPlace) then
             Publisher= PublicationPlace;
             Publisher= PublicationPlace;
         else  
         else  
             Publisher = "";
             Publisher = "";
         end
         end
         if ( PublicationDate and PublicationDate ~="" ) then
         if is_set(PublicationDate) then
             if Publisher ~= '' then
             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 ~= "" then
         if is_set(Publisher) then
             Publisher = " (" .. Publisher .. ")";
             Publisher = " (" .. Publisher .. ")";
         end
         end
     else
     else
         if ( PublicationDate and PublicationDate ~="" ) then
         if is_set(PublicationDate) then
             PublicationDate = " (" .. wrap( 'published', PublicationDate ) .. ")"
             PublicationDate = " (" .. wrap( 'published', PublicationDate ) .. ")";
        else
            PublicationDate = ""
         end
         end
         if ( PublisherName ~= nil and PublisherName ~="" ) then
         if is_set(PublisherName) then
             if (PublicationPlace ~= nil and PublicationPlace ~= '') then
             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 ~= nil and PublicationPlace ~= '') then  
         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 ~= nil and Periodical ~="" ) then  
     if is_set(Periodical) then
         if ( Title and Title ~= "" ) or ( TitleNote and TitleNote ~= "" ) then  
         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
     else Periodical = "" 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 ( ( (config.CitationClass == "journal") or (config.CitationClass == "citation") and
     if inArray(config.CitationClass, {"journal","citation"}) and is_set(Periodical) then
        Periodical ~= "" ) then
         if is_set(Others) then Others = Others .. sepc .. " " end
         if (Others ~= "") then Others = Others .. sepc .. " " end
         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 ( "" ~= Authors ) then
     if is_set(Authors) then
         if (Coauthors ~= "")  
         if is_set(Coauthors) then
          then Authors = Authors .. A['AuthorSeparator'] .. " " .. Coauthors
            Authors = Authors .. A['AuthorSeparator'] .. " " .. Coauthors
         end
         end
         if ( "" ~= Date )
         if is_set(Date) then
          then Date = " ("..Date..")" .. OrigYear .. sepc .. " "
            Date = " ("..Date..")" .. OrigYear .. sepc .. " "
          else
        elseif string.sub(Authors,-1,-1) == sepc then
            if ( string.sub(Authors,-1,-1) == sepc) --check end character
            Authors = Authors .. " "
              then Authors = Authors .. " "
        else
              else Authors = Authors .. sepc .. " "
            Authors = Authors .. sepc .. " "
            end
         end
         end
         if ( "" ~= Editors) then
         if is_set(Editors) then
             local in_text = " in "
             local in_text = " " .. cfg.messages['in'] .. " "
             if (sepc == '.') then in_text = " In " end
             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 ( "" ~= Editors) then
     elseif is_set(Editors) then
         if ( "" ~= Date ) then
         if is_set(Date) then
             if EditorCount <= 1 then
             if EditorCount <= 1 then
                 Editors = Editors .. ", " .. cfg.message_list['editor'];
                 Editors = Editors .. ", " .. cfg.messages['editor'];
             else
             else
                 Editors = Editors .. ", " .. cfg.message_list['editors'];
                 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.message_list['editor'] .. ")" .. sepc .. " "
                 Editors = Editors .. " (" .. cfg.messages['editor'] .. ")" .. sepc .. " "
             else
             else
                 Editors = Editors .. " (" .. cfg.message_list['editors'] .. ")" .. sepc .. " "
                 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 ( "" ~= Date ) then
         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 -- endif ""~=Date
         end
         if ( config.CitationClass=="journal" and Periodical ) then
         if config.CitationClass=="journal" and is_set(Periodical) then
          text = safejoin( {Chapter, Place, tcommon}, sepc );
            text = safejoin( {Chapter, Place, tcommon}, sepc );
          text = safejoin( {text, pgtext, Date, idcommon}, sepc );
            text = safejoin( {text, pgtext, Date, idcommon}, sepc );
         else
         else
          text = safejoin( {Chapter, Place, tcommon, Date}, sepc );
            text = safejoin( {Chapter, Place, tcommon, Date}, sepc );
          text = safejoin( {text, pgtext, idcommon}, sepc );
            text = safejoin( {text, pgtext, idcommon}, sepc );
         end
         end
     end
     end
      
      
     if PostScript ~= '' and PostScript ~= nil and PostScript ~= sepc then
     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 == nil ) then
     if not is_set(Year) then
         if ( DateIn ~= nil and DateIn ~= "" ) then  
         if is_set(DateIn) then
             Year = selectyear( DateIn )
             Year = selectyear( DateIn );
         elseif( PublicationDate ~= nil and PublicationDate ~= "" ) then
         elseif is_set(PublicationDate) then
             Year = selectyear( PublicationDate )
             Year = selectyear( PublicationDate );
        else
            Year = ""
         end
         end
     end
     end
     local classname = "citation"
   
     if ( config.CitationClass ~= "citation" )
     local options = {};
      then classname = "citation " .. (config.CitationClass or "") end
   
     local options = { class=classname }
     if is_set(config.CitationClass) and config.CitationClass ~= "citation" then
     if ( Ref ~= nil ) then  
        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 ( "" ~= Authors ) then
             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 ( "" ~= Editors ) then
             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 ~= nil then  
     if is_set(options.id) then  
         text = '<span id="' .. wikiescape(options.id) ..'" class="' .. wikiescape(options.class) .. '">' .. text .. "</span>";
         text = '<span id="' .. mw.uri.anchorEncode(options.id) ..'" class="' .. mw.text.nowiki(options.class) .. '">' .. text .. "</span>";
     else
     else
         text = '<span class="' .. wikiescape(options.class) .. '">' .. text .. "</span>";
         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="' .. wikiescape(OCinStitle) .. '" class="Z3988">' .. empty_span .. '</span>';
     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] ~= nil and v[1] ~= "" then  
             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 == "" or no_tracking_cats == "no" or
     if inArray(no_tracking_cats, {"", "no", "false", "n"}) then
            no_tracking_cats == "false" or no_tracking_cats == "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 k == 'postscript' then
         elseif args[k] ~= nil or (k == 'postscript') then
            args[k] = v;
        end       
    end   
 
    local config = {};
    for k, v in pairs( frame.args ) do
        config[k] = v;
        if args[k] == nil and (v ~= '' or k == 'postscript') then
             args[k] = v;
             args[k] = v;
         end         
         end         
Anonymous user