Module:Citation/CS1: Difference between revisions

    imported>Ahmsaqib
    m (1 revision imported)
    (synch from sandbox;)
    Line 153: Line 153:
    if not domain:match ('^[%a%d]') then -- first character must be letter or digit
    if not domain:match ('^[%a%d]') then -- first character must be letter or digit
    return false;
    end
    if domain:match ('^%a+:') then -- hack to detect things that look like s:Page:Title where Page: is namespace at wikisource
    return false;
    return false;
    end
    end
    Line 399: Line 403:
    local path;
    local path;
    local base_url;
    local base_url;
     
    if not is_set( label ) then
    if not is_set( label ) then
    label = URL;
    label = URL;
    Line 419: Line 423:


    base_url = table.concat({ "[", URL, " ", safe_for_url (label), "]" }); -- assemble a wikimarkup url
    base_url = table.concat({ "[", URL, " ", safe_for_url (label), "]" }); -- assemble a wikimarkup url
     
    if is_set (access) then -- access level (subscription, registration, limited)
    if is_set (access) then -- access level (subscription, registration, limited)
    base_url = substitute (cfg.presentation['ext-link-access-signal'], {cfg.presentation[access].class, cfg.presentation[access].title, base_url}); -- add the appropriate icon
    base_url = substitute (cfg.presentation['ext-link-access-signal'], {cfg.presentation[access].class, cfg.presentation[access].title, base_url}); -- add the appropriate icon
    Line 593: Line 597:
    return substitute( cfg.messages[key], str );
    return substitute( cfg.messages[key], str );
    end
    end
    end
    --[[--------------------------< W I K I S O U R C E _ U R L _ M A K E >----------------------------------------
    makes a wikisource url from wikisource interwiki link.  returns the url and appropriate label; nil else.
    str is the value assigned to |chapter= (or aliases) or |title= or |title-link=
    ]]
    local function wikisource_url_make (str)
    local wl_type, D, L;
    local ws_url, ws_label;
    wl_type, D, L = is_wikilink (str); -- wl_type is 0 (not a wikilink), 1 (simple wikilink), 2 (complex wikilink)
    if 0 == wl_type then -- not a wikilink; might be from |title-link=
    str = D:match ('^[Ww]ikisource:(.+)') or D:match ('^[Ss]:(.+)'); -- article title from interwiki link with long-form or short-form namespace
    if is_set (str) then
    ws_url = table.concat ({ -- build a wikisource url
    'https://en.wikisource.org/wiki/', -- prefix
    str, -- article title
    });
    ws_label = str; -- label for the url
    end
    elseif 1 == wl_type then -- simple wikilink: [[Wikisource:ws article]]
    str = D:match ('^[Ww]ikisource:(.+)') or D:match ('^[Ss]:(.+)'); -- article title from interwiki link with long-form or short-form namespace
    if is_set (str) then
    ws_url = table.concat ({ -- build a wikisource url
    'https://en.wikisource.org/wiki/', -- prefix
    str, -- article title
    });
    ws_label = str; -- label for the url
    end
    elseif 2 == wl_type then -- non-so-simple wikilink: [[Wikisource:ws article|displayed text]] ([[L|D]])
    str = L:match ('^[Ww]ikisource:(.+)') or L:match ('^[Ss]:(.+)'); -- article title from interwiki link with long-form or short-form namespace
    if is_set (str) then
    ws_label = D; -- get ws article name from display portion of interwiki link
    ws_url = table.concat ({ -- build a wikisource url
    'https://en.wikisource.org/wiki/', -- prefix
    str, -- article title without namespace from link portion of wikilink
    });
    end
    end
    if ws_url then
    ws_url = mw.uri.encode (ws_url, 'WIKI'); -- make a usable url
    ws_url = ws_url:gsub ('%%23', '#'); -- undo percent encoding of anchor
    end
    return ws_url, ws_label, L or D; -- return proper url or nil and a label or nil
    end
    end


    Line 605: Line 661:
    local function format_chapter_title (scriptchapter, chapter, transchapter, chapterurl, chapter_url_source, no_quotes, access)
    local function format_chapter_title (scriptchapter, chapter, transchapter, chapterurl, chapter_url_source, no_quotes, access)
    local chapter_error = '';
    local chapter_error = '';
     
    local ws_url, ws_label, L = wikisource_url_make (chapter); -- make a wikisource url and label from a wikisource interwiki link
    if ws_url then
    ws_label = ws_label:gsub ('_', ''); -- replace underscore separaters with space characters
    chapter = ws_label;
    end
     
    if not is_set (chapter) then
    if not is_set (chapter) then
    chapter = ''; -- to be safe for concatenation
    chapter = ''; -- to be safe for concatenation
    Line 619: Line 681:
    if is_set (chapterurl) then
    if is_set (chapterurl) then
    chapter = external_link (chapterurl, chapter, chapter_url_source, access); -- adds bare_url_missing_title error if appropriate
    chapter = external_link (chapterurl, chapter, chapter_url_source, access); -- adds bare_url_missing_title error if appropriate
    elseif ws_url then
    chapter = external_link (ws_url, chapter .. '&nbsp;', 'ws link in chapter'); -- adds bare_url_missing_title error if appropriate; space char to move icon away from chap text; TODO: better way to do this?
    chapter = substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, chapter});
    end
    end


    Line 822: Line 887:
    return str; -- nothing to do, we're done
    return str; -- nothing to do, we're done
    end
    end
    str = str:gsub ('&[nm]dash;', {['&ndash;'] = '–', ['&mdash;'] = '—'}); -- replace &mdash; and &ndash; entities  with their characters; semicolon mucks up the text.split
    local out = {};
    local out = {};
    Line 1,342: Line 1,409:
    extensions. For example, code 'cbk-zam' and its associated name 'Chavacano de Zamboanga' (MediaWiki does not support
    extensions. For example, code 'cbk-zam' and its associated name 'Chavacano de Zamboanga' (MediaWiki does not support
    code 'cbk' or name 'Chavacano'.  Most (all?) of these languages are not used a 'language' codes per se, rather they
    code 'cbk' or name 'Chavacano'.  Most (all?) of these languages are not used a 'language' codes per se, rather they
    are used as sub-domain names: cbk-zam.wikipedia.org.  These names can be found (for the time being) at
    are used as sub-domain names: cbk-zam.wikipedia.org.  A list of language names and codes supported by fetchLanguageNames()
    https://phabricator.wikimedia.org/diffusion/ECLD/browse/master/LocalNames/LocalNamesEn.php
    can be found at Template:Citation Style documentation/language/doc


    Names but that are included in the list will be found if that name is provided in the |language= parameter.  For example,
    Names that are included in the list will be found if that name is provided in the |language= parameter.  For example,
    if |language=Chavacano de Zamboanga, that name will be found with the associated code 'cbk-zam'.  When names are found
    if |language=Chavacano de Zamboanga, that name will be found with the associated code 'cbk-zam'.  When names are found
    and the associated code is not two or three characters, this function returns only the Wikimedia language name.
    and the associated code is not two or three characters, this function returns only the WikiMedia language name.
     
    Some language names have multiple entries under different codes:
    Aromanian has code rup and code roa-rup
    When this occurs, this function returns the language name and the 2- or 3-character code


    Adapted from code taken from Module:Check ISO 639-1.
    Adapted from code taken from Module:Check ISO 639-1.
    Line 1,358: Line 1,429:
    end
    end


    local ietf_code; -- because some languages have both ietf-like codes and iso 639-like codes
    local ietf_name;
    local languages = mw.language.fetchLanguageNames(this_wiki_code, 'all') -- get a list of language names known to Wikimedia
    local languages = mw.language.fetchLanguageNames(this_wiki_code, 'all') -- get a list of language names known to Wikimedia
    -- ('all' is required for North Ndebele, South Ndebele, and Ojibwa)
    -- ('all' is required for North Ndebele, South Ndebele, and Ojibwa)
    local langlc = mw.ustring.lower(lang); -- lower case version for comparisons
    local langlc = mw.ustring.lower(lang); -- lower case version for comparisons
     
    for code, name in pairs(languages) do -- scan the list to see if we can find our language
    for code, name in pairs(languages) do -- scan the list to see if we can find our language
    if langlc == mw.ustring.lower(name) then
    if langlc == mw.ustring.lower(name) then
    if 2 ~= code:len() and 3 ~= code:len() then -- two- or three-character codes only; extensions not supported
    if 2 == code:len() or 3 == code:len() then -- two- or three-character codes only; extensions not supported
    return name; -- so return the name but not the code
    return name, code; -- so return the name and the code
    end
    end
    return name, code; -- found it, return name to ensure proper capitalization and the the code
    ietf_code = code; -- remember that we found an ietf-like code and save its name
    ietf_name = name; -- but keep looking for a 2- or 3-char code
    end
    end
    end
    end
    return lang; -- not valid language; return language in original case and nil for the code
    -- didn't find name with 2- or 3-char code; if ietf-like code found return
    return ietf_code and ietf_name or lang; -- associated name; return original language text else
    end
    end


    Line 1,404: Line 1,480:


    for _, lang in ipairs (names_table) do -- reuse lang
    for _, lang in ipairs (names_table) do -- reuse lang
    name = cfg.lang_code_remap[lang:lower()]; -- first see if this is a code that is not supported by MediaWiki but is in remap


    if lang:match ('^%a%a%-') then -- strip ietf language tags from code; TODO: is there a need to support 3-char with tag?
    if name then -- there was a remapped code so
    lang = lang:match ('(%a%a)%-') -- keep only 639-1 code portion to lang; TODO: do something with 3166 alpha 2 country code?
    lang = lang:gsub ('^(%a%a%a?)%-.*', '%1'); -- strip ietf tags from code
    end
    else
    if 2 == lang:len() or 3 == lang:len() then -- if two-or three-character code
    if lang:match ('^%a%a%-') then -- strip ietf tags from code; TODO: is there a need to support 3-char with tag?
    name = mw.language.fetchLanguageName( lang:lower(), this_wiki_code); -- get language name if |language= is a proper code
    lang = lang:match ('(%a%a)%-') -- keep only 639-1 code portion to lang; TODO: do something with 3166 alpha 2 country code?
    if not is_set (name) then
    end
    name = cfg.lang_code_remap[lang]; -- not supported by MediaWiki; is it in remap?
    if 2 == lang:len() or 3 == lang:len() then -- if two-or three-character code
    name = mw.language.fetchLanguageName (lang:lower(), this_wiki_code); -- get language name if |language= is a proper code
    end
    end
    end
    end
     
    if is_set (name) then -- if |language= specified a valid code
    if is_set (name) then -- if |language= specified a valid code
    code = lang:lower(); -- save it
    code = lang:lower(); -- save it
    Line 1,441: Line 1,519:
    code = #language_list -- reuse code as number of languages in the list
    code = #language_list -- reuse code as number of languages in the list
    if 2 >= code then
    if 2 >= code then
    name = table.concat (language_list, ' and ') -- insert '<space>and<space>' between two language names
    name = table.concat (language_list, cfg.messages['parameter-pair-separator']) -- insert '<space>and<space>' between two language names
    elseif 2 < code then
    elseif 2 < code then
    language_list[code] = 'and ' .. language_list[code]; -- prepend last name with 'and<space>'
    name = table.concat (language_list, ', '); -- and concatenate with '<comma><space>' separators
    name = table.concat (language_list, ', ') -- and concatenate with '<comma><space>' separators
    name = name:gsub (', ([^,]+)$', cfg.messages['parameter-final-separator'] .. '%1'); -- replace last '<comma><space>' separator with '<comma><space>and<space>' separator
    end
    end
    if this_wiki_name == name then
    if this_wiki_name == name then
    Line 1,869: Line 1,947:
    end
    end


    local vol = '';
    local vol = ''; -- here for all cites except magazine
    if is_set (volume) then
    if is_set (volume) then
    if (4 < mw.ustring.len(volume)) then
    if volume:match ('^[MDCLXVI]+$') or volume:match ('^%d+$')then -- volume value is all digits or all uppercase roman numerals
    vol = substitute (cfg.messages['j-vol'], {sepc, volume});
    vol = substitute (cfg.presentation['vol-bold'], {sepc, hyphen_to_dash(volume)}); -- render in bold face
    else
    elseif (4 < mw.ustring.len(volume)) then -- not all digits or roman numerals and longer than 4 characters
    vol = substitute (cfg.presentation['vol-bold'], {sepc, hyphen_to_dash(volume)});
    vol = substitute (cfg.messages['j-vol'], {sepc, volume}); -- not bold
    add_prop_cat ('long_vol');
    else -- four or less characters
    vol = substitute (cfg.presentation['vol-bold'], {sepc, hyphen_to_dash(volume)}); -- bold
    end
    end
    end
    end
    Line 1,936: Line 2,017:
    return '', '', '', ''; -- return empty strings
    return '', '', '', ''; -- return empty strings
    end
    end
    --[[--------------------------< I N S O U R C E _ L O C _ G E T >----------------------------------------------
    returns one of the in-source locators: page, pages, or at.
    If any of these are interwiki links to wikisource, returns the label portion of the interwikilink as plain text
    for use in COinS.  This COinS thing is done because here we convert an interwiki link to and external link and
    add an icon span around that; get_coins_pages() doesn't know about the span.  TODO: should it? 
    TODO: add support for sheet and sheets?; streamline;
    TODO: make it so that this function returns only one of the three as the single in-source (the return value assigned
    to a new name)?
    ]]
    local function insource_loc_get (page, pages, at)
    local ws_url, ws_label, coins_pages, L; -- for wikisource interwikilinks; TODO: this corrupts page metadata (span remains in place after cleanup; fix there?)
    if is_set (page) then
    if is_set (pages) or is_set(at) then
    pages = ''; -- unset the others
    at = '';
    end
    extra_text_in_page_check (page); -- add this page to maint cat if |page= value begins with what looks like p. or pp.
    ws_url, ws_label, L = wikisource_url_make (page); -- make ws url from |page= interwiki link; link portion L becomes tool tip label
    if ws_url then
    page = external_link (ws_url, ws_label .. '&nbsp;', 'ws link in page'); -- space char after label to move icon away from in-source text; TODO: a better way to do this?
    page = substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, page});
    coins_pages = ws_label;
    end
    elseif is_set (pages) then
    if is_set (at) then
    at = ''; -- unset
    end
    extra_text_in_page_check (pages); -- add this page to maint cat if |pages= value begins with what looks like p. or pp.
    ws_url, ws_label, L = wikisource_url_make (pages); -- make ws url from |pages= interwiki link; link portion L becomes tool tip label
    if ws_url then
    pages = external_link (ws_url, ws_label .. '&nbsp;', 'ws link in pages'); -- space char after label to move icon away from in-source text; TODO: a better way to do this?
    pages = substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, pages});
    coins_pages = ws_label;
    end
    elseif is_set (at) then
    ws_url, ws_label, L = wikisource_url_make (at); -- make ws url from |at= interwiki link; link portion L becomes tool tip label
    if ws_url then
    at = external_link (ws_url, ws_label .. '&nbsp;', 'ws link in at'); -- space char after label to move icon away from in-source text; TODO: a better way to do this?
    at = substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, at});
    coins_pages = ws_label;
    end
    end
    return page, pages, at, coins_pages;
    end




    Line 2,082: Line 2,220:
    t = extract_names (args, 'TranslatorList'); -- fetch translator list from |translatorn= / |translator-lastn=, -firstn=, -linkn=, -maskn=
    t = extract_names (args, 'TranslatorList'); -- fetch translator list from |translatorn= / |translator-lastn=, -firstn=, -linkn=, -maskn=


    local interviewers_list = {};
    local interviewers_list = {};
    local Interviewers = A['Interviewers']
    local Interviewers; -- used later
    if is_set (Interviewers) then -- add a maint cat if the |interviewers= is used
    interviewers_list = extract_names (args, 'InterviewerList'); -- process preferred interviewers parameters
    add_maint_cat ('interviewers'); -- because use of this parameter is discouraged
    else
    interviewers_list = extract_names (args, 'InterviewerList'); -- else, process preferred interviewers parameters
    end


    local c = {}; -- contributors list from |contributor-lastn= / contributor-firstn= pairs
    local c = {}; -- contributors list from |contributor-lastn= / contributor-firstn= pairs
    Line 2,297: Line 2,431:
    -- check for extra |page=, |pages= or |at= parameters. (also sheet and sheets while we're at it)
    -- check for extra |page=, |pages= or |at= parameters. (also sheet and sheets while we're at it)
    select_one( args, {'page', 'p', 'pp', 'pages', 'at', 'sheet', 'sheets'}, 'redundant_parameters' ); -- this is a dummy call simply to get the error message and category
    select_one( args, {'page', 'p', 'pp', 'pages', 'at', 'sheet', 'sheets'}, 'redundant_parameters' ); -- this is a dummy call simply to get the error message and category
    local coins_pages;
    Page, Pages, At, coins_pages = insource_loc_get (Page, Pages, At);


    local NoPP = A['NoPP']  
    local NoPP = A['NoPP']  
    Line 2,304: Line 2,442:
    NoPP = nil; -- unset, used as a flag later
    NoPP = nil; -- unset, used as a flag later
    end
    end
    if is_set(Page) then
    if is_set(Pages) or is_set(At) then
    Pages = ''; -- unset the others
    At = '';
    end
    extra_text_in_page_check (Page); -- add this page to maint cat if |page= value begins with what looks like p. or pp.
    elseif is_set(Pages) then
    if is_set(At) then
    At = ''; -- unset
    end
    extra_text_in_page_check (Pages); -- add this page to maint cat if |pages= value begins with what looks like p. or pp.
    end


    -- both |publication-place= and |place= (|location=) allowed if different
    -- both |publication-place= and |place= (|location=) allowed if different
    Line 2,693: Line 2,818:
    ['Volume'] = Volume,
    ['Volume'] = Volume,
    ['Issue'] = Issue,
    ['Issue'] = Issue,
    ['Pages'] = get_coins_pages (first_set ({Sheet, Sheets, Page, Pages, At}, 5)), -- pages stripped of external links
    ['Pages'] = coins_pages or get_coins_pages (first_set ({Sheet, Sheets, Page, Pages, At}, 5)), -- pages stripped of external links
    ['Edition'] = Edition,
    ['Edition'] = Edition,
    ['PublisherName'] = PublisherName,
    ['PublisherName'] = PublisherName,
    Line 2,894: Line 3,019:
    end
    end
    if is_set(TitleLink) and is_set(Title) then
    Title = make_wikilink (TitleLink, Title);
    end
    if in_array(config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'mailinglist', 'interview', 'arxiv', 'biorxiv', 'citeseerx'}) or
    if in_array(config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'mailinglist', 'interview', 'arxiv', 'biorxiv', 'citeseerx'}) or
    ('citation' == config.CitationClass and is_set (Periodical) and not is_set (Encyclopedia)) or
    ('citation' == config.CitationClass and is_set (Periodical) and not is_set (Encyclopedia)) or
    Line 2,922: Line 3,043:
    end
    end
    end
    end
     
    if is_set(Title) then
    if is_set(Title) then
    if not is_set(TitleLink) and is_set(URL) then
    if not is_set (TitleLink) and is_set (URL) then
    Title = external_link (URL, Title, URLorigin, UrlAccess) .. TransTitle .. TransError .. Format;
    Title = external_link( URL, Title, URLorigin, UrlAccess ) .. TransTitle .. TransError .. Format;
    URL = ''; -- unset these because no longer needed
    URL = ''; -- unset these because no longer needed
    Format = "";
    Format = "";
    elseif is_set (TitleLink) and not is_set (URL) then
    local ws_url;
    ws_url = wikisource_url_make (TitleLink); -- ignore ws_label return; not used here
    if ws_url then
    Title = external_link (ws_url, Title .. '&nbsp;', 'ws link in title-link'); -- space char after Title to move icon away from italic text; TODO: a better way to do this?
    Title = substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], TitleLink, Title});
    Title = Title .. TransTitle .. TransError;
    else
    Title = make_wikilink (TitleLink, Title) .. TransTitle .. TransError;
    end
    else
    else
    Title = Title .. TransTitle .. TransError;
    local ws_url, ws_label;
    ws_url, ws_label, L = wikisource_url_make (Title); -- make ws url from |title= interwiki link; link portion L becomes tool tip label
    if ws_url then
    Title = Title:gsub ('%b[]', ws_label); -- replace interwiki link with ws_label to retain markup
    Title = external_link (ws_url, Title .. '&nbsp;', 'ws link in title'); -- space char after Title to move icon away from italic text; TODO: a better way to do this?
    Title = substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, Title});
    Title = Title .. TransTitle .. TransError;
    else
    Title = Title .. TransTitle .. TransError;
    end
    end
    end
    else
    else
    Line 3,353: Line 3,492:
    table.insert (render, substitute (cfg.presentation['ocins'], {OCinSoutput})); -- append metadata to the citation
    table.insert (render, substitute (cfg.presentation['ocins'], {OCinSoutput})); -- append metadata to the citation


    if #z.message_tail ~= 0 then
    if 0 ~= #z.message_tail then
    table.insert (render, ' ');
    table.insert (render, ' ');
    for i,v in ipairs( z.message_tail ) do
    for i,v in ipairs( z.message_tail ) do
    Line 3,366: Line 3,505:
    end
    end


    if #z.maintenance_cats ~= 0 then
    if 0 ~= #z.maintenance_cats then
    table.insert (render, '<span class="citation-comment" style="display:none; color:#33aa33; margin-left:0.3em">');
    local maint_msgs = {}; -- here we collect all of the maint messages
    for _, v in ipairs( z.maintenance_cats ) do -- append maintenance categories
    for _, v in ipairs( z.maintenance_cats ) do -- append maintenance categories
    table.insert (render, v);
    local maint = {}; -- here we assemble a maintenence message
    table.insert (render, ' (');
    table.insert (maint, v); -- maint msg is the category name
    table.insert (render, make_wikilink (':Category:' .. v, 'link'));
    table.insert (maint, ' ('); -- open the link text
    table.insert (render, ') ');
    table.insert (maint, make_wikilink (':Category:' .. v, 'link')); -- add the link
    table.insert (maint, ')'); -- and close it
    table.insert (maint_msgs, table.concat (maint)); -- assemble new maint message and add it to the maint_msgs table
    end
    end
    table.insert (render, '</span>');
    table.insert (render, substitute (cfg.presentation['hidden-maint'], table.concat (maint_msgs, ' '))); -- wrap the group of maint message with proper presentation and save
    end
    end