Changes

update per RfC;
Line 1: Line 1: −
   
local z = {
 
local z = {
error_categories = {}; -- for categorizing citations that contain errors
+
error_cats_t = {}; -- for categorizing citations that contain errors
error_ids = {};
+
error_ids_t = {}; -- list of error identifiers; used to prevent duplication of certain errors; local to this module
message_tail = {};
+
error_msgs_t = {}; -- sequence table of error messages
maintenance_cats = {}; -- for categorizing citations that aren't erroneous per se, but could use a little work
+
maint_cats_t = {}; -- for categorizing citations that aren't erroneous per se, but could use a little work
properties_cats = {}; -- for categorizing citations based on certain properties, language of source for instance
+
prop_cats_t = {}; -- for categorizing citations based on certain properties, language of source for instance
 +
prop_keys_t = {}; -- for adding classes to the citation's <cite> tag
 
};
 
};
   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 64: Line 42:  
end
 
end
 
return false;
 
return false;
 +
end
 +
 +
 +
--[[--------------------------< 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)
 +
if not is_set (str) then
 +
return str, false;
 +
end
 +
 +
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
 
end
   Line 69: Line 74:  
--[[--------------------------< S U B S T I T U T E >----------------------------------------------------------
 
--[[--------------------------< S U B S T I T U T E >----------------------------------------------------------
   −
Populates numbered arguments in a message string using an argument table.
+
Populates numbered arguments in a message string using an argument table. <args> may be a single string or a
 +
sequence table of multiple strings.
    
]]
 
]]
Line 80: Line 86:  
--[[--------------------------< 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. <content> may be a single string or a
 +
sequence table of multiple strings.
    
]]
 
]]
Line 86: Line 93:  
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
 +
 +
 +
--[[--------------------------< H Y P H E N _ T O _ D A S H >--------------------------------------------------
 +
 +
Converts a hyphen to a dash under certain conditions.  The hyphen must separate
 +
like items; unlike items are returned unmodified.  These forms are modified:
 +
letter - letter (A - B)
 +
digit - digit (4-5)
 +
digit separator digit - digit separator digit (4.1-4.5 or 4-1-4-5)
 +
letterdigit - letterdigit (A1-A5) (an optional separator between letter and
 +
digit is supported – a.1-a.5 or a-1-a-5)
 +
digitletter - digitletter (5a - 5d) (an optional separator between letter and
 +
digit is supported – 5.a-5.d or 5-a-5-d)
 +
 +
any other forms are returned unmodified.
 +
 +
str may be a comma- or semicolon-separated list
 +
 +
]]
 +
 +
local function hyphen_to_dash (str)
 +
if not is_set (str) then
 +
return str;
 +
end
 +
 +
local accept; -- boolean
 +
 +
str = str:gsub ("(%(%(.-%)%))", function(m) return m:gsub(",", ","):gsub(";", ";") end) -- replace commas and semicolons in accept-as-written markup with similar unicode characters so they'll be ignored during the split
 +
str = str:gsub ('&[nm]dash;', {['&ndash;'] = '–', ['&mdash;'] = '—'}); -- replace &mdash; and &ndash; entities with their characters; semicolon mucks up the text.split
 +
str = str:gsub ('&#45;', '-'); -- replace HTML numeric entity with hyphen character
 +
str = str:gsub ('&nbsp;', ' '); -- replace &nbsp; entity with generic keyboard space character
 +
 +
local out = {};
 +
local list = mw.text.split (str, '%s*[,;]%s*'); -- split str at comma or semicolon separators if there are any
 +
 +
for _, item in ipairs (list) do -- for each item in the list
 +
item, accept = has_accept_as_written (item); -- remove accept-this-as-written markup when it wraps all of item
 +
if not accept and mw.ustring.match (item, '^%w*[%.%-]?%w+%s*[%-–—]%s*%w*[%.%-]?%w+$') then -- if a hyphenated range or has endash or emdash separators
 +
if item:match ('^%a+[%.%-]?%d+%s*%-%s*%a+[%.%-]?%d+$') or -- letterdigit hyphen letterdigit (optional separator between letter and digit)
 +
item:match ('^%d+[%.%-]?%a+%s*%-%s*%d+[%.%-]?%a+$') or -- digitletter hyphen digitletter (optional separator between digit and letter)
 +
item:match ('^%d+[%.%-]%d+%s*%-%s*%d+[%.%-]%d+$') or -- digit separator digit hyphen digit separator digit
 +
item:match ('^%d+%s*%-%s*%d+$') or -- digit hyphen digit
 +
item:match ('^%a+%s*%-%s*%a+$') then -- letter hyphen letter
 +
item = item:gsub ('(%w*[%.%-]?%w+)%s*%-%s*(%w*[%.%-]?%w+)', '%1–%2'); -- replace hyphen, remove extraneous space characters
 +
else
 +
item = mw.ustring.gsub (item, '%s*[–—]%s*', '–'); -- for endash or emdash separated ranges, replace em with en, remove extraneous whitespace
 +
end
 +
end
 +
table.insert (out, item); -- add the (possibly modified) item to the output table
 +
end
 +
 +
local temp_str = ''; -- concatenate the output table into a comma separated string
 +
temp_str, accept = has_accept_as_written (table.concat (out, ', ')); -- remove accept-this-as-written markup when it wraps all of concatenated out
 +
if accept then
 +
temp_str = has_accept_as_written (str); -- when global markup removed, return original str; do it this way to suppress boolean second return value
 +
return temp_str:gsub(",", ","):gsub(";", ";");
 +
else
 +
return temp_str:gsub(",", ","):gsub(";", ";"); -- else, return assembled temp_str
 +
end
 
end
 
end
   Line 110: Line 177:  
--[[--------------------------< S E T _ M E S S A G E >----------------------------------------------------------
 
--[[--------------------------< 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 message using the ~/Configuration error_conditions{} table along with arguments supplied in the function
the responsibility of the calling function.
+
call, inserts the resulting message in z.error_msgs_t{} sequence table, and returns the error message.
   −
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
+
<error_id> – key value for appropriate error handler in ~/Configuration error_conditions{} table
 +
<arguments> – may be a single string or a sequence table of multiple strings to be subsititued into error_conditions[error_id].message
 +
<raw> – boolean
 +
true – causes this function to return the error message not wrapped in visible-error, hidden-error span tag;
 +
returns error_conditions[error_id].hidden as a second return value
 +
does not add message to z.error_msgs_t sequence table
 +
false, nil – adds message wrapped in visible-error, hidden-error span tag to z.error_msgs_t
 +
returns the error message wrapped in visible-error, hidden-error span tag; there is no second return value
 +
<prefix> – string to be prepended to <message> -- TODO: remove support for these unused(?) arguments?
 +
<suffix> – string to be appended to <message>
 +
 
 +
TODO: change z.error_cats_t and z.maint_cats_t to have the form cat_name = true?  this to avoid dups without having to have an extra table
    
]]
 
]]
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 added_maint_cats = {} -- list of maintenance categories that have been added to z.maint_cats_t; TODO: figure out how to delete this table
    
local function set_message (error_id, arguments, raw, prefix, suffix)
 
local function set_message (error_id, arguments, raw, prefix, suffix)
Line 129: Line 208:  
elseif is_set (error_state.category) then
 
elseif is_set (error_state.category) then
 
if error_state.message then -- when error_state.message defined, this is an error message
 
if error_state.message then -- when error_state.message defined, this is an error message
table.insert (z.error_categories, error_state.category);
+
table.insert (z.error_cats_t, error_state.category);
 
else
 
else
 
if not added_maint_cats[error_id] then
 
if not added_maint_cats[error_id] then
 
added_maint_cats[error_id] = true; -- note that we've added this category
 
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
+
table.insert (z.maint_cats_t, substitute (error_state.category, arguments)); -- make cat name then add to table
 
end
 
end
 
return; -- because no message, nothing more to do
 
return; -- because no message, nothing more to do
Line 156: Line 235:  
});
 
});
   −
z.error_ids[error_id] = true;
+
z.error_ids_t[error_id] = true;
if z.error_ids['err_citation_missing_title'] and -- if missing-title error already noted
+
if z.error_ids_t['err_citation_missing_title'] and -- if missing-title error already noted
 
in_array (error_id, {'err_bare_url_missing_title', 'err_trans_missing_title'}) then -- and this error is one of these
 
in_array (error_id, {'err_bare_url_missing_title', 'err_trans_missing_title'}) then -- and this error is one of these
 
return '', false; -- don't bother because one flavor of missing title is sufficient
 
return '', false; -- don't bother because one flavor of missing title is sufficient
Line 164: Line 243:  
message = table.concat ({prefix, message, suffix});
 
message = table.concat ({prefix, message, suffix});
   −
if raw == true then
+
if true == raw then
return message, error_state.hidden;
+
return message, error_state.hidden; -- return message not wrapped in visible-error, hidden-error span tag
 
end
 
end
   −
return error_comment (message, error_state.hidden);
+
message = error_comment (message, error_state.hidden); -- wrap message in visible-error, hidden-error span tag
 +
table.insert (z.error_msgs_t, message); -- add it to the messages sequence table
 +
return message; -- and done; return value generally not used but is used as a flag in various functions of ~/Identifiers
 
end
 
end
   Line 199: Line 280:  
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;
Line 222: Line 303:  
--[[--------------------------< A D D _ M A I N T _ C A T >------------------------------------------------------
 
--[[--------------------------< A D D _ M A I N T _ C A T >------------------------------------------------------
   −
Adds a category to z.maintenance_cats using names from the configuration file with additional text if any.
+
Adds a category to z.maint_cats_t using names from the configuration file with additional text if any.
To prevent duplication, the added_maint_cats table lists the categories by key that have been added to z.maintenance_cats.
+
To prevent duplication, the added_maint_cats table lists the categories by key that have been added to z.maint_cats_t.
    
]]
 
]]
Line 230: Line 311:  
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.maint_cats_t, substitute (cfg.maint_cats [key], arguments)); -- make name then add to table
 
end
 
end
 
end
 
end
Line 237: Line 318:  
--[[--------------------------< A D D _ P R O P _ C A T >--------------------------------------------------------
 
--[[--------------------------< 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.
+
Adds a category to z.prop_cats_t 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
 
foreign_lang_source and foreign_lang_source_2 keys have a language code appended to them so that multiple languages
Line 246: Line 327:  
]]
 
]]
   −
local added_prop_cats = {}; -- list of property categories that have been added to z.properties_cats
+
local added_prop_cats = {}; -- list of property categories that have been added to z.prop_cats_t
   −
local function add_prop_cat (key, arguments)
+
local function add_prop_cat (key, arguments, key_modifier)
if not added_prop_cats [key] then
+
local key_modified = key .. ((key_modifier and key_modifier) or ''); -- modify <key> with <key_modifier> if present and not nil
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
+
if not added_prop_cats [key_modified] then
table.insert (z.properties_cats, substitute (cfg.prop_cats [key], arguments)); -- make name then add to table
+
added_prop_cats [key_modified] = true; -- note that we've added this category
 +
table.insert (z.prop_cats_t, substitute (cfg.prop_cats [key], arguments)); -- make name then add to table
 +
table.insert (z.prop_keys_t, 'cs1-prop-' .. key); -- convert key to class for use in the citation's <cite> tag
 
end
 
end
 
end
 
end
Line 273: Line 356:  
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.
+
return str:gsub ('\n', ' '); -- Remove newlines as they break italics.
return str:gsub ('\n', ' ');
  −
 
   
end
 
end
   Line 366: Line 447:  
end
 
end
 
table.insert (error_list, wrap_style ('parameter', selected));
 
table.insert (error_list, wrap_style ('parameter', selected));
table.insert (z.message_tail, {set_message (error_condition, {make_sep_list (#error_list, error_list)}, true)});
+
set_message (error_condition, {make_sep_list (#error_list, error_list)});
 
end
 
end
 
 
Line 451: Line 532:  
while true do
 
while true do
 
if argument:find ("'''''", 1, true) then -- bold italic (5)
 
if argument:find ("'''''", 1, true) then -- bold italic (5)
argument, flag = argument:gsub ("%'%'%'%'%'", ""); -- remove all instances of it
+
argument, flag = argument:gsub ("%'%'%'%'%'", ""); -- remove all instances of it
elseif argument:find ("''''", 1, true) then -- italic start and end without content (4)
+
elseif argument:find ("''''", 1, true) then -- italic start and end without content (4)
 
argument, flag=argument:gsub ("%'%'%'%'", "");
 
argument, flag=argument:gsub ("%'%'%'%'", "");
elseif argument:find ("'''", 1, true) then -- bold (3)
+
elseif argument:find ("'''", 1, true) then -- bold (3)
 
argument, flag=argument:gsub ("%'%'%'", "");
 
argument, flag=argument:gsub ("%'%'%'", "");
 
elseif argument:find ("''", 1, true) then -- italic (2)
 
elseif argument:find ("''", 1, true) then -- italic (2)
Line 487: Line 568:  
error_comment = error_comment,
 
error_comment = error_comment,
 
has_accept_as_written = has_accept_as_written,
 
has_accept_as_written = has_accept_as_written,
 +
hyphen_to_dash = hyphen_to_dash,
 
in_array = in_array,
 
in_array = in_array,
 
is_set = is_set,
 
is_set = is_set,
Anonymous user