title_text = substitute ('$1-$2', { -- skip this text (individual and macro languages only)
title_text,
cfg.misc_text_t.language,
});
end
title_text = substitute ('$1 $2', { -- finish the tool tip
title_text,
cfg.make_translit_t.transliteration,
});
else
title_text = substitute ('$1 $2', { -- generic tool tip (can we ever get here?)
title_text,
cfg.make_translit_t.transliteration,
});
end
end
end  
local tag
if is_set (code) then -- when a language code is provided (always with templates, not always with )
code = code:match ('^(%a%a%a?)'); -- strip all subtags leaving only the language subtag
if not style then -- nil for the default italic style
tag = '<i lang="%s-Latn">%s</i>'
else
tag = '<span lang="%s-Latn">%s</span>' -- non-standard style, construct a span tag for it
tag = string.format(tag, style, "%s", "%s")
end
tag = string.format(tag, code, "%s")
else
tag = '<span>%s</span>' -- when no language code: no lang= attribute, not italic ( only)
end  
tag = string.format(tag, translit) -- add the translit text
if '' == title_text then -- when there is no need for a tool-tip
return tag; -- done
else
title_text = cfg.engvar_sel_t.gb == engvar and title_text:gsub ('([Rr]omani)z', '%1s') or title_text; -- gb eng when engvar specifies gb eng; us eng else
return title_wrapper_make (title_text, tag, 'span'); -- wrap with a tool-tip span and done
end
end  
--italic= template parameter so italic markup should never appear in args.text
either as *itself* or as ***bold italic*** unless |italic=unset or |italic=invert.  
local function validate_text (template, args)
if not is_set (args.text) then
return make_error_msg (cfg.validate_text_t.no_text, args, template);
end  
if args.text:find ("%f[\']\'\'\'\'%f[^\']") or args.text:find ("\'\'\'\'\'[\']+") then -- because we're looking, look for 4 appostrophes or 6+ appostrophes
return make_error_msg (cfg.validate_text_t.malformed_markup, args, template);
end  
local style = args.italic;  
if (cfg.keywords_t.unset ~= style) and (cfg.keywords_t.invert ~=style) then
if args.text:find ("%f[\']\'\'%f[^\']") or args.text:find ("%f[\']\'\'\'\'\'%f[^\']") then -- italic but not bold, or bold italic
return make_error_msg (cfg.validate_text_t.italic_markup, args, template);
end
end
end  
----------------------------< R E N D E R _ M A I N T >------------------------------------------------------  
Render mainenance messages and categories.  
local function render_maint (nocat)
local maint = {};  
if 0 < #maint_msgs then -- when there are maintenance messages
table.insert (maint, table.concat ({'<span>'})); -- opening <span> tag
for _, msg in ipairs (maint_msgs) do
table.insert (maint, table.concat ({msg, ' '})); -- add message strings
end
table.insert (maint, '</span>'); -- close the span
end  
if (0 < #maint_cats) and (0 == namespace) and not nocat then -- when there are maintenance categories; article namespace only
for _, cat in ipairs (maint_cats) do
table.insert (maint, table.concat ({''})); -- format and add the categories
end
end  
return table.concat (maint);
end  
----------------------------< P R O T O _ P R E F I X >------------------------------------------------------  
For proto languages, text is prefixed with a splat. We do that here as a flag for make_text_html so that a splat
will be rendered outside of italic markup (if used). If the first character in text here is already a splat, we
do nothing.  
proto_param is boolean or nil; true adds splat prefix regardless of language name; false removes and inhibits
regardless of language name; nil does nothing; presumes that the value in text is correct but removes extra splac.  
local function proto_prefix (text, language_name, proto_param)
if false == proto_param then -- when forced by |proto=no
return text:gsub ('^%**', ''); -- return text without splat prefix regardless of language name or existing splat prefix in text
elseif (language_name:find ('^Proto%-') or (true == proto_param)) then -- language is a proto or forced by |proto=yes
return text:gsub ('^%**', '*'); -- prefix proto-language text with a splat; also removes duplicate prefixing splats
end  
return text:gsub ('^%*+', '*'); -- return text unmolested except multiple splats reduced to one splat
end  
----------------------------< H A S _ P O E M _ T A G >------------------------------------------------------  
Looks for a poem strip marker in text; returns true when found; false else.  
Auto-italic detection disabled when text has poem stripmarker because it is not possible for this code to know
the content that will replace the stripmarker.  
local function has_poem_tag (text)
return text:find ('\127[^\127]*UNIQ%-%-poem%-[%a%d]+%-QINU[^\127]*\127') and true or false;
end  
----------------------------< H T M L _ T A G _ S E L E C T >------------------------------------------------  
Inspects content of and selectively trims text. Returns text and the name of an appropriate html tag for text.  
If text contains:
\n\n text has implied <p>..</p> tags - trim leading and trailing whitespace and return
If text begins with list markup:
\n* unordered
\n; definition
\n: definition
\n# ordered
trim all leading whitespace except \n and trim all trailing whitespace  
If text contains <poem>...</poem> stripmarker, return text unmodified and choose <div>..</div> tags because
the stripmarker is replaced with text wrapped in <div>..</div> tags.  
If the text contains any actual <div>...</div> tags, then it's again returned unmodified and <div>...</div>
tags are used to wrap it, to prevent div/span inversion.  
local function html_tag_select (text)
local tag;  
if has_poem_tag (text) then -- contains poem stripmarker (we can't know the content of that)
tag = 'div'; -- poem replacement is in div tags so lang must use div tags
elseif text:find ('<div') then -- reductive; if the text contains a div tag, we must use div tags
tag = 'div';
elseif mw.text.trim (text):find ('\n\n+') then -- contains implied p tags
text = mw.text.trim (text); -- trim leading and trailing whitespace characters
tag = 'div'; -- must be div because span may not contain p tags (added later by MediaWiki); poem replacement is in div tags
elseif text:find ('\n[%*:;%#]') then -- if text has list markup
text = text:gsub ('^[\t\r\f ]*', *):gsub ('%s*$', *); -- trim all whitespace except leading newline character '\n'
tag = 'div'; -- must be div because span may not contain ul, dd, dl, ol tags (added later by MediaWiki)
else
text = mw.text.trim (text); -- plain text
tag = 'span'; -- so span is fine
end  
return text, tag;
end  
--proto=; permitted values are yes and no; yes returns as true, no returns as false,
empty string (or parameter omitted) returns as nil; any other value returns nil with <proto_param> as second
return value for use in error message.  
local function validate_proto (proto_param)
if cfg.keywords_t.affirmative == proto_param then
return true;
elseif cfg.keywords_t.negative == proto_param then
return false;
elseif is_set (proto_param) then
return nil, proto_param; -- |proto= something other than 'yes' or 'no'
else
return nil; -- missing or empty
end
end  
----------------------------< L A N G U A G E _ N A M E _ G E T >--------------------------------------------  
Common function to return language name from the data set according to IETF tag.  
Returns language name if found in data tables; nil else.  
local function language_name_get (ietf, code, cat)
ietf = ietf:lower; -- ietf:lower because format_ietf_tag returns mixed case  
local name; -- remains nil if not found  
if override_table[ietf] then -- look for whole IETF tag in override table
name = override_table[ietf];
elseif override_table[code] then -- not there so try basic language tag
name = override_table[code];
elseif lang_table[code] then -- shift to iana active tag/name table
name = lang_table[code];
elseif lang_dep_table[code] then -- try the iana deprecated tag/name table
name = lang_dep_table[code];
end