Module:Citation/CS1/Utilities: Difference between revisions

    From Nonbinary Wiki
    (sync from sandbox;)
     
    (7 intermediate revisions by 2 users not shown)
    Line 13: Line 13:


    local cfg; -- table of tables imported from selected Module:Citation/CS1/Configuration
    local cfg; -- table of tables imported from selected Module:Citation/CS1/Configuration
    --[[--------------------------< H A S _ A C C E P T _ A S _ W R I T T E N >------------------------------------
    When <str> is wholly wrapped in accept-as-written markup, return <str> without markup and true; return <str> and false else
    with allow_empty = false, <str> must have at least one character inside the markup
    with allow_empty = true, <str> the markup frame can be empty like (()) to distinguish an empty template parameter from the specific condition "has no applicable value" in citation-context.
    After further evaluation the two cases might be merged at a later stage, but should be kept separated for now.
    ]]
    local function has_accept_as_written (str, allow_empty)
    local count;
    if true == allow_empty then
    str, count = str:gsub ('^%(%((.*)%)%)$', '%1'); -- allows (()) to be an empty set
    else
    str, count = str:gsub ('^%(%((.+)%)%)$', '%1');
    end
    return str, 0 ~= count;
    end




    Line 21: Line 43:
    ]]
    ]]


    local function is_set( var )
    local function is_set (var)
    return not (var == nil or var == '');
    return not (var == nil or var == '');
    end
    end
    Line 32: Line 54:
    ]]
    ]]


    local function in_array( needle, haystack )
    local function in_array (needle, haystack)
    if needle == nil then
    if needle == nil then
    return false;
    return false;
    end
    end
    for n,v in ipairs( haystack ) do
    for n, v in ipairs (haystack) do
    if v == needle then
    if v == needle then
    return n;
    return n;
    Line 51: Line 73:
    ]]
    ]]


    local function substitute( msg, args )
    local function substitute (msg, args)
    return args and mw.message.newRawMessage( msg, args ):plain() or msg;
    return args and mw.message.newRawMessage (msg, args):plain() or msg;
    end
    end


    Line 58: Line 80:
    --[[--------------------------< E R R O R _ C O M M E N T >----------------------------------------------------
    --[[--------------------------< E R R O R _ C O M M E N T >----------------------------------------------------


    Wraps error messages with css markup according to the state of hidden.
    Wraps error messages with CSS markup according to the state of hidden.


    ]]
    ]]


    local function error_comment( content, hidden )
    local function error_comment (content, hidden)
    return substitute( hidden and cfg.presentation['hidden-error'] or cfg.presentation['visible-error'], content );
    return substitute (hidden and cfg.presentation['hidden-error'] or cfg.presentation['visible-error'], content);
    end
    end


    Line 69: Line 91:
    --[=[-------------------------< M A K E _ W I K I L I N K >----------------------------------------------------
    --[=[-------------------------< M A K E _ W I K I L I N K >----------------------------------------------------


    Makes a wikilink; when bot link and display text is provided, returns a wikilink in the form [[L|D]]; if only
    Makes a wikilink; when both link and display text is provided, returns a wikilink in the form [[L|D]]; if only
    link is provided, returns a wikilink in the form [[L]]; if neither are provided or link is omitted, returns an
    link is provided (or link and display are the same), returns a wikilink in the form [[L]]; if neither are
    empty string.
    provided or link is omitted, returns an empty string.


    ]=]
    ]=]


    local function make_wikilink (link, display)
    local function make_wikilink (link, display)
    if is_set (link) then
    if not is_set (link) then return '' end
    if is_set (display) then
     
    return table.concat ({'[[', link, '|', display, ']]'});
    if is_set (display) and link ~= display then
    else
    return table.concat ({'[[', link, '|', display, ']]'});
    return table.concat ({'[[', link, ']]'});
    end
    else
    else
    return '';
    return table.concat ({'[[', link, ']]'});
    end
    end
    end
    end




    --[[--------------------------< S E T _ E R R O R >--------------------------------------------------------------
    --[[--------------------------< S E T _ M E S S A G E >----------------------------------------------------------


    Sets an error condition and returns the appropriate error message.  The actual placement of the error message in the output is
    Sets an error condition and returns the appropriate error message.  The actual placement of the error message in the output is
    the responsibility of the calling function.
    the responsibility of the calling function.
    TODO: change z.error_categories and z.maintenance_cats to have the form cat_name = true; to avoid dups without having to have an extra cat


    ]]
    ]]
    local added_maint_cats = {} -- list of maintenance categories that have been added to z.maintenance_cats; TODO: figure out how to delete this table


    local function set_error( error_id, arguments, raw, prefix, suffix )
    local function set_message (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.messages['undefined_error'] ); -- because missing error handler in Module:Citation/CS1/Configuration
    error (cfg.messages['undefined_error'] .. ': ' .. error_id); -- because missing error handler in Module:Citation/CS1/Configuration
    elseif is_set( error_state.category ) then
     
    table.insert( z.error_categories, error_state.category );
    elseif is_set (error_state.category) then
    if error_state.message then -- when error_state.message defined, this is an error message
    table.insert (z.error_categories, error_state.category);
    else
    if not added_maint_cats[error_id] then
    added_maint_cats[error_id] = true; -- note that we've added this category
    table.insert (z.maintenance_cats, substitute (error_state.category, arguments)); -- make cat name then add to table
    end
    return; -- because no message, nothing more to do
    end
    end
    end
     
    local message = substitute( error_state.message, arguments );
    local message = substitute (error_state.message, arguments);


    message = table.concat (
    message = table.concat (
    Line 124: Line 156:
    });
    });


    -- message = table.concat ({message, ' (', substitute (cfg.presentation['wikilink'],
    z.error_ids[error_id] = true;
    -- {cfg.messages['help page link'] .. '#' .. error_state.anchor, cfg.messages['help page label']}), ')'});
    if z.error_ids['err_citation_missing_title'] and -- if missing-title error already noted
    -- message = message .. " ([[" .. cfg.messages['help page link'] ..
    in_array (error_id, {'err_bare_url_missing_title', 'err_trans_missing_title'}) then -- and this error is one of these
    -- "#" .. error_state.anchor .. "|" ..
    return '', false; -- don't bother because one flavor of missing title is sufficient
    -- cfg.messages['help page label'] .. "]])";
    z.error_ids[ error_id ] = true;
    if in_array( error_id, { 'bare_url_missing_title', 'trans_missing_title' } )
    and z.error_ids['citation_missing_title'] then
    return '', false;
    end
    end
    message = table.concat({ prefix, message, suffix });
    message = table.concat ({prefix, message, suffix});
     
    if raw == true then
    if raw == true then
    return message, error_state.hidden;
    return message, error_state.hidden;
    end
    end
     
    return error_comment( message, error_state.hidden );
    return error_comment (message, error_state.hidden);
    end
    end


    Line 155: Line 181:
    alias – one of the list of possible aliases in the aliases lists from Module:Citation/CS1/Configuration
    alias – one of the list of possible aliases in the aliases lists from Module:Citation/CS1/Configuration
    index – for enumerated parameters, identifies which one
    index – for enumerated parameters, identifies which one
    enumerated – true/false flag used choose how enumerated aliases are examined
    enumerated – true/false flag used to choose how enumerated aliases are examined
    value – value associated with an alias that has previously been selected; nil if not yet selected
    value – value associated with an alias that has previously been selected; nil if not yet selected
    selected – the alias that has previously been selected; nil if not yet selected
    selected – the alias that has previously been selected; nil if not yet selected
    Line 173: Line 199:
    end
    end


    if is_set(args[alias]) then -- alias is in the template's argument list
    if is_set (args[alias]) then -- alias is in the template's argument list
    if value ~= nil and selected ~= alias then -- if we have already selected one of the aliases
    if value ~= nil and selected ~= alias then -- if we have already selected one of the aliases
    local skip;
    local skip;
    for _, v in ipairs(error_list) do -- spin through the error list to see if we've added this alias
    for _, v in ipairs (error_list) do -- spin through the error list to see if we've added this alias
    if v == alias then
    if v == alias then
    skip = true;
    skip = true;
    Line 183: Line 209:
    end
    end
    if not skip then -- has not been added so
    if not skip then -- has not been added so
    table.insert( error_list, alias ); -- add error alias to the error list
    table.insert (error_list, alias); -- add error alias to the error list
    end
    end
    else
    else
    Line 201: Line 227:
    ]]
    ]]


    local added_maint_cats = {} -- list of maintenance categories that have been added to z.maintenance_cats
    local function add_maint_cat (key, arguments)
    local function add_maint_cat (key, arguments)
    if not added_maint_cats [key] then
    if not added_maint_cats [key] then
    added_maint_cats [key] = true; -- note that we've added this category
    added_maint_cats [key] = true; -- note that we've added this category
    table.insert( z.maintenance_cats, substitute (cfg.maint_cats [key], arguments)); -- make name then add to table
    table.insert (z.maintenance_cats, substitute (cfg.maint_cats [key], arguments)); -- make name then add to table
    end
    end
     
     
    --[[--------------------------< A D D _ P R O P _ C A T >--------------------------------------------------------
     
    Adds a category to z.properties_cats using names from the configuration file with additional text if any.
     
    foreign_lang_source and foreign_lang_source_2 keys have a language code appended to them so that multiple languages
    may be categorized but multiples of the same language are not categorized.
     
    added_prop_cats is a table declared in page scope variables above
     
    ]]
     
    local added_prop_cats = {}; -- list of property categories that have been added to z.properties_cats
     
    local function add_prop_cat (key, arguments)
    if not added_prop_cats [key] then
    added_prop_cats [key] = true; -- note that we've added this category
    key = key:gsub ('(foreign_lang_source_?2?)%a%a%a?[%a%-]*', '%1'); -- strip lang code from keyname
    table.insert (z.properties_cats, substitute (cfg.prop_cats [key], arguments)); -- make name then add to table
    end
    end
    end
    end
    Line 220: Line 267:
    ]]
    ]]


    local function safe_for_italics( str )
    local function safe_for_italics (str)
    if not is_set(str) then
    if not is_set (str) then return str end
    return str;
     
    else
    if str:sub (1, 1) == "'" then str = "<span></span>" .. str; end
    if str:sub(1,1) == "'" then str = "<span></span>" .. str; end
    if str:sub (-1, -1) == "'" then str = str .. "<span></span>"; end
    if str:sub(-1,-1) == "'" then str = str .. "<span></span>"; end
    -- Remove newlines as they break italics.
    -- Remove newlines as they break italics.
    return str:gsub ('\n', ' ');
    return str:gsub( '\n', ' ' );
     
    end
    end
    end


    Line 242: Line 288:


    local function wrap_style (key, str)
    local function wrap_style (key, str)
    if not is_set( str ) then
    if not is_set (str) then
    return "";
    return "";
    elseif in_array( key, { 'italic-title', 'trans-italic-title' } ) then
    elseif in_array (key, {'italic-title', 'trans-italic-title'}) then
    str = safe_for_italics( str );
    str = safe_for_italics (str);
    end
    end


    return substitute( cfg.presentation[key], {str} );
    return substitute (cfg.presentation[key], {str});
    end
     
     
    --[[--------------------------< M A K E _ S E P _ L I S T >------------------------------------------------------------
     
    make a separated list of items using provided separators.
    <sep_list> - typically '<comma><space>'
    <sep_list_pair> - typically '<space>and<space>'
    <sep_list_end> - typically '<comma><space>and<space>' or '<comma><space>&<space>'
     
    defaults to cfg.presentation['sep_list'], cfg.presentation['sep_list_pair'], and cfg.presentation['sep_list_end']
    if <sep_list_end> is specified, <sep_list> and <sep_list_pair> must also be supplied
     
    ]]
     
    local function make_sep_list (count, list_seq, sep_list, sep_list_pair, sep_list_end)
    local list = '';
     
    if not sep_list then -- set the defaults
    sep_list = cfg.presentation['sep_list'];
    sep_list_pair = cfg.presentation['sep_list_pair'];
    sep_list_end = cfg.presentation['sep_list_end'];
    end
    if 2 >= count then
    list = table.concat (list_seq, sep_list_pair); -- insert separator between two items; returns list_seq[1] then only one item
    elseif 2 < count then
    list = table.concat (list_seq, sep_list, 1, count - 1); -- concatenate all but last item with plain list separator
    list = table.concat ({list, list_seq[count]}, sep_list_end); -- concatenate last item onto end of <list> with final separator
    end
    return list;
    end
    end


    Line 265: Line 343:
    ]]
    ]]


    local function select_one( args, aliases_list, error_condition, index )
    local function select_one (args, aliases_list, error_condition, index)
    local value = nil; -- the value assigned to the selected parameter
    local value = nil; -- the value assigned to the selected parameter
    local selected = ''; -- the name of the parameter we have chosen
    local selected = ''; -- the name of the parameter we have chosen
    Line 272: Line 350:
    if index ~= nil then index = tostring(index); end
    if index ~= nil then index = tostring(index); end


    for _, alias in ipairs( aliases_list ) do -- for each alias in the aliases list
    for _, alias in ipairs (aliases_list) do -- for each alias in the aliases list
    if alias:match ('#') then -- if this alias can be enumerated
    if alias:match ('#') then -- if this alias can be enumerated
    if '1' == index then -- when index is 1 test for enumerated and non-enumerated aliases
    if '1' == index then -- when index is 1 test for enumerated and non-enumerated aliases
    value, selected = is_alias_used (args, alias, index, false, value, selected, error_list); -- first test for non-enumerated alias
    value, selected = is_alias_used (args, alias, index, false, value, selected, error_list); -- first test for non-enumerated alias
    end
    end
    value, selected = is_alias_used (args, alias, index, true, value, selected, error_list); -- test for enumerated alias
    value, selected = is_alias_used (args, alias, index, true, value, selected, error_list); -- test for enumerated alias
    else
    else
    value, selected = is_alias_used (args, alias, index, false, value, selected, error_list); --test for non-enumerated alias
    value, selected = is_alias_used (args, alias, index, false, value, selected, error_list); -- test for non-enumerated alias
    end
    end
    end
    end


    if #error_list > 0 and 'none' ~= error_condition then -- for cases where this code is used outside of extract_names()
    if #error_list > 0 and 'none' ~= error_condition then -- for cases where this code is used outside of extract_names()
    local error_str = "";
    for i, v in ipairs (error_list) do
    for _, k in ipairs( error_list ) do
    error_list[i] = wrap_style ('parameter', v);
    if error_str ~= "" then error_str = error_str .. cfg.messages['parameter-separator'] end
    error_str = error_str .. wrap_style ('parameter', k);
    end