पटलम्:Citation/CS1

"इस मॉड्यूल हेतु प्रलेख पटलम्:Citation/CS1/doc पर बनाया जा सकता है"

local z = {    error_categories = {};    error_ids = {};    message_tail = {};}-- Include translation message hooks, ID and error handling configuration settings.local cfg = mw.loadData( 'Module:Citation/CS1/Configuration' );-- Contains a list of all recognized parameterslocal whitelist = mw.loadData( 'Module:Citation/CS1/Whitelist' );-- Whether variable is set or notfunction is_set( var )    return not (var == nil or var == '');end-- First set variable or nil if nonefunction first_set(...)    local list = {...};    for _, var in pairs(list) do        if is_set( var ) then            return var;        end    endend-- Whether needle is in haystackfunction 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    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-- Wraps a string using a message_list configuration taking one argumentfunction wrap( key, str, lower )    if not is_set( str ) then        return "";    elseif inArray( key, { 'italic-title', 'trans-italic-title' } ) then        str = safeforitalics( str );    end    if lower == true then        return substitute( cfg.messages[key]:lower(), {str} );    else        return substitute( cfg.messages[key], {str} );    end        end--[[Argument wrapper.  This function provides support for argument mapping defined in the configuration file so that multiple namescan be transparently aliased to single internal variable.]]function argument_wrapper( args )    local origin = {};        return setmetatable({        ORIGIN = function( self, k )            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;            end                        local args, list, v = args, cfg.aliases[k];                        if type( list ) == 'table' then                v, origin[k] = selectone( args, list, 'redundant_parameters' );                if origin[k] == nil then                    origin[k] = ''; -- Empty string, not nil                end            elseif list ~= nil then                v, origin[k] = args[list], list;            else                -- maybe let through instead of raising an error?                -- v, origin[k] = args[k], k;                error( cfg.messages['unknown_argument_map'] );            end                        -- Empty strings, not nil;            if v == nil then                v = cfg.defaults[k] or '';                origin[k] = '';            end                        tbl = rawset( tbl, k, v );            return v;        end,    });end-- Checks that parameter name is valid using the whitelistfunction validate( name )    name = tostring( name );        -- Normal arguments    if whitelist.basic_arguments[ name ] then        return true;    end        -- Arguments with numbers in them    name = name:gsub( "%d+", "#" );    if whitelist.numbered_arguments[ name ] then        return true;    end        -- Not found, argument not supported.    return falseend-- Formats a comment for error trappingfunction errorcomment( content, hidden )    return wrap( hidden and 'hidden-error' or 'visible-error', content );end--[[Sets an error condition and returns the appropriate error message.  The actual placementof the error message in the output is the responsibility of the calling function.]]function seterror( error_id, arguments, raw, prefix, suffix )    local error_state = cfg.error_conditions[ error_id ];        prefix = prefix or "";    suffix = suffix or "";        if error_state == nil then        error( cfg.messages['undefined_error'] );    elseif is_set( error_state.category ) then        table.insert( z.error_categories, error_state.category );    end        local message = substitute( error_state.message, arguments );        message = message .. " ([[" .. cfg.messages['help page link'] ..         "#" .. error_state.anchor .. "|" ..        cfg.messages['help page label'] .. "]])";        z.error_ids[ error_id ] = true;    if inArray( error_id, { 'bare_url_missing_title', 'trans_missing_title' } )            and z.error_ids['citation_missing_title'] then        return '', false;    end        message = table.concat({ prefix, message, suffix });        if raw == true then        return message, error_state.hidden;    end                    return errorcomment( message, error_state.hidden );end-- Formats a wiki style external linkfunction externallinkid(options)    local url_string = options.id;    if options.encode == true or options.encode == nil then        url_string = mw.uri.encode( url_string );    end    return mw.ustring.format( '[[%s|%s]]%s[%s%s%s %s]',        options.link, options.label, options.separator or "&nbsp;",        options.prefix, url_string, options.suffix or "",        mw.text.nowiki(options.id)    );end-- Formats a wiki style internal linkfunction internallinkid(options)    return mw.ustring.format( '[[%s|%s]]%s[[%s%s%s|%s]]',        options.link, options.label, options.separator or "&nbsp;",        options.prefix, options.id, options.suffix or "",        mw.text.nowiki(options.id)    );end-- Format an external link with error checkingfunction externallink( URL, label, source )    local error_str = "";    if not is_set( label ) then        label = URL;        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    if not checkurl( URL ) then        error_str = seterror( 'bad_url', {}, false, " " ) .. error_str;    end    return table.concat({ "[", URL, " ", safeforurl( label ), "]", error_str });end-- Formats a link to Amazonfunction amazon(id, domain)    if not is_set(domain) then         domain = "com"    elseif ( "jp" == domain or "uk" == domain ) then        domain = "co." .. domain    end    local handler = cfg.id_handlers['ASIN'];    return externallinkid({link = handler.link,        label=handler.label , prefix="//www.amazon."..domain.."/dp/",id=id,        encode=handler.encode, separator = handler.separator})end--[[Formats a PMC and checks for embargoed articles.  The embargo parameter takes a date for a value. If the embargo date is in the futuethe PMC identifier will not be linked to the article.  If the embargo specifies a date in the past, or if it is empty or omitted, thenthe PMC identifier is linked to the article through the link at cfg.id_handlers['PMC'].link.The {{citation/core}} version of {{cite journal}} links the citation title (if url parameter is empty) when embargo date is in the pastor when embargo parameter is missing or empty. That behavior is inconsistent with the behavior of other identifiers used in CS1 and isnot supported here.]]function pmc(id, embargo)local handler = cfg.id_handlers['PMC'];    local text;if is_set(embargo) thenlocal lang = mw.getContentLanguage();local good1, embargo_date, good2, todays_date;good1, embargo_date = pcall( lang.formatDate, lang, 'U', embargo );good2, todays_date = pcall( lang.formatDate, lang, 'U' );if good1 and good2 and tonumber( embargo_date ) < tonumber( todays_date ) then--if embargo date is in the past thentext = externallinkid({link = handler.link, label = handler.label,--ok to link to articleprefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})elsetext="[[" .. handler.link .. "|" .. handler.label .. "]]:" .. handler.separator .. id;--still embargoed so no external linkendelsetext = externallinkid({link = handler.link, label = handler.label,--no embargo date, ok to link to articleprefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})endreturn textend-- Formats a DOI and checks for DOI errors.function doi(id, inactive)    local cat = ""    local handler = cfg.id_handlers['DOI'];        local text;    if is_set(inactive) then        text = "[[" .. handler.link .. "|" .. handler.label .. "]]:" .. id;        table.insert( z.error_categories, "Pages with DOIs inactive since " .. selectyear(inactive) );                inactive = " (" .. cfg.messages['inactive'] .. " " .. inactive .. ")"     else         text = externallinkid({link = handler.link, label = handler.label,            prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})        inactive = ""     end    if ( string.sub(id,1,3) ~= "10." ) then              cat = seterror( 'bad_doi' );    end    return text .. inactive .. cat end-- Formats an OpenLibrary link, and checks for associated errors.function openlibrary(id)    local code = id:sub(-1,-1)    local handler = cfg.id_handlers['OL'];    if ( code == "A" ) then        return externallinkid({link=handler.link, label=handler.label,            prefix="http://openlibrary.org/authors/OL",id=id, separator=handler.separator,            encode = handler.encode})    elseif ( code == "M" ) then        return externallinkid({link=handler.link, label=handler.label,            prefix="http://openlibrary.org/books/OL",id=id, separator=handler.separator,            encode = handler.encode})    elseif ( code == "W" ) then        return externallinkid({link=handler.link, label=handler.label,            prefix= "http://openlibrary.org/works/OL",id=id, separator=handler.separator,            encode = handler.encode})    else        return externallinkid({link=handler.link, label=handler.label,            prefix= "http://openlibrary.org/OL",id=id, separator=handler.separator,            encode = handler.encode}) ..             ' ' .. seterror( 'bad_ol' );    endend--[[Validate and format an issn.  This code fixes the case where an editor has included an ISSN in the citation but has separated the two groups of fourdigits with a space.  When that condition occurred, the resulting link looked like this:|issn=0819 4327 gives: [http://www.worldcat.org/issn/0819 4327 0819 4327]  -- can't have spaces in an external linkThis code now prevents that by inserting a hyphen at the issn midpoint.  It also validates the issn for length and makes sure that the checkdigit agreeswith the calculated value.  Incorrect length (8 digits), characters other than 0-9 and X, or checkdigit / calculated value mismatch will all cause a check issnerror message.  The issn is always displayed with a hyphen, even if the issn was given as a single group of 8 digits.]]function issn(id)local clean_issn;local issn_copy = id;-- save a copy of unadulterated issn; use this version for display if issn does not validatelocal handler = cfg.id_handlers['ISSN'];local temp = 0;local text;local valid_issn = true;id=id:gsub( "[%s-–]", "" );-- strip spaces, hyphens, and ndashes from the issnclean_issn=string.sub( id, 1, 4 ) .. "-" .. string.sub( id, 5 );-- make a copy with a hyphen after 4 digits; use this version for display if issn validatesif 8 ~= id:len() or nil == id:match( "^%d*X?$" ) then-- validate the issn: 8 didgits long, containing only 0-9 or X in the last positionvalid_issn=false;-- wrong length or improper characterelseid = { id:byte(1, 8) };-- table of individual bytesfor i, v in ipairs( id ) do-- loop through all of the byte an calculate the checksumif v == string.byte( "X" ) then-- if checkdigit is Xtemp = temp + 10*( 9 - i );-- it represents 10 decimalelsetemp = temp + tonumber( string.char(v) )*(9-i);endendvalid_issn = temp % 11 == 0;-- checksum must be zero for valid issnendif true == valid_issn thenid = clean_issn;-- if valid, use the cleaned-up version for the displayelseid = issn_copy;-- if not valid, use the show the invalid issn with error messageendtext = externallinkid({link = handler.link, label = handler.label,prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode}) if false == valid_issn thentext = text .. ' ' .. seterror( 'bad_issn' )-- add an error message if the issn is invalidend return textend--[[Determines whether an URL string is validAt present the only check is whether the string appears to be prefixed with a URI scheme.  It is not determined whether the URI scheme is valid or whether the URL is otherwise well formed.]]function checkurl( url_str )    -- Protocol-relative or URL scheme    return url_str:sub(1,2) == "//" or url_str:match( "^[^/]*:" ) ~= nil;end-- Removes irrelevant text and dashes from ISBN number-- Similar to that used for Special:BookSourcesfunction cleanisbn( isbn_str )    return isbn_str:gsub( "[^-0-9X]", "" );end-- Determines whether an ISBN string is validfunction checkisbn( isbn_str )    isbn_str = cleanisbn( isbn_str ):gsub( "-", "" );    local len = isbn_str:len();     if len ~= 10 and len ~= 13 then        return false;    end     local temp = 0;    if len == 10 then        if isbn_str:match( "^%d*X?$" ) == nil then return false; end        isbn_str = { isbn_str:byte(1, len) };        for i, v in ipairs( isbn_str ) do            if v == string.byte( "X" ) then                temp = temp + 10*( 11 - i );            else                temp = temp + tonumber( string.char(v) )*(11-i);            end        end        return temp % 11 == 0;    else        if isbn_str:match( "^%d*$" ) == nil then return false; end        isbn_str = { isbn_str:byte(1, len) };        for i, v in ipairs( isbn_str ) do            temp = temp + (3 - 2*(i % 2)) * tonumber( string.char(v) );        end        return temp % 10 == 0;    endend-- Gets the display text for a wikilink like [[A|B]] or [[B]] gives Bfunction removewikilink( str )    return (str:gsub( "%[%[([^%[%]]*)%]%]", function(l)        return l:gsub( "^[^|]*|(.*)$", "%1" ):gsub("^%s*(.-)%s*$", "%1");    end));end-- Escape sequences for content that will be used for URL descriptionsfunction safeforurl( str )    if str:match( "%[%[.-%]%]" ) ~= nil then         table.insert( z.message_tail, { seterror( 'wikilink_in_url', {}, true ) } );    end        return str:gsub( '[%[%]\n]', {            ['['] = '&#91;',        [']'] = '&#93;',        ['\n'] = ' ' } );end-- Converts a hyphen to a dashfunction hyphentodash( str )    if not is_set(str) or str:match( "[%[%]{}<>]" ) ~= nil then        return str;    end        return str:gsub( '-', '–' );end-- Protects a string that will be wrapped in wiki italic markup '' ... ''function safeforitalics( str )    --[[ Note: We can not use <i> for italics, as the expected behavior for    italics specified by ''...'' in the title is that they will be inverted    (i.e. unitalicized) in the resulting references.  In addition, <i> and ''    tend to interact poorly under Mediawiki's HTML tidy. ]]        if not is_set(str) then        return str;    else        if str:sub(1,1) == "'" then str = "<span />" .. str; end        if str:sub(-1,-1) == "'" then str = str .. "<span />"; end                -- Remove newlines as they break italics.        return str:gsub( '\n', ' ' );    endend--[[Joins a sequence of strings together while checking for duplicate separationcharacters.]]function safejoin( tbl, duplicate_char )    --[[    Note: we use string functions here, rather than ustring functions.        This has considerably faster performance and should work correctly as     long as the duplicate_char is strict ASCII.  The strings    in tbl may be ASCII or UTF8.    ]]        local str = '';    local comp = '';    local end_chr = '';    local trim;    for _, value in ipairs( tbl ) do        if value == nil then value = ''; end                if str == '' then            str = value;        elseif value ~= '' then            if value:sub(1,1) == '<' then                -- Special case of values enclosed in spans and other markup.                comp = value:gsub( "%b<>", "" );            else                comp = value;            end                        if comp:sub(1,1) == duplicate_char then                trim = false;                end_chr = str:sub(-1,-1);                -- str = str .. "<HERE(enchr=" .. end_chr.. ")"                if end_chr == duplicate_char then                    str = str:sub(1,-2);                elseif end_chr == "'" then                    if str:sub(-3,-1) == duplicate_char .. "''" then                        str = str:sub(1, -4) .. "''";                    elseif str:sub(-5,-1) == duplicate_char .. "]]''" then                        trim = true;                    elseif str:sub(-4,-1) == duplicate_char .. "]''" then                        trim = true;                    end                elseif end_chr == "]" then                    if str:sub(-3,-1) == duplicate_char .. "]]" then                        trim = true;                    elseif str:sub(-2,-1) == duplicate_char .. "]" then                        trim = true;                    end                elseif end_chr == " " then                    if str:sub(-2,-1) == duplicate_char .. " " then                        str = str:sub(1,-3);                    end                end                if trim then                    if value ~= comp then                         local dup2 = duplicate_char;                        if dup2:match( "%A" ) then dup2 = "%" .. dup2; end                                                value = value:gsub( "(%b<>)" .. dup2, "%1", 1 )                    else                        value = value:sub( 2, -1 );                    end                end            end            str = str .. value;        end    end    return str;end  --[[Return the year portion of a date string, if possible.  Returns empty string if the argument can not be interpretedas a year.]]function selectyear( str )    -- Is the input a simple number?    local num = tonumber( str );     if num ~= nil and num > 0 and num < 2100 and num == math.floor(num) then        return str;    else        -- Use formatDate to interpret more complicated formats        local lang = mw.getContentLanguage();        local good, result;        good, result = pcall( lang.formatDate, lang, 'Y', str );        if good then             return result;        else            -- extract year if the date uses seasons            str=string.lower (str);            local seasons={"winter", "spring", "summer", "fall", "autumn"};            local date_string_split=mw.text.split (str, "[%s%-/–]");      -- split date string into parts; white space, hyphen, forward slash, and ndash are allowed separators            local has_season=false;                        for n,season_value in ipairs(seasons) do                -- for each season ...                for n,split_value in ipairs(date_string_split) do   -- ... loop through date string values                     if split_value == season_value then             -- does the split value match the season value?                        if has_season==false then                   -- found one. if this one is the first we've found ...                            has_season=true;                        -- ... remember that we found a season                        end                    elseif has_season==true then                    -- if split_value isn't a season, and we've previously found a season ...                        num = tonumber( split_value );              -- ... convert current split value to a number if we can                        if num ~= nil and num > 0 and num < 2100 and num == math.floor(num) then    -- if it's a suitable number                            return tostring( num );                                                 -- return it as a string                        end -- if num                    end -- if string.find                end -- for split value loop            end -- season value loop        end -- if good    end -- if numend -- selectyear-- Attempts to convert names to initials.function reducetoinitials(first)    local initials = {}    for word in string.gmatch(first, "%S+") do        table.insert(initials, string.sub(word,1,1)) -- Vancouver format does not include full stops.    end    return table.concat(initials) -- Vancouver format does not include spaces.end-- Formats a list of people (e.g. authors / editors) function listpeople(control, people)    local sep = control.sep;    local namesep = control.namesep    local format = control.format    local maximum = control.maximum    local lastauthoramp = control.lastauthoramp;    local text = {}    local etal = false;        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        if is_set(person.last) then            local mask = person.mask            local one            local sep_one = sep;            if maximum ~= nil and i > maximum then                etal = true;                break;            elseif (mask ~= nil) then                local n = tonumber(mask)                if (n ~= nil) then                    one = string.rep("&mdash;",n)                else                    one = mask;                    sep_one = " ";                end            else                one = person.last                local first = person.first                if is_set(first) then                     if ( "vanc" == format ) then first = reducetoinitials(first) end                    one = one .. namesep .. first                 end                if is_set(person.link) then one = "[[" .. person.link .. "|" .. one .. "]]" end            end            table.insert( text, one )            table.insert( text, sep_one )        end    end    local count = #text / 2;    if count > 0 then         if count > 1 and is_set(lastauthoramp) and not etal then            text[#text-2] = " & ";        end        text[#text] = nil;     end        local result = table.concat(text) -- construct list    if etal then         local etal_text = cfg.messages['et al'];        result = result .. " " .. etal_text;    end        -- if necessary wrap result in <span> tag to format in Small Caps    if ( "scap" == format ) then result =         '<span class="smallcaps" style="font-variant:small-caps">' .. result .. '</span>';    end     return result, countend-- Generates a CITEREF anchor ID.function anchorid( options )    return "CITEREF" .. table.concat( options );end-- Gets name list from the input argumentsfunction extractnames(args, list_name)    local names = {};    local i = 1;    local last;        while true do        last = selectone( args, cfg.aliases[list_name .. '-Last'], 'redundant_parameters', i );        if not is_set(last) then            -- just in case someone passed in an empty parameter            break;        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;    end    return names;end-- Populates ID table from arguments using configuration settingsfunction extractids( args )    local id_list = {};    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    return id_list;end-- Takes a table of IDs and turns it into a table of formatted ID outputs.function buildidlist( id_list, options )    local 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        -- fallback to read-only cfg        handler = setmetatable( { ['id'] = v }, fallback(k) );                if handler.mode == 'external' then            table.insert( new_list, {handler.label, externallinkid( handler ) } );        elseif handler.mode == 'internal' then            table.insert( new_list, {handler.label, internallinkid( handler ) } );        elseif handler.mode ~= 'manual' then            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 == 'PMC' then            table.insert( new_list, {handler.label, pmc( v, options.Embargo ) } );        elseif k == 'ISSN' then        table.insert( new_list, {handler.label, issn( 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            error( cfg.messages['unknown_manual_ID'] );        end    end        function comp( a, b )        return a[1] < b[1];    end        table.sort( new_list, comp );    for k, v in ipairs( new_list ) do        new_list[k] = v[2];    end        return new_list;end  -- Chooses one matching parameter from a list of parameters to consider-- Generates an error if more than one match is present.function selectone( args, possible, error_condition, index )    local value = nil;    local selected = '';    local error_list = {};        if index ~= nil then index = tostring(index); end        -- Handle special case of "#" replaced by empty string    if index == '1' then        for _, v in ipairs( possible ) do            v = v:gsub( "#", "" );            if is_set(args[v]) then                if value ~= nil and selected ~= v then                    table.insert( error_list, v );                else                    value = args[v];                    selected = v;                end            end        end            end        for _, v in ipairs( possible ) do        if index ~= nil then            v = v:gsub( "#", index );        end        if is_set(args[v]) then            if value ~= nil and selected ~=  v then                table.insert( error_list, v );            else                value = args[v];                selected = v;            end        end    end        if #error_list > 0 then        local error_str = "";        for _, k in ipairs( error_list ) do            if error_str ~= "" then error_str = error_str .. cfg.messages['parameter-separator'] end            error_str = error_str .. wrap( 'parameter', k );        end        if #error_list > 1 then            error_str = error_str .. cfg.messages['parameter-final-separator'];        else            error_str = error_str .. cfg.messages['parameter-pair-separator'];        end        error_str = error_str .. wrap( 'parameter', selected );        table.insert( z.message_tail, { seterror( error_condition, {error_str}, true ) } );    end        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--[[This is the main function foing the majority of the citationformatting.]]function citation0( config, args)    --[[     Load Input Parameters    The argment_wrapper facillitates the mapping of multiple    aliases to single internal variable.    ]]    local A = argument_wrapper( args );    local i     local PPrefix = A['PPrefix']    local PPPrefix = A['PPPrefix']    if is_set( A['NoPP'] ) then PPPrefix = "" PPrefix = "" end        -- Pick out the relevant fields from the arguments.  Different citation templates    -- define different field names for the same underlying things.        local Authors = A['Authors'];    local a = extractnames( args, 'AuthorList' );    local Coauthors = A['Coauthors'];    local Others = A['Others'];    local Editors = A['Editors'];    local e = extractnames( args, 'EditorList' );    local Year = A['Year'];    local PublicationDate = A['PublicationDate'];    local OrigYear = A['OrigYear'];    local Date = A['Date'];    local LayDate = A['LayDate'];    ------------------------------------------------- Get title data    local Title = A['Title'];    local BookTitle = A['BookTitle'];    local Conference = A['Conference'];    local TransTitle = A['TransTitle'];    local TitleNote = A['TitleNote'];    local TitleLink = A['TitleLink'];    local Chapter = A['Chapter'];    local ChapterLink = A['ChapterLink'];    local TransChapter = A['TransChapter'];    local TitleType = A['TitleType'];    local ArchiveURL = A['ArchiveURL'];    local URL = A['URL']    local URLorigin = A:ORIGIN('URL');    local ChapterURL = A['ChapterURL'];    local ChapterURLorigin = A:ORIGIN('ChapterURL');    local ConferenceURL = A['ConferenceURL'];    local ConferenceURLorigin = A:ORIGIN('ConferenceURL');    local Periodical = A['Periodical'];        if ( config.CitationClass == "encyclopaedia" ) then        if not is_set(Chapter) then            if not is_set(Title) then                Title = Periodical;                Periodical = '';            else                Chapter = Title                TransChapter = TransTitle                Title = '';                TransTitle = '';            end        end    end    local Series = A['Series'];    local Volume = A['Volume'];    local Issue = A['Issue'];    local Position = '';    local Page, Pages, At, page_type;        Page = A['Page'];    Pages = hyphentodash( A['Pages'] );    At = A['At'];        if is_set(Page) then        if is_set(Pages) or is_set(At) then            Page = Page .. " " .. seterror('extra_pages');            Pages = '';            At = '';        end    elseif is_set(Pages) then        if is_set(At) then            Pages = Pages .. " " .. seterror('extra_pages');            At = '';        end    end            local Edition = A['Edition'];    local PublicationPlace = A['PublicationPlace']    local Place = A['Place'];        if not is_set(PublicationPlace) and is_set(Place) then        PublicationPlace = Place;    end        if PublicationPlace == Place then Place = ''; end        local PublisherName = A['PublisherName'];    local RegistrationRequired = A['RegistrationRequired'];    local SubscriptionRequired = A['SubscriptionRequired'];    local Via = A['Via'];    local AccessDate = A['AccessDate'];    local ArchiveDate = A['ArchiveDate'];    local Agency = A['Agency'];    local DeadURL = A['DeadURL']    local Language = A['Language'];    local Format = A['Format'];    local Ref = A['Ref'];        local DoiBroken = A['DoiBroken'];    local ID = A['ID'];    local ASINTLD = A['ASINTLD'];    local IgnoreISBN = A['IgnoreISBN'];    local Embargo = A['Embargo'];    local ID_list = extractids( args );        local Quote = A['Quote'];    local PostScript = A['PostScript'];    local LayURL = A['LayURL'];    local LaySource = A['LaySource'];    local Transcript = A['Transcript'];    local TranscriptURL = A['TranscriptURL']     local TranscriptURLorigin = A:ORIGIN('TranscriptURL');    local sepc = A['Separator'];    local LastAuthorAmp = A['LastAuthorAmp'];    local no_tracking_cats = A['NoTracking'];    local use_lowercase = ( sepc ~= '.' );    local this_page = mw.title.getCurrentTitle();  --Also used for COinS and for language        if not is_set(no_tracking_cats) then        for k, v in pairs( cfg.uncategorized_namespaces ) do            if this_page.nsText == v then                no_tracking_cats = "true";                break;            end        end    end    -- At this point fields may be nil if they weren't specified in the template use.  We can use that fact.        -- Account for the oddity that is {{cite conference}}, before generation of COinS data.    if is_set(BookTitle) then        Chapter = Title;        ChapterLink = TitleLink;        TransChapter = TransTitle;        Title = BookTitle;        TitleLink = '';        TransTitle = '';    end    -- Account for the oddity that is {{cite episode}}, before generation of COinS data.    if config.CitationClass == "episode" then        local AirDate = A['AirDate'];        local SeriesLink = A['SeriesLink'];        local Season = A['Season'];        local SeriesNumber = A['SeriesNumber'];        local Network = A['Network'];        local Station = A['Station'];        local s, n = {}, {};        local Sep = (first_set(A["SeriesSeparator"], A["Separator"]) or "") .. " ";                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 is_set(SeriesNumber) then table.insert(s, cfg.messages["series"] .. " " .. SeriesNumber); end        if is_set(Network) then table.insert(n, Network); end        if is_set(Station) then table.insert(n, Station); end                Date = Date or AirDate;        Chapter = Title;        ChapterLink = TitleLink;        TransChapter = TransTitle;        Title = Series;        TitleLink = SeriesLink;        TransTitle = '';                Series = table.concat(s, Sep);        ID = table.concat(n, Sep);    end        -- COinS metadata (see <http://ocoins.info/>) for    -- automated parsing of citation information.    local OCinSoutput = COinS{        ['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 = '';    end    -- Now perform various field substitutions.    -- We also add leading spaces and surrounding markup and punctuation to the    -- various parts of the citation, but only when they are non-nil.    if not is_set(Authors) then        local Maximum = tonumber( A['DisplayAuthors'] );                -- Preserve old-style implicit et al.        if not is_set(Maximum) and #a == 9 then             Maximum = 8;            table.insert( z.message_tail, { seterror('implict_etal_author', {}, true ) } );        elseif not is_set(Maximum) then            Maximum = #a + 1;        end                    local control = {             sep = A["AuthorSeparator"] .. " ",            namesep = (first_set(A["AuthorNameSeparator"], A["NameSeparator"]) or "") .. " ",            format = A["AuthorFormat"],            maximum = Maximum,            lastauthoramp = LastAuthorAmp        };                -- If the coauthor field is also used, prevent ampersand and et al. formatting.        if is_set(Coauthors) then            control.lastauthoramp = nil;            control.maximum = #a + 1;        end                Authors = listpeople(control, a)     endif not is_set(Authors) and is_set(Coauthors) then-- coauthors aren't displayed if one of authors=, authorn=, or lastn= isn't specifiedtable.insert( z.message_tail, { seterror('coauthors_missing_author', {}, true) } );-- emit error messageend    local EditorCount    if not is_set(Editors) then        local Maximum = tonumber( A['DisplayEditors'] );        -- Preserve old-style implicit et al.        if not is_set(Maximum) and #e == 4 then             Maximum = 3;            table.insert( z.message_tail, { seterror('implict_etal_editor', {}, true) } );        elseif not is_set(Maximum) then            Maximum = #e + 1;        end        local control = {             sep = A["EditorSeparator"] .. " ",            namesep = (first_set(A["EditorNameSeparator"], A["NameSeparator"]) or "") .. " ",            format = A['EditorFormat'],            maximum = Maximum,            lastauthoramp = LastAuthorAmp        };        Editors, EditorCount = listpeople(control, e);    else        EditorCount = 1;    end    local Cartography = "";    local Scale = "";    if config.CitationClass == "map" then        if not is_set( Authors ) and is_set( PublisherName ) then            Authors = PublisherName;            PublisherName = "";        end        Cartography = A['Cartography'];        if is_set( Cartography ) then            Cartography = sepc .. " " .. wrap( 'cartography', Cartography, use_lowercase );        end                Scale = A['Scale'];        if is_set( Scale ) then            Scale = sepc .. " " .. Scale;        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;                local Day = A['Day']                if is_set(Day) then Date = Day .. " " .. Date end            end        end    end        if inArray(PublicationDate, {Date, Year}) then PublicationDate = ''; end    if not is_set(Date) and is_set(PublicationDate) then        Date = PublicationDate;        PublicationDate = '';    end    -- Captures the value for Date prior to adding parens or other textual transformations    local DateIn = Date;        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        if ( config.CitationClass == "web" ) then            table.insert( z.message_tail, { seterror( 'cite_web_url', {}, true ) } );        end                -- Test if accessdate is given without giving a URL        if is_set(AccessDate) then            table.insert( z.message_tail, { seterror( 'accessdate_missing_url', {}, true ) } );            AccessDate = '';        end                -- Test if format is given without giving a URL        if is_set(Format) then            Format = Format .. seterror( 'format_missing_url' );        end    end        -- Test if citation has no title    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 ) } );    end        Format = is_set(Format) and " (" .. Format .. ")" or "";        local OriginalURL = URL    DeadURL = DeadURL:lower();    if is_set( ArchiveURL ) then        if ( DeadURL ~= "no" ) then            URL = ArchiveURL            URLorigin = A:ORIGIN('ArchiveURL')        end    end        -- Format chapter / article title    if is_set(Chapter) and is_set(ChapterLink) then         Chapter = "[[" .. ChapterLink .. "|" .. Chapter .. "]]";    end    if is_set(Periodical) and is_set(Title) then        Chapter = wrap( 'italic-title', Chapter );        TransChapter = wrap( 'trans-italic-title', TransChapter );    else        Chapter = wrap( 'quoted-title', Chapter );        TransChapter = wrap( 'trans-quoted-title', TransChapter );    end        local TransError = ""    if is_set(TransChapter) then        if not is_set(Chapter) then            TransError = " " .. seterror( 'trans_missing_chapter' );        else            TransChapter = " " .. TransChapter;        end    end        Chapter = Chapter .. TransChapter;        if is_set(Chapter) then        if not is_set(ChapterLink) then            if is_set(ChapterURL) then                Chapter = externallink( ChapterURL, Chapter ) .. TransError;                if not is_set(URL) then                    Chapter = Chapter .. Format;                    Format = "";                end            elseif is_set(URL) then                 Chapter = externallink( URL, Chapter ) .. TransError .. Format;                URL = "";                Format = "";            else                Chapter = Chapter .. TransError;            end                    elseif is_set(ChapterURL) then            Chapter = Chapter .. " " .. externallink( ChapterURL, nil, ChapterURLorigin ) ..                 TransError;        else            Chapter = Chapter .. TransError;        end        Chapter = Chapter .. sepc .. " " -- with end-space    elseif is_set(ChapterURL) then        Chapter = " " .. externallink( ChapterURL, nil, ChapterURLorigin ) .. sepc .. " ";    end                -- Format main title.    if is_set(TitleLink) and is_set(Title) then        Title = "[[" .. TitleLink .. "|" .. Title .. "]]"    end        if is_set(Periodical) then        Title = wrap( 'quoted-title', Title );        TransTitle = wrap( 'trans-quoted-title', TransTitle );    elseif inArray(config.CitationClass, {"web","news","pressrelease","conference"}) and            not is_set(Chapter) then        Title = wrap( 'quoted-title', Title );        TransTitle = wrap( 'trans-quoted-title', TransTitle );    else        Title = wrap( 'italic-title', Title );        TransTitle = wrap( 'trans-italic-title', TransTitle );    end        TransError = "";    if is_set(TransTitle) then        if not is_set(Title) then            TransError = " " .. seterror( 'trans_missing_title' );        else            TransTitle = " " .. TransTitle;        end    end        Title = Title .. TransTitle;        if is_set(Title) then        if not is_set(TitleLink) and is_set(URL) then             Title = externallink( URL, Title ) .. TransError .. Format                   URL = "";            Format = "";        else            Title = Title .. TransError;        end    end        if is_set(Place) then        Place = " " .. wrap( 'written', Place, use_lowercase ) .. sepc .. " ";    end        if is_set(Conference) then        if is_set(ConferenceURL) then            Conference = externallink( ConferenceURL, Conference );        end        Conference = sepc .. " " .. Conference    elseif is_set(ConferenceURL) then        Conference = sepc .. " " .. externallink( ConferenceURL, nil, ConferenceURLorigin );    end        if not is_set(Position) then        local Minutes = A['Minutes'];        if is_set(Minutes) then            Position = " " .. Minutes .. " " .. cfg.messages['minutes'];        else            local Time = A['Time'];            if is_set(Time) then                local TimeCaption = A['TimeCaption']                if not is_set(TimeCaption) then                    TimeCaption = cfg.messages['event'];                    if sepc ~= '.' then                        TimeCaption = TimeCaption:lower();                    end                end                Position = " " .. TimeCaption .. " " .. Time;            end        end    else        Position = " " .. Position;        At = '';    end        if not is_set(Page) then        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;            end        end    else        if is_set(Periodical) and            not inArray(config.CitationClass, {"encyclopaedia","web","book","news"}) then            Page = ": " .. Page;        else            Page = sepc .." " .. PPrefix .. Page;        end    end        At = is_set(At) and (sepc .. " " .. At) or "";    Position = is_set(Position) and (sepc .. " " .. Position) or "";    if config.CitationClass == 'map' then        local Section = A['Section'];        local Inset = A['Inset'];        if first_set( Pages, Page, At ) ~= nil or sepc ~= '.' then            if is_set( Section ) then                Section = ", " .. wrap( 'section', Section, true );            end            if is_set( Inset ) then                Inset = ", " .. wrap( 'inset', Inset, true );            end        else            if is_set( Section ) then                Section = sepc .. " " .. wrap( 'section', Section, use_lowercase );                if is_set( Inset ) then                    Inset = ", " .. wrap( 'inset', Inset, true );                end            elseif is_set( Inset ) then                Inset = sepc .. " " .. wrap( 'inset', Inset, use_lowercase );            end                    end                    At = At .. Section .. Inset;            end    --[[Look in the list of iso639-1 language codes to see if the value provided in the language parameter matches one of them.  If a match is found, use that value; if not, then use the value that was provided with the language parameter.Categories are assigned in a manner similar to the {{xx icon}} templates - categorizes only mainspace citations and only when the language code is not 'en' (English).]]if is_set (Language) thenlocal name = cfg.iso639_1[Language:lower()];-- get the language name if Language parameter has a valid iso 639-1 codeif nil == name thenLanguage=" " .. wrap( 'language', Language );-- no match, use parameter's valueelseif 0 == this_page.namespace and 'en' ~= Language:lower() then--found a match; is this page main / article space and English not the language?Language=" " .. wrap( 'language', name .. '[[Category:Articles with ' .. name .. '-language external links]]' );-- in main space and not English: categorizeelseLanguage=" " .. wrap( 'language', name );--not in mainspace or language is English so don't categorizeendendelseLanguage="";-- language not specified so make sure this is an empty string;end    Others = is_set(Others) and (sepc .. " " .. Others) or "";    TitleType = is_set(TitleType) and (" (" .. TitleType .. ")") or "";    TitleNote = is_set(TitleNote) and (sepc .. " " .. TitleNote) 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        if ( mw.ustring.len(Volume) > 4 )          then Volume = sepc .." " .. Volume;          else Volume = " <b>" .. hyphentodash(Volume) .. "</b>";        end    end        ------------------------------------ totally unrelated data    --[[ Loosely mimic {{subscription required}} template; Via parameter identifies a delivery source that is not the publisher; these sources often, but not always, exist    behind a registration or paywall.  So here, we've chosen to decouple via from subscription (via has never been part of the registration required template).        Subscription implies paywall; Registration does not.  If both are used in a citation, the subscription required link note is displayed. There are no error messages for this condition.    ]]    if is_set(Via) then        Via = " " .. wrap( 'via', Via );    endif is_set(SubscriptionRequired) then        SubscriptionRequired = sepc .. " " .. cfg.messages['subscription']; --here when 'via' parameter not used but 'subscription' is    elseif is_set(RegistrationRequired) then        SubscriptionRequired = sepc .. " " .. cfg.messages['registration']; --here when 'via' and 'subscription' parameters not used but 'registration' is    end    if is_set(AccessDate) then        local retrv_text = " " .. cfg.messages['retrieved']        if (sepc ~= ".") then retrv_text = retrv_text:lower() end        AccessDate = '<span class="reference-accessdate">' .. sepc            .. substitute( retrv_text, {AccessDate} ) .. '</span>'    end        if is_set(ID) then ID = sepc .." ".. ID; end        ID_list = buildidlist( ID_list, {DoiBroken = DoiBroken, ASINTLD = ASINTLD, IgnoreISBN = IgnoreISBN, Embargo=Embargo} );    if is_set(URL) then        URL = " " .. externallink( URL, nil, URLorigin );    end    if is_set(Quote) then        if Quote:sub(1,1) == '"' and Quote:sub(-1,-1) == '"' then            Quote = Quote:sub(2,-2);        end        Quote = sepc .." " .. wrap( 'quoted-text', Quote );         PostScript = "";    elseif PostScript:lower() == "none" then        PostScript = "";    end        local Archived    if is_set(ArchiveURL) then        if not is_set(ArchiveDate) then            ArchiveDate = seterror('archive_missing_date');        end        if "no" == DeadURL then            local arch_text = cfg.messages['archived'];            if sepc ~= "." then arch_text = arch_text:lower() end            Archived = sepc .. " " .. substitute( cfg.messages['archived-not-dead'],                { externallink( ArchiveURL, arch_text ), ArchiveDate } );            if not is_set(OriginalURL) then                Archived = Archived .. " " .. seterror('archive_missing_url');                                           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            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    else        Archived = ""    end        local Lay    if is_set(LayURL) then        if is_set(LayDate) then LayDate = " (" .. LayDate .. ")" end        if is_set(LaySource) then             LaySource = " &ndash; ''" .. safeforitalics(LaySource) .. "''";        else            LaySource = "";        end        if sepc == '.' then            Lay = sepc .. " " .. externallink( LayURL, cfg.messages['lay summary'] ) .. LaySource .. LayDate        else            Lay = sepc .. " " .. externallink( LayURL, cfg.messages['lay summary']:lower() ) .. LaySource .. LayDate        end                else        Lay = "";    end        if is_set(Transcript) then        if is_set(TranscriptURL) then Transcript = externallink( TranscriptURL, Transcript ); end    elseif is_set(TranscriptURL) then        Transcript = externallink( TranscriptURL, nil, TranscriptURLorigin );    end        local Publisher;    if is_set(Periodical) and        not inArray(config.CitationClass, {"encyclopaedia","web","pressrelease"}) then        if is_set(PublisherName) then            if is_set(PublicationPlace) then                Publisher = PublicationPlace .. ": " .. PublisherName;            else                Publisher = PublisherName;              end        elseif is_set(PublicationPlace) then            Publisher= PublicationPlace;        else             Publisher = "";        end        if is_set(PublicationDate) then            if is_set(Publisher) then                Publisher = Publisher .. ", " .. wrap( 'published', PublicationDate );            else                Publisher = PublicationDate;            end        end        if is_set(Publisher) then            Publisher = " (" .. Publisher .. ")";        end    else        if is_set(PublicationDate) then            PublicationDate = " (" .. wrap( 'published', PublicationDate ) .. ")";        end        if is_set(PublisherName) then            if is_set(PublicationPlace) then                Publisher = sepc .. " " .. PublicationPlace .. ": " .. PublisherName .. PublicationDate;            else                Publisher = sepc .. " " .. PublisherName .. PublicationDate;              end                    elseif is_set(PublicationPlace) then             Publisher= sepc .. " " .. PublicationPlace .. PublicationDate;        else             Publisher = PublicationDate;        end    end        -- Several of the above rely upon detecting this as nil, so do it last.    if is_set(Periodical) then        if is_set(Title) or is_set(TitleNote) then             Periodical = sepc .. " " .. wrap( 'italic-title', Periodical )         else             Periodical = wrap( 'italic-title', Periodical )        end    end    -- Piece all bits together at last.  Here, all should be non-nil.    -- We build things this way because it is more efficient in LUA    -- not to keep reassigning to the same string variable over and over.    local tcommon    if inArray(config.CitationClass, {"journal","citation"}) and is_set(Periodical) then        if is_set(Others) then Others = Others .. sepc .. " " end        tcommon = safejoin( {Others, Title, TitleNote, Conference, Periodical, Format, TitleType, Scale, Series,             Language, Cartography, Edition, Publisher, Agency, Volume, Issue}, sepc );    else         tcommon = safejoin( {Title, TitleNote, Conference, Periodical, Format, TitleType, Scale, Series, Language,             Volume, Issue, Others, Cartography, Edition, Publisher, Agency}, sepc );    end        if #ID_list > 0 then        ID_list = safejoin( { sepc .. " ",  table.concat( ID_list, sepc .. " " ), ID }, sepc );    else        ID_list = ID;    end        local idcommon = safejoin( { ID_list, URL, Archived, AccessDate, Via, SubscriptionRequired, Lay, Quote }, sepc );    local text;    local pgtext = Position .. Page .. Pages .. At;        if is_set(Authors) then        if is_set(Coauthors) then            Authors = Authors .. A['AuthorSeparator'] .. " " .. Coauthors        end        if is_set(Date) then            Date = " ("..Date..")" .. OrigYear .. sepc .. " "        elseif string.sub(Authors,-1,-1) == sepc then            Authors = Authors .. " "        else            Authors = Authors .. sepc .. " "        end        if is_set(Editors) then            local in_text = " ";            local post_text = "";            if is_set(Chapter) then                in_text = in_text .. cfg.messages['in'] .. " "            else                if EditorCount <= 1 then                    post_text = ", " .. cfg.messages['editor'];                else                    post_text = ", " .. cfg.messages['editors'];                end            end             if (sepc ~= '.') then in_text = in_text:lower() end            Editors = in_text .. Editors .. post_text;            if (string.sub(Editors,-1,-1) == sepc)                then Editors = Editors .. " "                else Editors = Editors .. sepc .. " "            end        end        text = safejoin( {Authors, Date, Chapter, Place, Editors, tcommon }, sepc );        text = safejoin( {text, pgtext, idcommon}, sepc );    elseif is_set(Editors) then        if is_set(Date) then            if EditorCount <= 1 then                Editors = Editors .. ", " .. cfg.messages['editor'];            else                Editors = Editors .. ", " .. cfg.messages['editors'];            end            Date = " (" .. Date ..")" .. OrigYear .. sepc .. " "        else            if EditorCount <= 1 then                Editors = Editors .. " (" .. cfg.messages['editor'] .. ")" .. sepc .. " "            else                Editors = Editors .. " (" .. cfg.messages['editors'] .. ")" .. sepc .. " "            end        end        text = safejoin( {Editors, Date, Chapter, Place, tcommon}, sepc );        text = safejoin( {text, pgtext, idcommon}, sepc );    else        if is_set(Date) then            if ( string.sub(tcommon,-1,-1) ~= sepc )              then Date = sepc .." " .. Date .. OrigYear              else Date = " " .. Date .. OrigYear            end        end        if config.CitationClass=="journal" and is_set(Periodical) then            text = safejoin( {Chapter, Place, tcommon}, sepc );            text = safejoin( {text, pgtext, Date, idcommon}, sepc );        else            text = safejoin( {Chapter, Place, tcommon, Date}, sepc );            text = safejoin( {text, pgtext, idcommon}, sepc );        end    end        if is_set(PostScript) and PostScript ~= sepc then        text = safejoin( {text, sepc}, sepc );  --Deals with italics, spaces, etc.        text = text:sub(1,-2); --Remove final seperator        end            text = safejoin( {text, PostScript}, sepc );    -- Now enclose the whole thing in a <span/> element    if not is_set(Year) then        if is_set(DateIn) then            Year = selectyear( DateIn );        elseif is_set(PublicationDate) then            Year = selectyear( PublicationDate );        end    end        local options = {};        if is_set(config.CitationClass) and config.CitationClass ~= "citation" then        options.class = "citation " .. config.CitationClass;    else        options.class = "citation";    end        if is_set(Ref) and Ref:lower() ~= "none" then        local id = Ref        if ( "harv" == Ref ) then            local names = {} --table of last names & year            if #a > 0 then                for i,v in ipairs(a) do                     names[i] = v.last                     if i == 4 then break end                end            elseif #e > 0 then                for i,v in ipairs(e) do                     names[i] = v.last                     if i == 4 then break end                                end            end            names[ #names + 1 ] = Year;            id = anchorid(names)        end        options.id = id;    end        if string.len(text:gsub("<span[^>/]*>.-</span>", ""):gsub("%b<>","")) <= 2 then        z.error_categories = {};        text = seterror('empty_citation');        z.message_tail = {};    end        if is_set(options.id) then         text = '<span id="' .. mw.uri.anchorEncode(options.id) ..'" class="' .. mw.text.nowiki(options.class) .. '">' .. text .. "</span>";    else        text = '<span class="' .. mw.text.nowiki(options.class) .. '">' .. text .. "</span>";    end            local empty_span = '<span style="display:none;">&nbsp;</span>';        -- Note: Using display: none on then COinS span breaks some clients.    local OCinS = '<span title="' .. OCinSoutput .. '" class="Z3988">' .. empty_span .. '</span>';    text = text .. OCinS;        if #z.message_tail ~= 0 then        text = text .. " ";        for i,v in ipairs( z.message_tail ) do            if is_set(v[1]) then                if i == #z.message_tail then                    text = text .. errorcomment( v[1], v[2] );                else                    text = text .. errorcomment( v[1] .. "; ", v[2] );                end            end        end    end        no_tracking_cats = no_tracking_cats:lower();    if inArray(no_tracking_cats, {"", "no", "false", "n"}) then        for _, v in ipairs( z.error_categories ) do            text = text .. '[[Category:' .. v ..']]';        end    end        return textend-- This is used by templates such as {{cite book}} to create the actual citation text.function z.citation(frame)    local pframe = frame:getParent()        local args = {};    local suggestions = {};    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        if v ~= '' then            if not validate( k ) then                            error_text = "";                if type( k ) ~= 'string' then                    -- Exclude empty numbered parameters                    if v:match("%S+") ~= nil then                        error_text, error_state = seterror( 'text_ignored', {v}, true );                    end                elseif validate( k:lower() ) then                     error_text, error_state = seterror( 'parameter_ignored_suggest', {k, k:lower()}, true );                else                    if #suggestions == 0 then                        suggestions = mw.loadData( 'Module:Citation/CS1/Suggestions' );                    end                    if suggestions[ k:lower() ] ~= nil then                        error_text, error_state = seterror( 'parameter_ignored_suggest', {k, suggestions[ k:lower() ]}, true );                    else                        error_text, error_state = seterror( 'parameter_ignored', {k}, true );                    end                end                                  if error_text ~= '' then                    table.insert( z.message_tail, {error_text, error_state} );                end                            end            args[k] = v;        elseif args[k] ~= nil or (k == 'postscript') then            args[k] = v;        end            end            return citation0( config, args)endreturn z
"https:https://www.search.com.vn/wiki/index.php?lang=sa&q=पटलम्:Citation/CS1&oldid=285006" इत्यस्माद् प्रतिप्राप्तम्