Difference between revisions of "Module:Citation/CS1/styles.css"

From Wikispooks
Jump to navigation Jump to search
(Temporarily reduce the size)
(Replaced content with " local cs1 ={};")
Tag: Replaced
Line 1: Line 1:
  
 
local cs1 ={};
 
local cs1 ={};
 
--[[--------------------------< F O R W A R D  D E C L A R A T I O N S >--------------------------------------
 
]]
 
 
local dates, year_date_check, reformat_dates, date_hyphen_to_dash, -- functions in Module:Citation/CS1/Date_validation
 
date_name_xlate
 
 
local is_set, in_array, substitute, error_comment, set_error, select_one, -- functions in Module:Citation/CS1/Utilities
 
add_maint_cat, wrap_style, safe_for_italics, is_wikilink, make_wikilink;
 
 
local z ={}; -- tables in Module:Citation/CS1/Utilities
 
 
local extract_ids, extract_id_access_levels, build_id_list, is_embargoed; -- functions in Module:Citation/CS1/Identifiers
 
 
local make_coins_title, get_coins_pages, COinS; -- functions in Module:Citation/CS1/COinS
 
 
local cfg = {}; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration
 
local whitelist = {}; -- table of tables listing valid template parameter names; defined in Module:Citation/CS1/Whitelist
 
 
 
--[[--------------------------< P A G E  S C O P E  V A R I A B L E S >--------------------------------------
 
 
declare variables here that have page-wide scope that are not brought in from other modules; thatare created here
 
and used here
 
 
]]
 
 
local added_deprecated_cat; -- boolean flag so that the category is added only once
 
local added_prop_cats = {}; -- list of property categories that have been added to z.properties_cats
 
local added_vanc_errs; -- boolean flag so we only emit one Vancouver error / category
 
 
local Frame; -- holds the module's frame table
 
 
 
--[[--------------------------< F I R S T _ S E T >------------------------------------------------------------
 
 
Locates and returns the first set value in a table of values where the order established in the table,
 
left-to-right (or top-to-bottom), is the order in which the values are evaluated.  Returns nil if none are set.
 
 
This version replaces the original 'for _, val in pairs do' and a similar version that used ipairs.  With the pairs
 
version the order of evaluation could not be guaranteed.  With the ipairs version, a nil value would terminate
 
the for-loop before it reached the actual end of the list.
 
 
]]
 
 
local function first_set (list, count)
 
local i = 1;
 
while i <= count do -- loop through all items in list
 
if is_set( list[i] ) then
 
return list[i]; -- return the first set list member
 
end
 
i = i + 1; -- point to next
 
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 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?', '%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
 
 
 
--[[--------------------------< A D D _ V A N C _ E R R O R >----------------------------------------------------
 
 
Adds a single Vancouver system error message to the template's output regardless of how many error actually exist.
 
To prevent duplication, added_vanc_errs is nil until an error message is emitted.
 
 
added_vanc_errs is a boolean declared in page scope variables above
 
 
]]
 
 
local function add_vanc_error (source)
 
if not added_vanc_errs then
 
added_vanc_errs = true; -- note that we've added this category
 
table.insert( z.message_tail, { set_error( 'vancouver', {source}, true ) } );
 
end
 
end
 
 
 
--[[--------------------------< I S _ S C H E M E >------------------------------------------------------------
 
 
does this thing that purports to be a uri scheme seem to be a valid scheme?  The scheme is checked to see if it
 
is in agreement with http://tools.ietf.org/html/std66#section-3.1 which says:
 
Scheme names consist of a sequence of characters beginning with a
 
  letter and followed by any combination of letters, digits, plus
 
  ("+"), period ("."), or hyphen ("-").
 
 
returns true if it does, else false
 
 
]]
 
 
local function is_scheme (scheme)
 
return scheme and scheme:match ('^%a[%a%d%+%.%-]*:'); -- true if scheme is set and matches the pattern
 
end
 
 
 
--[=[-------------------------< I S _ D O M A I N _ N A M E >--------------------------------------------------
 
 
Does this thing that purports to be a domain name seem to be a valid domain name?
 
 
Syntax defined here: http://tools.ietf.org/html/rfc1034#section-3.5
 
BNF defined here: https://tools.ietf.org/html/rfc4234
 
Single character names are generally reserved; see https://tools.ietf.org/html/draft-ietf-dnsind-iana-dns-01#page-15;
 
see also [[Single-letter second-level domain]]
 
list of tlds: https://www.iana.org/domains/root/db
 
 
rfc952 (modified by rfc 1123) requires the first and last character of a hostname to be a letter or a digit.  Between
 
the first and last characters the name may use letters, digits, and the hyphen.
 
 
Also allowed are IPv4 addresses. IPv6 not supported
 
 
domain is expected to be stripped of any path so that the last character in the last character of the tld.  tld
 
is two or more alpha characters.  Any preceding '//' (from splitting a url with a scheme) will be stripped
 
here.  Perhaps not necessary but retained incase it is necessary for IPv4 dot decimal.
 
 
There are several tests:
 
the first character of the whole domain name including subdomains must be a letter or a digit
 
internationalized domain name (ascii characters with .xn-- ASCII Compatible Encoding (ACE) prefix xn-- in the tld) see https://tools.ietf.org/html/rfc3490
 
single-letter/digit second-level domains in the .org and .cash TLDs
 
q, x, and z SL domains in the .com TLD
 
i and q SL domains in the .net TLD
 
single-letter SL domains in the ccTLDs (where the ccTLD is two letters)
 
two-character SL domains in gTLDs (where the gTLD is two or more letters)
 
three-plus-character SL domains in gTLDs (where the gTLD is two or more letters)
 
IPv4 dot-decimal address format; TLD not allowed
 
 
returns true if domain appears to be a proper name and tld or IPv4 address, else false
 
 
]=]
 
 
local function is_domain_name (domain)
 
if not domain then
 
return false; -- if not set, abandon
 
end
 
 
domain = domain:gsub ('^//', ''); -- strip '//' from domain name if present; done here so we only have to do it once
 
 
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;
 
end
 
-- Do most common case first
 
if domain:match ('%f[%a%d][%a%d][%a%d%-]+[%a%d]%.%a%a+$') then -- three or more character hostname.hostname or hostname.tld
 
return true;
 
elseif domain:match ('%f[%a%d][%a%d][%a%d%-]+[%a%d]%.xn%-%-[%a%d]+$') then -- internationalized domain name with ACE prefix
 
return true;
 
elseif domain:match ('%f[%a%d][%a%d]%.cash$') then -- one character/digit .cash hostname
 
return true;
 
elseif domain:match ('%f[%a%d][%a%d]%.org$') then -- one character/digit .org hostname
 
return true;
 
elseif domain:match ('%f[%a][qxz]%.com$') then -- assigned one character .com hostname (x.com times out 2015-12-10)
 
return true;
 
elseif domain:match ('%f[%a][iq]%.net$') then -- assigned one character .net hostname (q.net registered but not active 2015-12-10)
 
return true;
 
elseif domain:match ('%f[%a%d][%a%d]%.%a%a$') then -- one character hostname and cctld (2 chars)
 
return true;
 
elseif domain:match ('%f[%a%d][%a%d][%a%d]%.%a%a+$') then -- two character hostname and tld
 
return true;
 
elseif domain:match ('^%d%d?%d?%.%d%d?%d?%.%d%d?%d?%.%d%d?%d?') then -- IPv4 address
 
return true;
 
else
 
return false;
 
end
 
end
 
 
 
--[[--------------------------< I S _ U R L >------------------------------------------------------------------
 
 
returns true if the scheme and domain parts of a url appear to be a valid url; else false.
 
 
This function is the last step in the validation process.  This function is separate because there are cases that
 
are not covered by split_url(), for example is_parameter_ext_wikilink() which is looking for bracketted external
 
wikilinks.
 
 
]]
 
 
local function is_url (scheme, domain)
 
if is_set (scheme) then -- if scheme is set check it and domain
 
return is_scheme (scheme) and is_domain_name (domain);
 
else
 
return is_domain_name (domain); -- scheme not set when url is protocol relative
 
end
 
end
 
 
 
--[[--------------------------< S P L I T _ U R L >------------------------------------------------------------
 
 
Split a url into a scheme, authority indicator, and domain.
 
 
First remove Fully Qualified Domain Name terminator (a dot following tld) (if any) and any path(/), query(?) or fragment(#).
 
 
If protocol relative url, return nil scheme and domain else return nil for both scheme and domain.
 
 
When not protocol relative, get scheme, authority indicator, and domain.  If there is an authority indicator (one
 
or more '/' characters immediately following the scheme's colon), make sure that there are only 2.
 
 
Strip off any port and path;
 
 
]]
 
 
local function split_url (url_str)
 
local scheme, authority, domain;
 
 
url_str = url_str:gsub ('([%a%d])%.?[/%?#].*$', '%1'); -- strip FQDN terminator and path(/), query(?), fragment (#) (the capture prevents false replacement of '//')
 
 
if url_str:match ('^//%S*') then -- if there is what appears to be a protocol relative url
 
domain = url_str:match ('^//(%S*)')
 
elseif url_str:match ('%S-:/*%S+') then -- if there is what appears to be a scheme, optional authority indicator, and domain name
 
scheme, authority, domain = url_str:match ('(%S-:)(/*)(%S+)'); -- extract the scheme, authority indicator, and domain portions
 
authority = authority:gsub ('//', '', 1); -- replace place 1 pair of '/' with nothing;
 
if is_set(authority) then -- if anything left (1 or 3+ '/' where authority should be) then
 
return scheme; -- return scheme only making domain nil which will cause an error message
 
end
 
domain = domain:gsub ('(%a):%d+', '%1'); -- strip port number if present
 
end
 
 
return scheme, domain;
 
end
 
 
 
--[[--------------------------< L I N K _ P A R A M _ O K >---------------------------------------------------
 
 
checks the content of |title-link=, |series-link=, |author-link= etc for properly formatted content: no wikilinks, no urls
 
 
Link parameters are to hold the title of a wikipedia article so none of the WP:TITLESPECIALCHARACTERS are allowed:
 
# < > [ ] | { } _
 
except the underscore which is used as a space in wiki urls and # which is used for section links
 
 
returns false when the value contains any of these characters.
 
 
When there are no illegal characters, this function returns TRUE if value DOES NOT appear to be a valid url (the
 
|<param>-link= parameter is ok); else false when value appears to be a valid url (the |<param>-link= parameter is NOT ok).
 
 
]]
 
 
local function link_param_ok (value)
 
local scheme, domain;
 
if value:find ('[<>%[%]|{}]') then -- if any prohibited characters
 
return false;
 
end
 
 
scheme, domain = split_url (value); -- get scheme or nil and domain or nil from url;
 
return not is_url (scheme, domain); -- return true if value DOES NOT appear to be a valid url
 
end
 
 
 
--[[--------------------------< L I N K _ T I T L E _ O K >---------------------------------------------------
 
 
Use link_param_ok() to validate |<param>-link= value and its matching |<title>= value.
 
 
|<title>= may be wikilinked but not when |<param>-link= has a value.  This function emits an error message when
 
that condition exists
 
 
]]
 
 
local function link_title_ok (link, lorig, title, torig)
 
local orig;
 
 
if is_set (link) then -- don't bother if <param>-link doesn't have a value
 
if not link_param_ok (link) then -- check |<param>-link= markup
 
orig = lorig; -- identify the failing link parameter
 
elseif title:find ('%[%[') then -- check |title= for wikilink markup
 
orig = torig; -- identify the failing |title= parameter
 
end
 
end
 
 
if is_set (orig) then
 
table.insert( z.message_tail, { set_error( 'bad_paramlink', orig)}); -- url or wikilink in |title= with |title-link=;
 
end
 
end
 
 
 
--[[--------------------------< C H E C K _ U R L >------------------------------------------------------------
 
 
Determines whether a URL string appears to be valid.
 
 
First we test for space characters.  If any are found, return false.  Then split the url into scheme and domain
 
portions, or for protocol relative (//example.com) urls, just the domain.  Use is_url() to validate the two
 
portions of the url.  If both are valid, or for protocol relative if domain is valid, return true, else false.
 
 
Because it is different from a standard url, and because this module used external_link() to make external links
 
that work for standard and news: links, we validate newsgroup names here.  The specification for a newsgroup name
 
is at https://tools.ietf.org/html/rfc5536#section-3.1.4
 
 
]]
 
 
local function check_url( url_str )
 
if nil == url_str:match ("^%S+$") then -- if there are any spaces in |url=value it can't be a proper url
 
return false;
 
end
 
local scheme, domain;
 
 
scheme, domain = split_url (url_str); -- get scheme or nil and domain or nil from url;
 
 
if 'news:' == scheme then -- special case for newsgroups
 
return domain:match('^[%a%d%+%-_]+%.[%a%d%+%-_%.]*[%a%d%+%-_]$');
 
end
 
 
return is_url (scheme, domain); -- return true if value appears to be a valid url
 
end
 
 
 
--[=[-------------------------< I S _ P A R A M E T E R _ E X T _ W I K I L I N K >----------------------------
 
 
Return true if a parameter value has a string that begins and ends with square brackets [ and ] and the first
 
non-space characters following the opening bracket appear to be a url.  The test will also find external wikilinks
 
that use protocol relative urls. Also finds bare urls.
 
 
The frontier pattern prevents a match on interwiki links which are similar to scheme:path urls.  The tests that
 
find bracketed urls are required because the parameters that call this test (currently |title=, |chapter=, |work=,
 
and |publisher=) may have wikilinks and there are articles or redirects like '//Hus' so, while uncommon, |title=[[//Hus]]
 
is possible as might be [[en://Hus]].
 
 
]=]
 
 
local function is_parameter_ext_wikilink (value)
 
local scheme, domain;
 
 
if value:match ('%f[%[]%[%a%S*:%S+.*%]') then -- if ext wikilink with scheme and domain: [xxxx://yyyyy.zzz]
 
scheme, domain = split_url (value:match ('%f[%[]%[(%a%S*:%S+).*%]'));
 
elseif value:match ('%f[%[]%[//%S+.*%]') then -- if protocol relative ext wikilink: [//yyyyy.zzz]
 
scheme, domain = split_url (value:match ('%f[%[]%[(//%S+).*%]'));
 
elseif value:match ('%a%S*:%S+') then -- if bare url with scheme; may have leading or trailing plain text
 
scheme, domain = split_url (value:match ('(%a%S*:%S+)'));
 
elseif value:match ('//%S+') then -- if protocol relative bare url: //yyyyy.zzz; may have leading or trailing plain text
 
scheme, domain = split_url (value:match ('(//%S+)')); -- what is left should be the domain
 
else
 
return false; -- didn't find anything that is obviously a url
 
end
 
 
return is_url (scheme, domain); -- return true if value appears to be a valid url
 
end
 
 
 
--[[-------------------------< C H E C K _ F O R _ U R L >-----------------------------------------------------
 
 
loop through a list of parameters and their values.  Look at the value and if it has an external link, emit an error message.
 
 
]]
 
 
local function check_for_url (parameter_list)
 
local error_message = '';
 
for k, v in pairs (parameter_list) do -- for each parameter in the list
 
if is_parameter_ext_wikilink (v) then -- look at the value; if there is a url add an error message
 
if is_set(error_message) then -- once we've added the first portion of the error message ...
 
error_message=error_message .. ", "; -- ... add a comma space separator
 
end
 
error_message=error_message .. "&#124;" .. k .. "="; -- add the failed parameter
 
end
 
end
 
if is_set (error_message) then -- done looping, if there is an error message, display it
 
table.insert( z.message_tail, { set_error( 'param_has_ext_link', {error_message}, true ) } );
 
end
 
end
 
 
 
--[[--------------------------< S A F E _ F O R _ U R L >------------------------------------------------------
 
 
Escape sequences for content that will be used for URL descriptions
 
 
]]
 
 
local function safe_for_url( str )
 
if str:match( "%[%[.-%]%]" ) ~= nil then
 
table.insert( z.message_tail, { set_error( 'wikilink_in_url', {}, true ) } );
 
end
 
 
return str:gsub( '[%[%]\n]', {
 
['['] = '&#91;',
 
[']'] = '&#93;',
 
['\n'] = ' ' } );
 
end
 
 
 
--[[--------------------------< E X T E R N A L _ L I N K >----------------------------------------------------
 
 
Format an external link with error checking
 
 
]]
 
 
local function external_link( URL, label, source, access)
 
local error_str = "";
 
local domain;
 
local path;
 
local base_url;
 
 
if not is_set( label ) then
 
label = URL;
 
if is_set( source ) then
 
error_str = set_error( 'bare_url_missing_title', { wrap_style ('parameter', source) }, false, " " );
 
else
 
error( cfg.messages["bare_url_no_origin"] );
 
end
 
end
 
if not check_url( URL ) then
 
error_str = set_error( 'bad_url', {wrap_style ('parameter', source)}, false, " " ) .. error_str;
 
end
 
 
domain, path = URL:match ('^([/%.%-%+:%a%d]+)([/%?#].*)$'); -- split the url into scheme plus domain and path
 
if path then -- if there is a path portion
 
path = path:gsub ('[%[%]]', {['[']='%5b',[']']='%5d'}); -- replace '[' and ']' with their percent encoded values
 
URL = table.concat ({domain, path}); -- and reassemble
 
end
 
 
base_url = table.concat({ "[", URL, " ", safe_for_url (label), "]" }); -- assemble a wikimarkup url
 
 
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
 
end
 
 
return table.concat ({base_url, error_str});
 
end
 
 
 
--[[--------------------------< D E P R E C A T E D _ P A R A M E T E R >--------------------------------------
 
 
Categorize and emit an error message when the citation contains one or more deprecated parameters.  The function includes the
 
offending parameter name to the error message.  Only one error message is emitted regardless of the number of deprecated
 
parameters in the citation.
 
 
added_deprecated_cat is a boolean declared in page scope variables above
 
 
]]
 
 
local function deprecated_parameter(name)
 
if not added_deprecated_cat then
 
added_deprecated_cat = true; -- note that we've added this category
 
table.insert( z.message_tail, { set_error( 'deprecated_params', {name}, true ) } ); -- add error message
 
end
 
end
 

Revision as of 04:31, 8 August 2019

Documentation for this module may be created at Module:Citation/CS1/styles.css/doc


local cs1 ={};