Modulo:pate
Aspekto
MODULO | ||
Memtesto disponeblas sur la paĝo Ŝablono:pate. |
- Ĉi tiu modulo efektivigas laboron de ŝablono
{{pate}}
. - Ĝi ne dependas de iuj moduloj aŭ ŝablonoj, sed dependas de bildo Return arrow.svg ( ).
--[===[
MODULE "PATE" (proxy for analysis of template output)
"id.wikipedia.org/wiki/Modul:Pate" <!--2024-Aug-29-->
"id.wiktionary.org/wiki/Modul:pate"
"eo.wikipedia.org/wiki/Modulo:Pate"
"eo.wiktionary.org/wiki/Modulo:pate"
Purpose: calls a template indirectly with various extra features
in order to help debugging and documentation
Utilo: alvokas sxablonon nerekte kun diversaj aldonaj funkcioj
por helpi al sencimigado kaj dokumentado
Manfaat: melakukan panggilan templat secara tidak langsung dengan
bermacam-macam fungsi tambah supaya membantu penghilangan
kekutu dan dokumentasi
Syfte: anropar en mall indirekt med diverse extra funktioner ...
Used by templates / Uzata far sxablonoj:
* only "pate" (not to be called from any other place)
Required submodules / Bezonataj submoduloj /
Submodul yang diperlukan / Behoevda submoduler:
* NONE
Required images:
* "File:Return arrow.svg", Public Domain
Name: "pate" is an abbreviation of "PAnggilan TEmplat" = "template
call", idea born 2018-Dec at ID wikipedia, alternatively
"Proxy for Analysis of TEmplate output"
This module can accept parameters whether sent to itself (own frame) or
to the caller (caller's frame). If there is a parameter "caller=true"
on the own frame then that own frame is discarded in favor of the
caller's one.
Incoming: * one anonymous and obligatory parameter:
* target, can be one of 4 types (3 detected by content, one
activated by "nsm=2"):
* bare name of the target template or module, no walls,
no parameters
* complete call to the target template or module with
parameters, protected by rectangular brackets, at least
one wall required, requires triplebracket workaround if
inner {{ ... }} are present
* more than call, or wikitext containing calls to multiple
templates, or call to one template + something more, or
just something else, "raw mode", protected by rectangular
brackets, activated by "nsm=2", requires triplebracket
workaround if inner {{ ... }} are present
* special value
* special value ":top" begins the HTML table (incl title row)
* special value ":end" ends the HTML table
* notes:
* unless with "nsm=2" for target name the default "Template:" or
"Templat:" prefix can be omitted, other namespace prefix is
possible, extra colon for namespace ZERO is NOT permitted,
use "zer=1" instead
* calling a module is possible, use the "mod=" parameter
* complete call must be enclosed in double rectangular brackets
"[["..."]]" instead of traditional double curly brackets
"{{"..."}}" used for direct calls, inner wikilinks
with rectangular brackets permitted
* if no wall is present then double rectangular
brackets are prohibited, a violation like
{{#invoke:pate|ek|[[mall-test]]|sel=111-111}} gives #E04
* length 1...10'000 octet:s
* 14 named and optional parameters:
* list: tab= sel= tit= war= bor= mod= zer= nsm= tag=
rem= ref= reg= hlt= ncf=
* notes:
* some are relevant for special work ":top" too, namely
"sel=" "tit=" "war=" "bor="
* none are relevant for ":end"
* "tab=" HTML table type, prohibited for special work, one
digit, can be "0"..."5", default is "2":
* "0" raw style, do NOT add any table elements (gives #E40
if parameter "sel=" requests more than 1 table cell)
* "1" brew one or several table cells with "<td>" and "</td>"
but no "<tr>" and "</tr>" (this is rarely useful)
* "2" brew one or several table cells with "<td>" and "</td>"
together inside a table row delimited by "<tr>" and "</tr>"
* "3" generate a complete horizontal table with 1+1 rows (one
row for titles, one row for one target) and 1...6 columns
* "4" generate a complete horizontal table with 1 row only
(no titles, one target) and 1...6 columns
* "5" generate a complete vertical table with 1+1 columns
(one column for titles, one column for one target) and
1...6 rows (this is useful for "big" target templates)
* "sel=" control string for cells, 7 characters, 6 values, data
types boolean tristate fourstate, for "tab=0" the default is
"010-000" (show only parsed result), otherwise for "tab<>0"
it is "111-110" (show all except debug), value "000-000"
prohibited, see below under "Misc technical stuff", the values
(left to right) correspond to:
* X..-... # calling code, with link to the target template if
"call" not same page, showed even if the template doesn't
012 exist, the link can be red, with all parameters,
text without link if same page, value "1" to enable,
"2" for small text
* .X.-... # parsed result from the target template (called
"parsed" with all possible example parameters and hidden
01 parameters) displayed, or whining if problem (target
not found, returned empty (ZERO octet:s), returned
invalid (see below) content)
* ..X-... # remark ie extra usage information from parameter
"rem" "rem=", or placehodler string "--" if not supplied,
01 showed even if target not found
* ...-X.. # links to categories resulting from category
"cat" insertions generated by the template with sorting
012 hints (every of them split into 2 lines, all
categories are counted, up to 12 listed), or
whining if problem, value "1" to enable, "2"
to omit sorting hints
* ...-.X. # links to list of backlinks and redirects to the
"back" target template (showed even if template is not
01 found, as links to these services cannot be red)
* ...-..X # technical information for debug purposes including
"debug" bloat of the result brewed by the template,
0123 findings, full raw wikitext (always unparsed, either
simple "hard nowiki" or coloured "hard nowiki" or
coloured map), fourstate ("0" omit column, "1" show
per simple "hard nowiki", "2" show per coloured
"hard nowiki", "3" show map)
* "tit=" defines the titles for the table, 1...6 title strings
attached together by double at-signs "@@", relevant if the
anonymous parameter is ":top" or the "tab=" parameter is
"3" or "5", otherwise ignored, the default or specified
"sel=" value determines the size of the table, only selected
columns (for "tab=3" "sel=100-003" and "tit=calling@@insanity"
there will be 2 columns, the latter one named "insanity"
containing the debug map), superfluous title strings are
ignored, missing ones are replaced by default names hardcoded
in "contabcolumns", total length 1...200, equal sign "=" and
wall "|" are problematic, LF illegal, [[...]] illegal, <b> and
<br> legal
* "war=" table line color, always 6 hex digits without
cross "#", default is "60A0A0" AKA bluegreen
* "bor=" CSS "border:" value, legal range "05" ... "80" becomes
"0.05em"..."0.80em", default is "20" becoming "0.20em",
always 2 digits
* "mod=" target is a module, value is the name of function ("1"
prohibited), prohibited for special work, prohibited together
with "zer=1", prohibited for "nsm=2"
* "zer=1" allow target in ns ZERO (prefix for ns 10 will NOT
get added, instead check whether it indeed is in ns ZERO),
prohibited for special work, prohibited together with
"mod=", prohibited for "nsm=2"
* "nsm=" activate workaround for nested template calls or raw
mode, "1" to enable triplebracket workaround, "2" for
raw mode, prohibited for special work, see "Notes on
protection" below
* "tag=1" activate ne-workaround for aggressive tags and
replace for example "<nonewiki>" <--> "<nowiki>", see
below under "Misc technical stuff"
* "rem=" remark ie extra usage information for the target
template or given case, undergoes same translation as the
call target parameter, length 1...1000, equal sign "=" and
wall "|" are problematic, LF illegal, [[...]] legal, <b>
and <br> legal, prohibited for special work
* "ref=" eat away references, name of group or "1" for default one
* "reg=" eat away references, name of group or "1" for default one
* "hlt=1" send "trackingcategorieshiglow=true" to the target
and activate bypassing, prohibited for special work, note that
literal "trackingcategorieshiglow=true" sent into "pate" will
NOT work, see below "Notes on tracking categories"
* "ncf=1" (deprecated) send "nocat=false" to a legacy target
template, prohibited for special work, note that literal
"nocat=false" will NOT work, see below "Notes on category
suppression"
Returned: * large and complicated string as documented below, may or may
not contain part of a HMTL table or a complete such
Restrictions for incoming strings:
* risks and needs
* LF is prohibited (LF + star "*" or LF + cross "#" would break layout,
use <br> instead)
* "[http" is prohibited
* <b> and <br> are legal
* list with parameters:
* "tit="
* 1...6 title strings attached together by double at-signs "@@"
* total length 1...200 (all up to 6 strings plus all double at-signs)
* equal sign "=" and wall "|" are problematic (see below
under "Notes on protection")
* LF illegal
* [[...]] illegal
* <b> and <br> legal
* plain cross "#" at begin is safe (such as "#T99") ie no
wiki-like-begin-of-line-specific rules apply
* "rem="
* undergoes very same translation as the call target parameter
controlled by "nsm=" and "tag=1"
* length 1...1000
* equal sign "=" and wall "|" are problematic (see below
under "Notes on protection")
* LF illegal
* [[...]] legal
* <b> and <br> legal
* plain cross "#" at begin is safe (such as "#T99") ie no
wiki-like-begin-of-line-specific rules apply
------------------------------------------------------------------------
### Usage (user manual)
Features:
* calls a target (usually template) and separates cat insertions
from remaining wikitext, thus performs category suppression, provided
on one place for all templates in a wiki
* drastically simplifies tasks like template and module documentation and
self-testing, template debugging, listing of multiple template results
(like userboxes) in a table, provides easy linking to templates
with parameters
* completely replaces all other legacy category suppression tricks (except
title page rule) thus greatly simplifies template design and reduces
risk of miscategorizations
* allows to show the generated category insertions including sorting hints
* can handle hidden parameters (special parameters that can pretend to the
target facts that it detects and depends on, like pagename, namespace,
protection level, preview-vs-submit, existence of a file or page,
date, ...)
* preserves the sortorder and formatting of parameters
* works with misplaced templates ie templates in other namespaces
such as "User:" (still namespaces 14 "Category:" as well as 6 and -2
"File:" and "Media:" are prohibited), works even for target in ns
ZERO (needs "zer=1")
* can usually work even with legacy templates internally still relying
on legacy category suppression tricks
* can handle nested template calls (needs "nsm=1")
* can call a module too (so far only usable for modules callable from
templates, ie not those callable only from other modules)
* can "fire" and analyze wikitext consisting of more than just one
template call (needs "nsm=2")
* can handle template calls containing some aggressive tags in
parameters (needs "tag=1")
* accepts most of same and less sane content that templates can generate,
can handle "<pre>" and HTML comments there
* can handle references generated by the target in a decent and useful
manner, see below "Notes on references"
* detects and reports various errors in output from templates, severe
errors result in early rejection ie no separation, but still at least
partial report
Limitations and caveats:
* uncommon syntax of the template call with double rectangular brackets
(note: this is due to some rules or priciples in the MediaWiki parser
that are old and inherent, thus this will NOT get "fixed" to "standard"
double curly brackets, see below "Notes on protection")
* uncommon syntax of nested inner template calls using the triplebracket
workaround {({ })} (same here, this will NOT get "fixed" to "standard"
double curly brackets)
* uncommon syntax of some aggressive tags such as references or galleries
using the ne-workaround (same here, this will NOT get "fixed" to any
"standard" form)
* uncommon syntax of the hidden forwarded parameters by using "*HIDDEN*"
instead in the equal sign "="
* nested template calls will NOT work out of the box since the innermost
template is expanded at the earliest, but there is a solution
(triplebracket workaround), see above as well as below "Notes on protection"
* some aggressive tags such as references or galleries passed as template
parameters don't work out of the box, but there is a solution
(ne-workaround), see above as well as below "Notes on protection"
* intermediate type template parameters ie holes in anonymous parameter
chain are not supported (for example "{{mytemplate|junk|4=green}}" is bad) !!!FIXME!!! is this true at all ??
* there is NO LIMIT for number of forwarded parameters, but there is a
size limit max 10'000 octet:s resulting in a theoretical limit a bit
below 5'000 anonymous parameters, note that chess needs only slightly
more than 64 parameters for a standard chessboard
* equal sign "=" and wall "|" are prohibited (must be html-dec-encoded) in
title strings (parameter "tit=") and remark (parameter "rem=") (limitation
comes from the wiki parser), and several titles have to be separated by
"@@" and must NOT be empty
* due to MediaWiki parser again, testing broken call syntax like {{doit|}}
is a problem, written as [[doit|]] it gets victim of the "pipe trick",
but there is a solution, see below "Notes on protection"
* may cause problems with some legacy templates (try the "ncf=1"
ie "nocat=false" trick)
* fires one expensive request and thus must be used less than 500 times !!!FIXME!!!
on one page
* some aggressive tags rarely output by templates result in strip markers
showed and detected here (but no strip markers arise if the content
comes from a module), they make debug output less informative but parsed
output still looks OK, see also "Notes on protection" and "Notes on
references" below
* <syntaxhighlight lang="text"> does not work (rejected as error) !!!FIXME!!!
* "<nowiki>" does NOT work (rejected as error), note that "<nowiki>" does !!!FIXME!!!
NOT work at all in output from a module thus modules must NOT emit such
content even if "pate" is not involved, still "<nowiki>" could be useful
in output from an old-style template, for now <nowiki> is prohibited,
<pre> works strangely when coming from a module but we fix it
* augmented <pre> such as <pre style="overflow:auto;"> does not work, other
augmented tags don't work either (still augmented <ref> works mostly)
* upperCASE and malformed tags such as "<NOWIKI>" or "<nowiki >" don't work !!!FIXME!!!
* some templates output stuff such as "[[]]" or "[[ ]]" as part of well
useful mesages like
rectangular brackets [[ ]] are prohibited in parameter "qq="
that will cause an error in "pate", to fix this the target template
should use the "FSI-workaround" like this
rectangular brackets [⁨[ ]⁨] are prohibited in parameter "qq="
Notes on protection:
* this is about passing parameters into templates only
* problems:
* the MediaWiki parser has an inherent and old principle "expand and
process from inside outwards", this means that for example with
{{umbox|text=NO WE{{br}}CAN'T}}
the outer template "umbox" will NOT find "{{br}}" in the incoming
parameter, instead it gets the result of expansion such as "<br>",
"(Breton)" or similar
* some aggressive tags in template parameters ar problematic, for
example with
{{umbox|text=There is a God <ref>The Bible</ref>.}}
the template will NOT find "<ref>" in the incoming parameter, instead it
gets a useless strip marker, and the relevant text "The Bible" is gone too
* some char:s, most notably equal sign "=" and wall "|", are problematic
in template calls, while particularly the equal sign is common in url:s,
the traditional workarounds are parser functions {{=}} and {{!}}
(note the exclam instead of wall in the latter) and html-dec-encoding
"=" and "|"
* those principles are bad for "pate" and thus we must workaround them,
otherwise the concept of "pate" will NOT work at all
* workarounds:
* the main always active workaround is to place the forwarded template
call into double rectangular brackets like
[[umbox|text=NO WE CAN'T]]
for
{{umbox|text=NO WE CAN'T}}
and that way "protecting" plain walls and equal signs used to delimit
template parameters from premature effect (it does not protect
from expansion of {{=}} and {{!}} though)
* in some cases further layers of protection must be added:
* for nested templates such as
{{umbox|text=NO WE{{br}}CAN'T}}
we must prevent premature expansion of {{br}}, the way
to do it is called triplebracket workaround used like this
[[umbox|text=NO WE{({br})}CAN'T]]
and let "pate" replace triplebrackets {({...})} by ordinary {{...}}
after they have been smuggled in behind the back of the parser,
the "nsm=1" or "nsm=2" parameter activates this workaround
* for some aggressive tags in parameters (pre, nowiki, ref, gallery), we
have to use the ne-workaround and write for example <renef>...</renef>
and let "pate" fix it back to <ref>...</ref>, this is activated by
"tag=1" independently of "nsm="
* when forwarding broken call syntax like {{doit|}} written as [[doit|]]
it gets victim of the "pipe trick" highly undesirable in the context,
again, "nsm=2" helps ("nsm=1" is insufficient), write [[{({doit|})}]]
* those workarounds are applied to the target parameter as well as to "rem="
since it can be desirable to write things like "<gallery> can be used"
or "bad use, <gallery> is prohibited"
* there is an alternative way to protect
{{umbox|text=NO WE{{br}}CAN'T}}
and
{{umbox|text=NO WE{{=}}CAN'T}}
and
{{umbox|text=my <gallery>Hole.svg</gallery> hole}}
namely using "<noinclude/>" this way:
{{umbox|text=NO WE{<noinclude/>{br}<noinclude/>}CAN'T}}
and
{{umbox|text=NO WE{<noinclude/>{=}<noinclude/>}CAN'T}}
and
{{umbox|text=my <gal<noinclude/>lery>Hole.svg</gal<noinclude/>lery> hole}}
with the advantage that the trick is native to MediaWiki not needing
"nsm=" or "tag=1", and the disadvantage of very long and unreadable text
* with "pate" in forwarded parameters inside [[ ]] parser functions {{=}}
and {{!}} DO NOT WORK as possibly desired, they give same bad result as
raw "=" and "|", valid solutions are either "=" and "|", or
modified {({=})} and {({!})} together with "nsm=1" or "nsm=2"
* with "pate" in "rem=" both parser functions {{=}} and {{!}} and
html-dec-encoding do work as desired
Notes on category suppression:
* All active cat insertions are carefully cut out from the output coming from
the target, whereas links to categories such as "[[:Category:Chemistry]]"
and commented-out cat insertions are kept. This works even for malformed
cat insertions with wrong letter case or redundant spaces, untranslated
prefix "Category:" on non-English wikis, and cat insertions with
sorting hints.
* The target template should NOT use any other type of category
suppression like the infamous "CategoryHandler", namespace detection,
"nocat=" parameter, or similar tricks. Reasonably behaving legacy
templates have a good chance to work with "pate", though (try the
"ncf=1" ie "nocat=false" trick).
* Do NOT submit "nocat=" or similar into this template, neither directly, nor
indirectly ie via the [[...]]-protected parameter (ordinary or hidden via
*HIDDEN*) intended for target template. Doing so in any of those manners
(as long as the name is "nocat") is an error. If the "ncf=1" ie
"nocat=false" trick is used then "nocat=false" will be sent to the
target template.
* The target template still may avoid categorizing when finding itself
on the title page, but even here there is a better way: send the
transclusion through "pate" with "nsm=2", or through other module
"Suppress Categories" limited to the core task category suppression.
Notes on tracking categories:
* A tracking category is there to collect pages suffering from a certain
type of problem, or even technical feature.
* Tracking categories are (non-technically) separated from content
categories of a wiki, and may be hidden, or not created ie kept red.
* Insertion into a tracking cat is done either by MediaWiki, or by
templates and modules.
* Usually a tracking cat is populated by pages (articles, lemmas, even
appendixes) using a temlate in a wrong way. "pate" perfectly supports
this use, and allows to check that the tracking categorization works
as supposed. Then templates and modules do NOT have to bother at all
with "nocat" nor "pate".
* Rarely there is a need for a tracking cat collecting high level templates
using a low level template in a wrong way. This is more difficult to
accomplish, since we do NOT want that pages using the broken high level
template "get caught" too. "pate" has a solution for this in the form
of "hlt=1" that sends "trackingcategorieshiglow=true" to the target
and activates bypassing. Then the low level template must help "pate"
in following way:
* evaluate the parameter "trackingcategorieshiglow=true"
* if this is NOT true, do NOT emit the tracking cat insertions
* if this applies, then do emit the tracking cat insertions, but
embed EVERY SINGLE such (of not many anyway) in:
* <span title="bypass-pate">
* </span>
for example like this:
* <span title="bypass-pate">[[Kategori:Tracking-ubx-text-too-long]]</span>
If "hlt=1" is used then "pate" will find those markers and bypass the
strict cat suppression, if favor of BOTH displaying the tracking cat,
AND letting the page get caught into it, exactly as intended. This method
is not as trivial and straightforward as one might dream of, but it is
still the probably easiest approach, and definitely better than the legacy
way ie "CategoryHandler" (ns detection + caller detection + whitelists +
blackists + greylists + ...) + "nocat" + overuse of <includeonly> +
other obscure tricks.
Notes on namespaces:
* the "Template:" namespace is the preferred one for templates
* per MediaWiki it is possible to transclude pages in other namespaces
including ns ZERO
* MediaWiki adds automatically the ns prefix "Template:" to template calls
per {{...}} if no other prefix is present, for ns ZERO the title must be
prefixed with an extra colon ":"
* "pate" supports other namespaces including ns ZERO, the extra colon
must NOT be fed into "pate" since it is added automatically if needed
* some namespaces are prohibited by "pate", most notably "Category:" and
"File:", they cannot be used in the anonymous and obligatory parameter,
a violation gives #E05
Notes on references:
* templates can theoretically generate references, this is a troublesome
habit, but there are templates around that indeed do so
* for reasons hardcoded into MediaWiki, "pate" cannot detect or capture
accumulated references, but it can let MediaWiki dump them below the
parsed result if manually instructed to do so
* there can be several groups of references
* failure to request MediaWiki harvest the default group results in it
being dumped at the bottom of the screen in an uncontrolled manner
* failure to request MediaWiki harvest any additional group results in
a red error message displayed at the bottom of the screen
* the parameter "ref=" of "pate" can be used if the template generates
references, failure to use it results in a messy output, if it is used
then there must NOT be any accumulated references from before, parameter
"reg=" is for an additional group
* for reasons hardcoded into MediaWiki, passing the syntax <ref>...</ref>
in a template parameter is a problem and causes a mess (strip markers),
this can affect the target template or a possible inner nested template,
the only solution is "tag=1" hiding the tag from the MediaWiki parser, see
above "Notes on protection"
------------------------------------------------------------------------
### Mapping of wikitext
The mapping is performed by "lfhparsemap" and is a crucial step towards
a reliable parsing. See separate document "Mapping of wikitext" for a deeper
explanation. The map essentially reveals for every position in a piece of
wikitext what type of content is located there: plain wikitext, inside
wikilink of specified depth, inside template call (not used here), inside
HTML comment, inside "nowiki", etc.
Some of such content areas are nestable:
* wikilink [[ ]]
* template call {{ }}
* seizure of template parameter {{{ }}}
Whereas others are not:
* external HTTP link [http ... ]
* nowiki
* pre
* HTML comment "<!--" ... "-->"
* ...
For the mapping the following area types are defined:
* #A00 0 ordinary plain wikitext no link
* 1...9 wikilink of given depth
* #A14 14 strip marker listed pre nowiki ref references !!!FIXME!!! not yet
* #A15 15 strip marker other
* #A17 17 "<syntaxhighlight"
* #A22 22 pre
* #A23 23 nowiki
* #A24 24 ref
* #A27 27 HTML comment "<!--" ... "-->"
* #AFF 255 invalid
Here we fully ignore:
* template call {{ ... }}
* seizure of template parameter {{{ ... }}}
* external HTTP link [http ... ]
Nested wikilinks are inherently dubious, but MediaWiki does not discourage
them sufficiently vigorously. They appear particularly in image syntax
with depth 2, and that's the limit we tolerate for ordinary links, still
a cat insertion on a level different from ONE is unacceptable. Since we
ignore template calls and template parameters, we could happen to miscount
the levels of [[ ]], but a template generating such stuff is an error anyway.
MediaWiki will handle many types of areas and nesting in a particular
way. For example comments can get stripped off during some types of
transclusion (most notably the "frame" service "preprocess"), but kept
in other contexts (most notable dumping the content of a template
onto a wiki page by means of "subst:"). This happens irrespective
whether located inside links and cat insertions
[[Category:Chemis<!--don't-->try]] or elsewhere.
"lfhparsemap" returns a nested table containing 3 subtables:
* [0] findings ie status fields #M?? (see list below)
* [1] main map of area types
* [2] boundary map with tristate flags
We map in two different contexts:
* the incoming target parameter (also being wikitext) is
mapped to "tabinparmap" in order to:
* detect and reject strip markets giving #E46
* reliably detect "nocat=" and "trackingcategorieshiglow=" prohibited there !!!FIXME!!! not yet
* reliably detect unbalanced [[ ... ]] !!!FIXME!!! not yet
* the output from expansion (also being wikitext) is
mapped to "tabutparmap" in order to:
* perform category suppression
* brew the debug map if requested
The full nested table of mapping output is handled by:
* lfhparsemap -- brew
* lfhtablewithmap -- read only
* lfysplitkat -- read only
Only the subtable [0] of mapping output is used by:
* lfhreportfindings -- read only
Note that on error the main map and the boundary map can be incomplete
ie contain type "nil" in some positions (particularly relevant for the
main map, whereas the boundary map is mostly full of "nil" anyway).
------------------------------------------------------------------------
### Error handling and statuses
* this module CANNOT produce insertions to a tracking category
* missing target template, or existing template returning empty or garbage
is NOT fatal, partial results (in a table if requested) will be showed
* red error-like text coming from the target template is possible
and considered as ordinary output
Error codes in "numerr" (order: tab= sel= tit= war= bor= mod= zer= !!!FIXME!!! move up error codes (#E00...#E12 reserved)
nsm= tag= rem= ref= reg= hlt= ncf=):
* #E01 internal
* #E02 unknown param fed in !!!FIXME!!! not detected
* #E03 obviously bad anon param (some problems land in #E04 instead)
* #E04 bad use of [[ | ]] [ ] in anon param
* #E05 bad or nonstandard target title or ns (on wikipedia this typically
results from wrong capitalization, ie "Mall:bo" instead of "Mall:Bo")
* #E06 named parameter used together with ":end" !!!FIXME!!! detect all
* #E07 named parameter other than sel=, tit=, !!!FIXME!!! detect all
war=, bor= used together with ":top"
* #E08 "tab=" bad
* #E21 "sel=" bad
* #E23 "tit=" bad (contains LF, [[...]], ...)
* #E25 "war=" bad
* #E26 "bor=" bad
* #E28 "mod=" bad (equal "1", ...)
* #E29 "zer=" bad (other than "0" or "1", also for target NOT in ns ZERO)
* #E31 "nsm=" bad
* #E32 "tag=" bad
* #E34 "rem=" bad (contains LF, ...)
* #E35 "ref=" "reg=" bad (both same, "reg=" without "ref=", ...)
* #E36 "hlt=" bad
* #E37 "ncf=" bad
* #E40 "sel=" conflicts with "tab=" since no raw with multiple columns
* #E41 "mod=" and "zer=1" must NOT be used together
* #E43 "trackingcategorieshiglow=" sent into "pate"
* #E44 "nocat=" sent into "pate"
* #E46 strip marker detected in incoming target parameter
* #E48 hidden parameter contains double brackets [[ ]] {{
* #E49 *HIDDEN* without preceding wall "|"
Status codes from expand mm ie "arxframent:preprocess" mm in "numpexpasta":
* #X00 NOT attempted yet
* #X01 exists but expand NOT attempted yet
* #X70 success
* #X80 target (template or page) does NOT exist
* #X81 no string ie expand failure
* #X82 empty string from expansion by "arxframent:preprocess", note that
a size of ONE is perfectly valid, no chance for a cat insertion,
but consider for example the old template {{=}}
Status fields from parse&map done in sub "lfhparsemap" stored
in "tabutparmap" subtable [0]:
* [0] #M00 mapping attempted
* [1] #M01 unclosed inactive area (no other discovery possible)
* [2] #M02 unclosed strip marker (impossible unless deliberately
constructed) (no other discovery possible)
* [3] #M03 unbalanced [[ ]] in active areas (no other discovery possible)
* [4] #M04 strip markers (pre nowiki ref references) !!!FIXME!!!
* [5] #M05 strip markers (other)
* [6] #M06 "<syntaxhighlight" ...
* [8] #M08 pre
* [9] #M09 nowiki
* [10] #M10 ref
* [11] #M11 HTML comment "<!--","-->"
* [12] #M12 <includeonly>,</includeonly>,<onlyinclude>,</onlyinclude>, !!!FIXME!!!
<noinclude>,</noinclude> detected
* [20] #M20 max wikilink depth (counting aborts at 9->10, special value 97
denotes an underflow error, and special value 98 denotes
an overflow error)
* [22] #M22 treacherous space attached to inner side of double rectangular
brackets "[[ " and " ]]", different from #S02
Do NOT use extraneous spaces in cat insertions:
[[Category:Crime]] OK
[[Category: Crime]] bad, accepted with complaint #S02
[[Category: Crime]] rejected by "lfysplitkat" with #S27
[[Category :Crime]] bad, will fail to find the category
[[ Category:Crime]] rejected by "lfhparsemap" with #M22
[[ Category:Crime]] rejected by "lfhparsemap" with #M22
[[Category:Crime ]] rejected by "lfhparsemap" with #M22
Do NOT put cat insertions on a level different from ONE:
[[Category:Crime]] OK
[[Category:Crime|Crime]] OK
[[CRIME|indeed [[Category:Crime]] yes we can]] bad
Status codes from split ie "lfysplitkat" in
"numzsplitsta" ZERO OK vs 2...6 (non-fatal) vs 20...40 (fatal):
* #S00 OK
* #S02 single extra space attached after colon (still split success,
different from #M22)
* #S03 empty cat hint "[[Category:|]]" or "[[Category:| ]]" (still split
success, former fault apparently cannot even be created by
ordinary wiki editing)
* #S20 split NOT attempted due to other #M06 #M09 #M12 or or #M22 !!!FIXME!!!
* #S21 split NOT attempted due to nesting #M01 #M02 #M03 #M20>2
* #S23 broken wikilink lacking left part "[[]]" or like "[[|crap]]"
* #S24 cat insertion on level different from ONE
* #S25 invalid title (empty "[[Category:]]" etc)
* #S27 more than one space "[[Category: Crap]]" !!!FIXME!!!
------------------------------------------------------------------------
### Alignment, centering, newline-sensitivity, overlong lines
The alignment is fixed for the sake of simplicity.
The whole big table is positioned left on the screen,
outside left, CSS "margin:0.6em;" (this is top).
Text is centered in all cells of the title row
"call", "parsed", "rem", "cat", "back", "debug".
Text is theoretically centered in all content cells, but this
is later workarounded in some cells:
* in "call" an inner table outside left inside left "lfipretable"
* in "parsed" an inner <div> (NOT table) outside left inside
left hog full width "lfilefqdivqlefqtxt"
* in "cat" an inner table only if more than 2 cat:s "lficenqtabqlefqtxt"
via "lfhtabletohtmllista" outside center inside left, other
text above centered
* in "debug" upper text centered, findings via "lfhtabletohtmllista"
outside center inside left, finally lower text either "hard nowiki"
outside center inside left, or map with table outside center
inside many small cells
In "call" we need left alignment because this is how code is always showed.
In "parsed" we need left alignment for both text and block elements because
that is the default behaviour of wiki that we mimic there. Further we need
a newline before the generated content to make sure that "#" ":" "*" and
wikitables do work as supposed, again we mimic default behaviour. This
newline does NOT consume any vertical space due to the "single LF in HTML
is ignored" rule.
In "rem" we do NOT add any newline thus no begin-of-line-specific
rules apply.
In "cat" there is NO risk of overlong lines due to underscores "_" since
we standardize the titles by means of "lfwsplit3title" which includes
replacing of underscores by spaces.
In "debug" we can get overlong lines due to underscores "_" but this doesn't
matter since overlong lines appear there anyway an we force-break them.
------------------------------------------------------------------------
### Misc technical stuff
We do NOT use any "pairs" in this module.
Parameter "sel=" (6 + 1 digits):
* for "tab=0" the default is "010-000" (show only parsed result)
* for "tab<>0" the default is "111-110" (show all except debug)
* value "000-000" (do not show anything at all) is prohibited
* relevant also for ":top", but then the extra features activable
by values 2 or 3 do NOT apply, thus all values are binary
* number bigger than "1" in the control string "sel=" is used (design
decision) to hold a value instead of another named parameter if:
* there is a low number of possible discrete values
* the issue is specific to a column of the table
* the issue is about display only, not about operation
* following display details are "built-in" into "sel=":
* column "call" : small text size (boolean -> tristate)
* column "cat" : omit sorting hints (boolean -> tristate)
* column "debug" : type of display (black text, coloured
text, map) (tristate -> fourstate)
* there is a conflict of interest about the column "back", it is
useful when exposing many calls to different templates, but undesirable
(alternatively use some "rowspan" ...) for many calls to same template
with varying parameters
Strip markers:
* tags and parser functions vulnerable to strip markers:
* <pre> and <nowiki> #A14 #M04
* <ref> and <references> #A14 #M04
* both <categorytree> and {{#categorytree}} #A15 #M05
* <templatestyles> #A15 #M05
* <gallery> #A15 #M05
* <math> #A15 #M05
* "<syntaxhighlight" ...
* unproblematic tags:
* <b> <i> <s>
* <sub> <sup>
* <br>
* parameter "tag=1" activates workaround for some of the vulnerable ones:
* <pre> <--> <pnere>
* <nowiki> <--> <nonewiki> observed in template parameters
* <ref> <--> <renef> observed in template parameters (works
even for "<ref group=" and "<ref name=")
* <gallery> <--> <gallenery> observed in template parameters where
a single image is expected (probably not sane)
Storage of parameter chains:
* Raw string such as "nope|center=YES" used in incoming anonymous
parameter together with the name of the target, with rectangular
brackets and adjacent whitespace later removed, equal sign is
protected inside [[ ]] thus "{{=}}" is NOT needed.
* We do NOT use a table with parameters for a call.
* Still we must look for "trackingcategorieshiglow=" or "nocat=" and
whine if found.
* Also we must look for "*HIDDEN*".
* Unless in the raw mode by "nsm=2", we apply "partial preservation of
trimmed whitespace". Then [[ ]] serve as replacement of {{ }} and
we preserve ONE SPACE or ONE LF separately on every side (inside of
the [[ ]]), but NOT more. This is needed to preserve the arrangement
of the call (see below).
For "nsm=2" ie "boo3nsm2m" following changes apply:
* column "call": the call is never linked
* column "back": backlinks are not showed, if the column is enabled
(discouraged) then it will contain the standard placeholder instead
* operation:
* [[ ]] must always be used, and do NOT serve as replacement
of {{ }}, extra {({ })} must be used inside
* partial preservation of trimmed whitespace does NOT apply
* check for the existence of target is skipped, "#X80" cannot occur
* many sanity checks skipped
* "zer=1" does NOT work, bad old extra colon ":" must be used
* "hlt=1" and "ncf=1" do NOT work
Hidden parameters:
* denoted per "*HIDDEN*" instead of equal sign "=" in the call string
* are available for all "nsm=0" "nsm=1" "nsm=2"
* are available also for "mod=1"
* must NOT contain wikilinks
* must NOT contain nested templates, not even with "nsm=1", still outside
of the hidden parameter, nested template calls are permitted in same call
* hidden parameters can be several and anywhere in the chain, but
preferably put them always together at the end
* main anon parameter is split into two strings:
* one with "*HIDDEN*" replaced by "=" intented to be fed into
expansion ie "arxframent:preprocess"
* one with parameters using "*HIDDEN*" removed intended to be
showed in the table
Handling of ns prefixes:
* the {{-}}-syntax (indirectly used here) defaults to ns 10
ie "Template:", other prefix still possible
* parser function "arxframent:expandTemplate" (not used
here) defaults to ns 10 too
* unless "zer=1" we have to always add the prefix for the purpose
of linking by means of [[...]]-syntax and backlink evaluation by
means of "Special:WhatLinksHere"
* if "zer=1" then we must add an extra colon for the {{-}}-syntax for
both expansion and display
The "<pre>" tag is insanely useful in plain wikitext, but behaves
inconsistently when coming from a template or module. We want it
to work for via "pate" in the rare cases when it's needed, and must
then care about it by html-dec-encoding.
Both <ref> and <references/> do NOT work in output from a module. We need
the latter only and must workaround it by "frame:extensionTag".
Link to the target template is showed without a possible default "Template:"
prefix, other prefixes are visible, even if template not found. Internal
structure of the link:
* a) "[[" (not visible, do NOT encode)
* b) name of the template always with prefix (not visible, link target)
* c) wall "|" (not visible, do NOT encode)
* d) "{{" (visible) (works without encoding)
* e) name of the template without default prefix + parameter chain (visible)
* f) "}}" (visible) (works without encoding)
* g) "]]" (not visible, do NOT encode)
Note that the HTML parser can split the string into multiple lines
(or more lines than requested by EOL:s) if there are spaces in !!!FIXME!!! EOL to <br> and underscore to space
but not if underscores "_" are used instead.
Encoding of text:
* For backlinks and redirects we have to urlencode the parameter,
"lfwbrew3url" with help of "{{canonicalurl:...}}" does encode the
service page "Special:WhatLinksHere" but the target parameter
must be encoded separately by "mw.uri.encode".
* For the call column, we must preserve the layout of preformatted text
and block all parsing, but we want to have all the stuff in a link to the
template, with optionally reduced font size, "lfidecencodbr" does the
encoding natively blocking all wikilink parsing, HTML tag parsing and HTML
entity parsing, output from it must be placed into a special inner table
(see below) ensuring monospace.
* For the output column, we disallow "<nowiki>" and "<syntaxhighlight
lang="text">" in content coming from the template, further we need special
handling for "<pre>" where we must encode all "[" "]" "&" to prevent parsing
of wikilinks (this phenomenon may indeed occur in some cases) and HTML
entities. Cat insertions inside areas poorly inactivated by "<pre>" are NOT
caught, they are fixed by encoding in "lfysplitkat" instead.
* For the debug column, we must avoid any parsing, and make spaces, LF:s and
broken char:s visible, "lfiultencode" provides this natively.
There are several possible ways to display monospaced preformatted text:
* "<pre>" (NOT used for the call)
+ nice appearance with box
+ simple syntax
- aggressive high-priority tag with inconsistent and dangerous
behaviour when coming from a template, can cause strip markers
* "<code><nowiki>" (NOT used for the call)
+ less aggressive tag
+ can be combined with "<small>"
+ can be placed into a link
- "<nowiki>" does not work when coming from a template, still can
cause strip markers
- needs manual fixing of spaces and LF:s
- bad appearance for multiline text, particularly if it
contains empty lines, no box
* do all manually, use a HTML table for the box (used here for the call)
+ nice appearance with box
+ no aggressive or dangerous tags
+ can vary text size
+ can be placed into a link
- needs manual fixing of spaces and LF:s
- needs complicated HTML+CSS
There are several imaginable ways to submit a call to a target
template into a calling proxy ie "pate". None of them is perfect,
and none of them will support plain nested template calls.
* submit target as an anonymous parameter followed by forwarded
parameters and seize them by "pairs" (NOT used)
+ nice syntax, no extra brackets
- sortorder of parameters NOT preserved
- formatting of the call NOT preserved
- needs some "ultrahidden" parameters for submitting instructions
into the calling proxy
- nested template calls will not work and cannot be supported
* complete call protected by rectangular brackets (used here)
+ fairly nice syntax, only 4 extra brackets [[ ]]
+ sortorder of parameters preserved
+ formatting of the call preserved
+ nested template calls can be supported with a workaround
- syntax is a bit strange with a faked wikilink
There are several ways how to expand a template:
* arxframent:expandTemplate (eats title + table, adds ns prefix, crashes
on the spot if template does not exist) (NOT used)
* arxframent:preprocess (eats raw string, adds ns prefix if {{ }} is used,
does NOT work with substitution but this doesn't really matter here)
(used here)
Note that above methods for expanding a template are NOT expensive whereas
wiki's native "ifexist" and LUA's "getContent()" are. Unfortunately we have
to expand two times, but both are free. In order to get free "ifexist" we
need "msgnw:", but for the main work we must avoid "msgnw:".
Another problem are strip markers deeply buried in the design of MediaWiki.
Some aggressive tags such as <pre> and <nowiki> in a classic template being
expanded result in strip markers, whereas this does NOT occur if a module
generates such content. The function "mw.text.unstrip" is inherently useless
since it returns raw text for <nowiki> (with the tags removed), and a
completely empty string in all other cases including <pre>.
------------------------------------------------------------------------
### Arrangements
There are several useful styles to arrange template calls.
Inline compact:
{{doall|now|priority=urgent}}
Inline with spaces:
{{ doall | now | priority = urgent }}
Multiline with spaces:
{{ taxobox
| domain = none
| kingdom = fungi
| phylum = unknown
}}
Chess:
{{chessboard
|--|--|--|--|kd|--|--|rd
|--|--|--|--|--|--|--|--
|--|--|--|--|--|bl|--|pl
|--|--|--|rl|--|kl|pd|pl
|--|--|--|--|--|--|--|--
|--|--|--|--|--|--|--|--
|--|--|--|--|--|--|--|--
|--|--|--|--|--|--|--|--
|btm = deliver checkmate in two moves
}}
We do NOT really bother, and keep the complete call to the target template
as-is except replacing outer [[ ]] by {{ }}. We must, however, isolate
the target title (since we link to it in various ways), and strip
all possible whitespace around it.
------------------------------------------------------------------------
### Examples of usage
Two templates (by default tab=2 and sel=111-110):
{{pate|:top}}
{{pate|hr3}}
{{pate|hr4}}
{{pate|:end}}
Two templates with manually selected some columns (by default tab=2):
{{pate|sel=110-110|:top}}
{{pate|sel=110-110|hr3}}
{{pate|sel=110-110|hr4}}
{{pate|:end}}
Two templates with manually selected all columns (by default tab=2):
{{pate|sel=111-111|:top}}
{{pate|sel=111-111|hr3}}
{{pate|sel=111-111|hr4}}
{{pate|:end}}
One template suboptimal way horizontal table (by default tab=2):
{{pate|sel=110-100|:top}}
{{pate|sel=110-100|Pengguna transportasi publik}}
{{pate|:end}}
One template better way horizontal table:
{{pate|tab=3|sel=110-100|Pengguna transportasi publik}}
One template better way horizontal table without title row:
{{pate|tab=4|sel=110-100|Pengguna transportasi publik}}
One template better way vertical table (no way to show multiple templates):
{{pate|tab=5|sel=110-100|Pengguna transportasi publik}}
One template minimal use no table, used only to suppress
categorization (tab=0 brings default sel=010-000):
{{pate|tab=0|Pengguna transportasi publik}}
One template reduced output show only parsed result and categories:
{{pate|tab=3|sel=010-100|Pengguna transportasi publik}}
One template reduced output show only parsed result
and categories, and without title row:
{{pate|tab=4|sel=010-100|Pengguna transportasi publik}}
Two different calls to one template with custom title (by default tab=2):
{{pate|sel=110-111|:top|tit=CALL@@PARSED@@REM@@CAT@@BACK-LINKS@@DEBUG}}
{{pate|sel=110-111|[[ambox|text=this is a test|bgcolor=FF8080]]}}
{{pate|sel=110-111|[[ambox|text=this is a test|bgcolor=#FF8080]]|rem=invalid usage}}
{{pate|:end}}
One template suboptimal way horizontal table small text (by default tab=2):
{{pate|sel=111-000|:top}}
{{pate|sel=211-000|[[
taxobox
| domain = none
| kingdom = fungi
| phylum = unknown
]]}}
{{pate|:end}}
One template better way horizontal table small text:
{{pate|tab=3|sel=211-000|[[
taxobox
| domain = none
| kingdom = fungi
| phylum = unknown
]]}}
* make sure to use same value for "sel=" for the ":top" call and
all core calls below it
* do NOT feed "tab=" or "sel=" into the final ":end" call
* make sure to use the colon in ":top" and ":end", this convention allows
to call templates named "top" and "end"
* the order of named parameters relative to each other and to the only
anonymous parameter technically does not matter, but the style above
with "tab=" and "sel=" preceding the big anonymous parameter and all other
named parameters following it is strongly encouraged for best readability
------------------------------------------------------------------------
]===]
local exporttable = {}
------------------------------------------------------------------------
---- CONSTANTS [O] ----
------------------------------------------------------------------------
-- uncommentable constant strings (lang and core site-related features)
-- local constrpriv = "en" -- EN (privileged site language) !!!FIXME!!! peek this
local constrpriv = "eo" -- EO (privileged site language)
-- local constrpriv = "id" -- ID (privileged site language)
-- local constrpriv = "sv" -- SV (privileged site language)
local constrprli = "Special:WhatLinksHere" -- EN worx everywhere (must NOT end with a blackslash, must NOT be urlencoded)
-- uncommentable constant table (error messages) !!!FIXME!!! incomplete and no "constrkoll" yet
-- #E02...#E99, holes permitted
-- note that #E00 and #E01 are NOT supposed to be included here
local contaberaroj = {}
-- contaberaroj[ 2] = 'Unknown parameter' -- EN #E02 !!!FIXME!!! incomplete, and move up
contaberaroj[ 2] = 'Nekonata parametro' -- EO #E02
-- contaberaroj[ 2] = 'Parameter tidak dikenal' -- ID #E02
-- contaberaroj[ 2] = 'Ok\aend parameter' -- SV #E02
-- contaberaroj[ 3] = 'Bad anonymous parameter' -- EN #E03
contaberaroj[ 3] = 'Erara anonima parametro' -- EO #E03
-- contaberaroj[ 3] = 'Parameter anonim salah' -- ID #E03
-- contaberaroj[ 3] = 'Felaktig anonym parameter' -- SV #E03
-- contaberaroj[ 4] = 'Wrong use of [[ | ]] in anonymous parameter' -- EN #E04
contaberaroj[ 4] = 'Erara uzo de [[ | ]] en anonima parametro' -- EO #E04
-- contaberaroj[ 4] = 'Penggunaan [[ | ]] salah dalam parameter anonim' -- ID #E04
-- contaberaroj[ 4] = 'Felaktig anv\\aendning av [[ | ]] i anonym parameter' -- SV #E04
-- contaberaroj[ 5] = 'Bad or nonstandard target title or namespace' -- EN #E05
contaberaroj[ 5] = 'Erara aux nestandarda cela titolo aux nomspaco' -- EO #E05
-- contaberaroj[ 5] = 'Judul atau ruang nama sasaran salah atau takbaku' -- ID #E05
-- contaberaroj[ 5] = 'Felaktig eller icke-standardiserad titel eller namnrymd' -- SV #E05
-- contaberaroj[ 8] = '"tab=" bad' -- EN #E08
contaberaroj[ 8] = '"tab=" erara' -- EO #E08
-- contaberaroj[ 8] = '"tab=" salah' -- ID #E08
-- contaberaroj[21] = '"sel=" bad' -- EN #E21
contaberaroj[21] = '"sel=" erara' -- EO #E21
-- contaberaroj[21] = '"sel=" salah' -- ID #E21
-- contaberaroj[40] = '"sel=" conflicts with "tab="' -- EN #E40
contaberaroj[40] = '"sel=" konfliktas kun "tab="' -- EO #E40
-- contaberaroj[40] = '"sel=" tidak sesuai dengan "tab="' -- ID #E40
-- contaberaroj[41] = '"mod=" conflicts with "zer=1"' -- EN #E41
contaberaroj[41] = '"mod=" konfliktas kun "zer=1"' -- EO #E41
-- contaberaroj[41] = '"mod=" tidak sesuai dengan "zer=1"' -- ID #E41
-- contaberaroj[43] = '"trackingcategorieshiglow=" sent into "pate"' -- EN #E43
contaberaroj[43] = '"trackingcategorieshiglow=" sendita al "pate"' -- EN #E43
-- contaberaroj[43] = '"trackingcategorieshiglow=" dimasukkan ke "pate"' -- EN #E43
-- contaberaroj[43] = '"nocat=" sent into "pate"' -- EN #E44
contaberaroj[43] = '"nocat=" sendita al "pate"' -- EN #E44
-- contaberaroj[43] = '"nocat=" dimasukkan ke "pate"' -- EN #E44
contaberaroj[46] = 'Strip marker detected in incoming target parameter, use "tag=1"' -- EN #E46
contaberaroj[48] = 'Hidden parameter contains double brackets [[ ]] {{' -- EN #E48
contaberaroj[49] = '*HIDDEN* without preceding wall "|"' -- EN #E49
-- constant strings (error circumfixes)
local constrelabg = '<span class="error"><b>' -- lagom whining begin
local constrelaen = '</b></span>' -- lagom whining end
local constrlaxhu = ' ** ' -- lagom -> huge circumfix " ** "
-- uncommentable constant strings (messages)
local constrbalik = "Backlinks<br>Ligioj cxi tien" -- EO
-- local constrbalik = "Backlinks<br>Pranala balik" -- ID
local constrredir = "Redirects<br>Alidirektiloj" -- EO
-- local constrredir = "Redirects<br>Pengalihan" -- ID
-- local constrca3d = "(no category)" -- EN
local constrca3d = "(ne estas kategorio)" -- EO
-- local constrca3d = "(tidak ada kategori)" -- ID
-- local constrca3d = "(ingen kategori)" -- SV
local constrca4d = "Eniras" -- EO
-- local constrca4d = "Masuk ke" -- ID
-- local constrca4d = "Fastnar i" -- SV
local constrca5d = "kategoriojn" -- EO
-- local constrca5d = "kategori" -- ID
-- local constrca5d = "kategorier" -- SV
-- default column names (short, always English, one bare word)
local contabcolumns = {[0]="call","parsed","rem","cat","back","debug"} -- [0]...[5] see "lfhatmergetab"
-- cell background colors (2 or 6 hex digits) for "lfhtablewithmap" only
local contabbk = {}
contabbk[ 0] = "FF" -- white no link
contabbk[ 1] = "E9" -- -22 grey
contabbk[ 2] = "D4" -- -21 grey
contabbk[ 3] = "C4" -- -16 grey
contabbk[ 4] = "B4" -- -16 grey
contabbk[ 5] = "A8" -- -12 grey
contabbk[ 6] = "9C" -- -12 grey
contabbk[ 7] = "92" -- -10 grey
contabbk[ 8] = "88" -- -10 grey
contabbk[ 9] = "7E" -- -10 grey
contabbk[15] = "FF7070" -- deep red strip markers
contabbk[16] = "FF8000" -- orange nowiki
contabbk[17] = "C06090" -- violet syntaxhighlight
contabbk[22] = "2020FF" -- blue pre
contabbk[23] = "20FF20" -- green comment
-- uncommentable constant strings (more messages, #M00 omitted here, for "lfiexplain" only)
local contabxxplain = {}
-- contabxxplain ['#X80'] = 'target (template or page) does NOT exist' -- EN
contabxxplain ['#X80'] = 'celo (sxablono aux pagxo) NE ekzistas' -- EO
-- contabxxplain ['#X80'] = 'sasaran (templat atau halaman) TIDAK ada' -- ID
-- contabxxplain ['#X82'] = 'empty string from expansion' -- EN
contabxxplain ['#X82'] = 'maplena signocxeno el ekspando' -- EO
-- contabxxplain ['#X82'] = 'string kosong dari ekspansi' -- ID
-- contabxxplain ['#M01'] = 'unclosed inactive area' -- EN
contabxxplain ['#M01'] = 'nefermita neaktiva areo' -- EO
-- contabxxplain ['#M01'] = 'wilayah nonaktif tidak ditutup' -- ID
contabxxplain ['#M02'] = 'unclosed strip marker'
contabxxplain ['#M03'] = 'unbalanced [[ ]] in active areas'
contabxxplain ['#M04'] = 'strip markers (pre nowiki ref)'
contabxxplain ['#M05'] = 'strip markers (other)'
contabxxplain ['#M06'] = 'syntaxhighlight'
contabxxplain ['#M08'] = 'pre'
contabxxplain ['#M09'] = 'nowiki'
contabxxplain ['#M10'] = 'ref'
contabxxplain ['#M11'] = 'HTML comment'
contabxxplain ['#M12'] = '<includeonly> et al'
contabxxplain ['#M20'] = 'max wikilink depth' -- follows number
contabxxplain ['#M22'] = 'treacherous space'
contabxxplain ['#S20'] = 'split not attempted due to other' -- EN
contabxxplain ['#S21'] = 'split not attempted due to nesting' -- EN
contabxxplain ['#S23'] = 'broken wikilink lacking left part' -- EN
contabxxplain ['#S24'] = 'cat insertion on level different from ONE' -- EN
-- for "lfiultencode" only
local constrpilen = '[[File:Return arrow.svg|20px|link=]]' -- the file is Public Domain
local contabempatwarna = {[0]='FFA0A0','D0FFD0','A0A0FF','D0D0D0'} -- red, light green, blue, light grey
-- prohibited stuff -- see above under "Limitations and caveats" why !!!FIXME!!! unused
local tabprohi = {[0]="<includeonly>","</includeonly>","<noinclude>","</noinclude>"}
-- constant LUA tables for HTML tables with CSS
local contabtabeg = {[0]='<table style="margin:0.6em;border:0.','em solid #',';border-collapse:collapse;">'} -- [0]...[2]
local contabtdbeg = {[0]='<td style="border:0.','em solid #',';padding:0.5em;text-align:center;">'} -- [0]...[2]
-- surrogate transcoding table (only needed for EO)
local contabtransluteo = {}
contabtransluteo[ 67] = 0xC488 -- CX
contabtransluteo[ 99] = 0xC489 -- cx
contabtransluteo[ 71] = 0xC49C -- GX
contabtransluteo[103] = 0xC49D -- gx
contabtransluteo[ 74] = 0xC4B4 -- JX
contabtransluteo[106] = 0xC4B5 -- jx
contabtransluteo[ 83] = 0xC59C -- SX
contabtransluteo[115] = 0xC59D -- sx
contabtransluteo[ 85] = 0xC5AC -- UX breve
contabtransluteo[117] = 0xC5AD -- ux breve
-- surrogate transcoding table (only needed for SV)
local contabtranslutsv = {}
contabtranslutsv['AA'] = 0xC385 -- Aring
contabtranslutsv['Aa'] = 0xC385 -- Aring
contabtranslutsv['aa'] = 0xC3A5 -- aring
contabtranslutsv['AE'] = 0xC384
contabtranslutsv['Ae'] = 0xC384
contabtranslutsv['ae'] = 0xC3A4
contabtranslutsv['EE'] = 0xC389 -- rarely used
contabtranslutsv['Ee'] = 0xC389 -- rarely used
contabtranslutsv['ee'] = 0xC3A9 -- rarely used
contabtranslutsv['OE'] = 0xC396
contabtranslutsv['Oe'] = 0xC396
contabtranslutsv['oe'] = 0xC3B6
-- constant strings (misc)
local constrempt = '--' -- placeholder for empty table cell "rem=" or "back"
-- math constants and boolean switches
local contabboo2int = {[false]=0,[true]=1}
local contabboo2siz = {[false]='100',[true]='70'}
------------------------------------------------------------------------
---- SPECIAL STUFF OUTSIDE MAIN [B] ----
------------------------------------------------------------------------
-- SPECIAL VAR:S
local qbooguard = false -- only for the guard test, pass to other var ASAP
local qstrtabegin = '' -- from "contabtabeg" added col & wi, begin of table
local qstrtdbegin = '' -- from "contabtdbeg" added col & wi, begin of cell
local qstrtdendus = '' -- end of cell
local qstrtaendus = '' -- end of table
local qtabmy6columns = {} -- based on "contabcolumns" used in "lficondicelrow"
-- GUARD AGAINST INTERNAL ERROR
qbooguard = ((type(constrpriv)~='string') or (type(constrprli)~='string'))
------------------------------------------------------------------------
---- MATH FUNCTIONS [E] ----
------------------------------------------------------------------------
local function mathisintrange (numzjinput, numzjmin, numzjmax)
local booisclean = false -- preASSume guilt
if (type(numzjinput)=='number') then -- no non-numbers, thanks
if (numzjinput==math.floor(numzjinput)) then -- no transcendental
booisclean = ((numzjinput>=numzjmin) and (numzjinput<=numzjmax)) -- rang
end--if
end--if
return booisclean
end--function mathisintrange
local function mathdiv (xdividens, xdivisero)
local resultdiv = 0 -- DIV operator lacks in LUA :-(
resultdiv = math.floor (xdividens / xdivisero)
return resultdiv
end--function mathdiv
local function mathmod (xdividendo, xdivisoro)
local resultmod = 0 -- MOD operator is "%" and bitwise AND operator lack too
resultmod = xdividendo % xdivisoro
return resultmod
end--function mathmod
------------------------------------------------------------------------
-- Local function MATHBITTEST
-- Find out whether single bit selected by ZERO-based index is "1" / "true".
-- Result has type "boolean".
-- Depends on functions :
-- [E] mathdiv mathmod
local function mathbittest (numincoming, numbitindex)
local boores = false
while true do
if ((numbitindex==0) or (numincoming==0)) then
break -- we have either reached our bit or run out of bits
end--if
numincoming = mathdiv(numincoming,2) -- shift right
numbitindex = numbitindex - 1 -- count down to ZERO
end--while
boores = (mathmod(numincoming,2)==1) -- pick bit
return boores
end--function mathbittest
------------------------------------------------------------------------
---- NUMBER CONVERSION FUNCTIONS [N] ----
------------------------------------------------------------------------
-- Local function LFDEC1DIGIT
-- Convert 1 decimal ASCII digit to integer 0...9 (255 if invalid).
local function lfdec1digit (num1digit)
num1digit = num1digit - 48 -- may become invalid
if ((num1digit<0) or (num1digit>9)) then
num1digit = 255 -- report ERROR on invalid input digit
end--if
return num1digit
end--function lfdec1digit
------------------------------------------------------------------------
-- Local function LFSTRONDIG2INT
-- Convert string with 1 decimal ASCII digit
-- to integer 0...9 (255 if invalid).
-- Depends on functions :
-- [N] lfdec1digit
local function lfstrondig2int (strmasukk)
local numalone = 255 -- preASSume guilt
if (string.len(strmasukk)==1) then
numalone = string.byte (strmasukk,1,1)
numalone = lfdec1digit (numalone) -- 255 if invalid, ZERO would be valid
end--if
return numalone
end--function lfstrondig2int
------------------------------------------------------------------------
-- Local function LFSTRTWDIG2INT
-- Convert string with always 2 decimal ASCII digit:s
-- to integer 0...99 (255 if invalid).
-- Depends on functions :
-- [N] lfdec1digit
local function lfstrtwdig2int (strmasuuk)
local numleft = 255 -- preASSume guilt
local numrayt = 0
if (string.len(strmasuuk)==2) then
numleft = string.byte (strmasuuk,1,1)
numleft = lfdec1digit (numleft) -- 255 if invalid, ZERO would be valid
numrayt = string.byte (strmasuuk,2,2)
numrayt = lfdec1digit (numrayt) -- 255 if invalid, ZERO would be valid
if (numrayt==255) then
numleft = 255 -- 255 is invalid, note that ZERO would be valid
else
numleft = numleft * 10 + numrayt -- valid integer number 0...99 now
end--if
end--if
return numleft
end--function lfstrtwdig2int
------------------------------------------------------------------------
-- Local function LFNONEHEXTOINT
-- Convert single quasi-digit (ASCII HEX "0"..."9" "A"..."F") to
-- integer (0...15, 255 invalid).
-- Only uppercase accepted.
local function lfnonehextoint (numdigit)
local numresult = 255
if ((numdigit>47) and (numdigit<58)) then
numresult = numdigit-48
end--if
if ((numdigit>64) and (numdigit<71)) then
numresult = numdigit-55
end--if
return numresult
end--function lfnonehextoint
------------------------------------------------------------------------
-- Local function LFNUMTO2DIGIT
-- Convert integer 0...99 to decimal ASCII string always 2 digits "00"..."99".
-- Depends on functions :
-- [E] mathisintrange mathdiv mathmod
local function lfnumto2digit (numzerotoninetynine)
local strtwodig = '??' -- always 2 digits
if (mathisintrange(numzerotoninetynine,0,99)) then
strtwodig = tostring(mathdiv(numzerotoninetynine,10)) .. tostring(mathmod(numzerotoninetynine,10))
end--if
return strtwodig
end--function lfnumto2digit
------------------------------------------------------------------------
-- Local function LFUINT8TOHEX
-- Convert UINT8 (0...255) to a 2-digit hex string.
-- Depends on functions :
-- [E] mathdiv mathmod
local function lfuint8tohex (numinclow)
local strheksulo = ''
local numhajhaj = 0
numhajhaj = mathdiv (numinclow,16)
numinclow = mathmod (numinclow,16)
if (numhajhaj>9) then
numhajhaj = numhajhaj + 7 -- now 0...9 or 17...22
end--if
if (numinclow>9) then
numinclow = numinclow + 7 -- now 0...9 or 17...22
end--if
strheksulo = string.char (numhajhaj+48) .. string.char (numinclow+48)
return strheksulo
end--function lfuint8tohex
------------------------------------------------------------------------
---- LOW LEVEL STRING FUNCTIONS [G] ----
------------------------------------------------------------------------
-- test whether char is an ASCII digit "0"..."9", return boolean
local function lfgtestnum (numkaad)
local boodigit = false
boodigit = ((numkaad>=48) and (numkaad<=57))
return boodigit
end--function lfgtestnum
------------------------------------------------------------------------
-- test whether char is an ASCII uppercase letter, return boolean
local function lfgtestuc (numkode)
local booupperc = false
booupperc = ((numkode>=65) and (numkode<=90))
return booupperc
end--function lfgtestuc
------------------------------------------------------------------------
-- test whether char is an ASCII lowercase letter, return boolean
local function lfgtestlc (numcode)
local boolowerc = false
boolowerc = ((numcode>=97) and (numcode<=122))
return boolowerc
end--function lfgtestlc
------------------------------------------------------------------------
-- Local function LFGIS62SAFE
-- Test whether incoming ASCII char is very safe (0...9 A...Z a...z).
-- Depends on functions :
-- [G] lfgtestnum lfgtestuc lfgtestlc
local function lfgis62safe (numcxair)
local booguud = false
booguud = lfgtestnum (numcxair) or lfgtestuc (numcxair) or lfgtestlc (numcxair)
return booguud
end--function lfgis62safe
------------------------------------------------------------------------
-- Local function LFGTRIMWHITE
-- Input : * strputihsekali -- string, empty tolerable, but type "nil" is NOT
local function lfgtrimwhite (strputihsekali)
local numtrimthemall = 0
local boodonenow = false
while true do
if (strputihsekali=='') then
break
end--if
boodonenow = true
numtrimthemall = string.byte(strputihsekali,1,1)
if ((numtrimthemall==32) or (numtrimthemall==10)) then
strputihsekali = string.sub (strputihsekali,2,-1)
boodonenow = false
end--if
numtrimthemall = string.byte(strputihsekali,-1,-1)
if ((numtrimthemall==32) or (numtrimthemall==10)) then
strputihsekali = string.sub (strputihsekali,1,-2)
boodonenow = false
end--if
if (boodonenow) then
break
end--if
end--while
return strputihsekali -- same var for input and output
end--function lfgtrimwhite
------------------------------------------------------------------------
-- Local function LFGDELETEALLWHITE
local function lfgdeleteallwhite (strin52in)
local strut52ut = ''
local numlen52len = 0
local numind52ind = 0
local numchr52chr = 0
numlen52len = string.len(strin52in)
while true do -- genuine loop
if (numind52ind>=numlen52len) then
break
end--if
numchr52chr = string.byte(strin52in,(numind52ind+1),(numind52ind+1))
if ((numchr52chr~=10) and (numchr52chr~=32)) then
strut52ut = strut52ut .. string.char(numchr52chr)
end--if
numind52ind = numind52ind + 1
end--while
return strut52ut
end--function lfgdeleteallwhite
------------------------------------------------------------------------
---- UTF8 FUNCTIONS [U] ----
------------------------------------------------------------------------
-- Local function LFULNUTF8CHAR
-- Evaluate length of a single UTF8 char in octet:s.
-- Input : * numbgoctet -- beginning octet of a UTF8 char
-- Output : * numlen1234x -- number 1...4 or ZERO if invalid
-- Does NOT thoroughly check the validity, looks at 1 octet only.
local function lfulnutf8char (numbgoctet)
local numlen1234x = 0
if (numbgoctet<128) then
numlen1234x = 1 -- $00...$7F -- ANSI/ASCII
end--if
if ((numbgoctet>=194) and (numbgoctet<=223)) then
numlen1234x = 2 -- $C2 to $DF
end--if
if ((numbgoctet>=224) and (numbgoctet<=239)) then
numlen1234x = 3 -- $E0 to $EF
end--if
if ((numbgoctet>=240) and (numbgoctet<=244)) then
numlen1234x = 4 -- $F0 to $F4
end--if
return numlen1234x
end--function lfulnutf8char
------------------------------------------------------------------------
---- HIGH LEVEL STRING FUNCTIONS [I] ----
------------------------------------------------------------------------
-- Local function LFIPILLEGAL
-- Check whether a string contains illegal stuff such
-- as LF < > [ ] '' [[ ]] {{ }} UNIQ [http. Note that codes
-- 0...9 and 11...31 are unconditionally prohibited.
-- Input : * strinpil -- empty cannot cause major harm and returns "false"
-- * boonolflf -- disallow LF
-- * boonotags -- disallow single diamond brackets <> ie HTML tags
-- * boonobold -- disallow double apo "''" ie both italics and bold
-- (<b> and <i> will still pass)
-- * numnorect -- 0 allow rect | 1 disallow double "[[" and "]]"
-- but not single ones | 2 disallow even single [ ]
-- * boonotskl -- disallow "{{" and "}}" but not single ones
-- * boonostrp -- disallow strip
-- * boonohttp -- disallow "[http" (this is redundant
-- for numnorect=2)
-- Output : * boocriminal ("true" if "strinpil" contains illegal stuff)
local function lfipillegal (strinpil, boonolflf, boonotags, boonobold, numnorect, boonotskl, boonostrp, boonohttp)
local numleunin = 0
local numindoxx = 1 -- ONE-based
local numtecken = 0
local numtecprv = 0 -- previous char
local boocriminal = false
while true do -- fake loop
boocriminal = boonostrp and (string.find(strinpil,(string.char(127,39,34,96)..'UNIQ'),1,true)~=nil) -- striptease marker
if (boocriminal) then
break
end--if
boocriminal = boonohttp and (string.find(strinpil,"[http",1,true)~=nil) -- external link !!!FIXME!!! this is weak
if (boocriminal) then
break
end--if
boocriminal = boonohttp and (string.find(strinpil,"[ http",1,true)~=nil) -- external link !!!FIXME!!! this is weak
if (boocriminal) then
break
end--if
numleunin = string.len (strinpil) -- length of input string to be tested
while true do
if (numindoxx>numleunin) then
break -- innocent now
end--if
numtecken = string.byte (strinpil,numindoxx,numindoxx)
if ((numtecken<31) and (numtecken~=10)) then
boocriminal = true -- unconditionally prohibited
break
end--if
if (boonolflf and (numtecken==10)) then
boocriminal = true -- LF
break
end--if
if (boonotags and ((numtecken==60) or (numtecken==62))) then
boocriminal = true -- single "<" or ">" is criminal
break
end--if
if ((numnorect==2) and ((numtecken==91) or (numtecken==93))) then
boocriminal = true -- catch even single [ ]
break
end--if
if (numtecken==numtecprv) then
if (boonobold and (numtecken==39)) then
boocriminal = true -- "''" ie italics or bold
break
end--if
if ((numnorect~=0) and ((numtecken==91) or (numtecken==93))) then
boocriminal = true
break
end--if
if (boonotskl and ((numtecken==123) or (numtecken==125))) then
boocriminal = true
break
end--if
end--if
numtecprv = numtecken -- previous char
numindoxx = numindoxx + 1
end--while
break -- finally to join mark
end--while -- fake loop -- join mark
return boocriminal
end--function lfipillegal
------------------------------------------------------------------------
-- Local function LFIDECENCODBR
-- Moderately encode char:s to prevent parsing (all wikilink parsing, HTML tag
-- parsing, HTML entity parsing), and optionally apply special treatment to
-- LF:s turning them into <br> as well as to spaces preventing reduction. This
-- is intended for showing sane UTF8 text, NOT for debugging purposes.
-- Input : * strinkkkkin -- string, empty tolerable, but type "nil" is NOT
-- * boopreformat -- true for special treatment preserving
-- preformatted text
-- Output : * strbrbrcod -- string, empty in worst case
local function lfidecencodbr (strinkkkkin, boopreformat)
local strwanchar = ''
local strbrbrcod = ''
local numsrtlen = 0
local numpekkinx = 1 -- ONE-based index
local numchmuar = 0
local boonbtp = true -- "true" needed for junk lines containing only space
numsrtlen = string.len (strinkkkkin)
while true do -- outer genuine loop
if (numpekkinx>numsrtlen) then
break
end--if
numchmuar = string.byte (strinkkkkin,numpekkinx,numpekkinx)
numpekkinx = numpekkinx + 1
while true do -- inner fake loop
if (numchmuar==9) then
numchmuar = 32 -- TAB to SPACE always
end--if
if ((numchmuar==10) and boopreformat) then -- special treatment
strwanchar = '<br>'
boonbtp = true -- "true" needed for junk lines containing only space
break
end--if
if ((numchmuar==32) and boopreformat) then -- special treatment
if (boonbtp) then
strwanchar = ' ' -- this prevents space reduction
else
strwanchar = ' '
end--if
boonbtp = not boonbtp
break
end--if
if ((numchmuar==10) or (numchmuar==32) or (numchmuar>127)) then
strwanchar = string.char (numchmuar) -- pass LF SPACE UTF8 untouched
break
end--if
if (numchmuar<32) then
numchmuar = 63 -- filter away crap to "?" -- then encode it below
end--if
strwanchar = '&#' .. tostring (numchmuar) .. ';' -- encode all ASCII
break -- finally to join mark
end--while -- inner fake loop -- join mark
strbrbrcod = strbrbrcod .. strwanchar
end--while -- outer genuine loop
return strbrbrcod
end--function lfidecencodbr
------------------------------------------------------------------------
-- Local function LFIULTENCODE
-- Generously encode char:s to prevent parsing and show hex if needed, make
-- single chars visible, bypass all wiki parsing and HTML parsing. Our cool
-- module has brewed something with "[["..."]]" and repeated spaces but we
-- want to see plain text for debugging purposes. Thus we dec-encode some
-- char:s, use NBSP to fix spaces, workaround EOL, and maybe add colour.
-- Input : * strkrampuj : string, empty tolerable, but type "nil" is NOT
-- * nummxwidth : maximal width of text (20...200, default 80)
-- * boowarrna : "true" to enable color
-- * boosplitutf : "true" to split UTF8 char:s into hex numbers
-- Output : * strkood : string, empty in worst case
-- Depends on functions :
-- [U] lfulnutf8char
-- [G] lfgtestnum lfgtestuc lfgtestlc lfgis62safe
-- [N] lfuint8tohex
-- [E] mathdiv mathmod
-- Depends on constants :
-- * string constrpilen [[File:...]]
-- * table contabempatwarna 0...3
-- This helps with:
-- * "[["..."]]", "["..."]", "*", "#", ":" (note that there is no
-- problem with plain "{{"..."}}")
-- * multiple spaces (they are no longer reduced to one piece due to HTML)
-- * EOL:s (they do not vanish in favor of spaces due to HTML, instead
-- the EOL arrow is showed)
-- * too long lines (they are force-broken)
-- * codes below 32 other than EOL
-- There is also "mw.text.nowiki" with some limitations, most notably
-- about multiple spaces and EOL:s.
-- In order to fix EOL we show the EOL arrow (preceded by space) for every
-- incoming LF, but do a "<br>" only once after multiple subsequent LF:s.
-- We must be UTF8-aware. A UTF8 char must be either split into hex codes,
-- or preserved over its complete length ie not split nor encoded at all.
-- Note that this causes BLOAT. The caller is responsible for
-- adding "<big>"..."</big>" if desired.
local function lfiultencode (strkrampuj,nummxwidth,boowarrna,boosplitutf)
local stronechar = ''
local strkolorr = ''
local strkood = ''
local numstrlne = 0
local numpeekynx = 1 -- ONE-based index
local numcahr = 0
local numcxxhr = 0
local numutf8len = 0
local numaccuwidth = 0 -- accumulated width
local numcolour = 0 -- 0,1,2,3 -- R,G,B,Y
local boonbsp = true -- "true" needed for junk lines containing only space
local boosplnow = false -- allow forced split in some cases
local boofickpilen = false -- true after LF arrow causes "<br>" later
if (type(nummxwidth)~='number') then
nummxwidth = 80
end--if
if ((nummxwidth<20) or (nummxwidth>200)) then
nummxwidth = 80
end--if
numstrlne = string.len (strkrampuj)
while true do -- outer genuine loop
if (numpeekynx>numstrlne) then
break
end--if
numcahr = string.byte (strkrampuj,numpeekynx,numpeekynx)
numpeekynx = numpeekynx + 1 -- ONE-based index
while true do -- inner fake loop
if (numcahr==10) then
break -- to join mark -- inner fake loop -- special processing for LF
end--if
if (numcahr==32) then
if (boonbsp) then
stronechar = ' ' -- this prevents space reduction
else
stronechar = ' '
end--if
boonbsp = not boonbsp
break -- to join mark -- inner fake loop
end--if
if (numcahr<32) then
stronechar = '{$' .. lfuint8tohex (numcahr) .. '}' -- always as hex
break -- to join mark -- inner fake loop
end--if
if (numcahr>127) then
boosplnow = boosplitutf
numutf8len = lfulnutf8char (numcahr)
if (numutf8len==0) then
boosplnow = true -- forced split for broken UTF8 sequence
else
numutf8len = numutf8len - 1 -- more char:s to pick
end--if
if ((numpeekynx+numutf8len)>(numstrlne+1)) then
boosplnow = true -- forced split for truncated UTF8 sequence
end--if
if (boosplnow) then
stronechar = '{$' .. lfuint8tohex (numcahr) .. '}'
else
stronechar = string.char (numcahr) -- preserve "numcahr" below
while true do -- deep loop copy UTF8 char
if (numutf8len==0) then
break
end--if
numcxxhr = string.byte (strkrampuj,numpeekynx,numpeekynx)
numpeekynx = numpeekynx + 1
numutf8len = numutf8len - 1
stronechar = stronechar .. string.char (numcxxhr)
end--while -- deep loop copy UTF8 char
end--if
break -- to join mark
end--if (numcahr>127) then
if (lfgis62safe(numcahr)) then -- safe ASCII ie 0...9 A...Z a...z
stronechar = string.char (numcahr) -- do NOT encode safe char:s
break -- to join mark
end--if
stronechar = '&#' .. tostring (numcahr) .. ';' -- dec-encode some ASCII
break -- finally to join mark
end--while -- inner fake loop -- join mark
if (numcahr==10) then
if (numaccuwidth>=nummxwidth) then
strkood = strkood .. '<br>'
numaccuwidth = 0
boonbsp = true -- "true" needed for junk lines containing only space
end--if
strkood = strkood .. ' ' .. constrpilen
numaccuwidth = numaccuwidth + 2 -- counts doubly
boofickpilen = true
else
if (boofickpilen or (numaccuwidth>=nummxwidth)) then
strkood = strkood .. '<br>'
numaccuwidth = 0
boonbsp = true -- "true" needed for junk lines containing only space
end--if
if (boowarrna) then
strkolorr = contabempatwarna [numcolour]
numcolour = mathmod ((numcolour+1),4) -- index 0...3
strkood = strkood .. '<span style="background-color:#' .. strkolorr .. ';">' .. stronechar .. '</span>'
else
strkood = strkood .. stronechar
end--if
numaccuwidth = numaccuwidth + 1
boofickpilen = false
end--if (numcahr==10) else
end--while -- outer genuine loop
return strkood
end--function lfiultencode
------------------------------------------------------------------------
-- Local function LFISPACUNDR !!!FIXME!!! unused -- column "call" ??
-- Spaces to underscores or vice-versa.
-- Incoming boolean "true" for underscores and "false" for spaces.
local function lfispacundr (strxxin, boounderlig)
local numleang = 0
local numandex = 0 -- ZERO-based
local numcxarr = 0
local strkatrol = ''
numleang = string.len (strxxin)
while true do -- genuine loop
if (numandex==numleang) then
break
end--if
numcxarr = string.byte (strxxin,(numandex+1),(numandex+1))
if ((numcxarr==32) or (numcxarr==95)) then
if (boounderlig) then
numcxarr = 95
else
numcxarr = 32
end--if
end--if
strkatrol = strkatrol .. string.char (numcxarr)
numandex = numandex + 1
end--while
return strkatrol
end--function lfispacundr
------------------------------------------------------------------------
-- Local function LFIKATPALDIGU
-- Brew cat insertion (no extra colon ":") or link to cat (with extra
-- colon ":") or link to page (appendix, other ns, even ns ZERO) from
-- 3 elements with optimization.
-- Input : * strprephyx -- ns prefix without colon, empty or
-- non-string if not desired ie ns ZERO
-- * strkataldnomo
-- * strhintvisi -- right part, empty or non-string if not desired
-- * numkattxtrakol -- ZERO for non-cat, ONE for cat insertion
-- (needed for optimization), TWO for extra
-- colon ie "colon rule" link to cat
local function lfikatpaldigu (strprephyx, strkataldnomo, strhintvisi, numkattxtrakol)
local strtigatipwiki = ''
if (type(strprephyx)~="string") then -- optional
strprephyx = ''
end--if
if (type(strhintvisi)~="string") then -- optional
strhintvisi = ''
end--if
if ((numkattxtrakol==1) and (strhintvisi==strkataldnomo)) then
strhintvisi = '' -- optimize: default is without ns prefix for cat:s
end--if
if (strprephyx~='') then
strkataldnomo = strprephyx .. ':' .. strkataldnomo -- now prefix plus name
end--if
if ((numkattxtrakol~=1) and (strhintvisi==strkataldnomo)) then
strhintvisi = '' -- optimize: default is with ns prefix if such is present
end--if
if (numkattxtrakol==2) then
strkataldnomo = ':' .. strkataldnomo -- ":Category"... apply "colon rule"
end--if
if (strhintvisi=='') then
strtigatipwiki = '[[' .. strkataldnomo .. ']]'
else
strtigatipwiki = '[[' .. strkataldnomo .. '|' .. strhintvisi .. ']]'
end--if
return strtigatipwiki
end--function lfikatpaldigu
------------------------------------------------------------------------
-- Local function LFIGETLEFTRIGHT
-- Split wikilink (in wide sense including cat insertions) into left
-- and right part detecting some common errors.
-- Input : * strinasy -- like " Category : Crime in Rhodesia | rho "
-- Output : * numlerikodo, strinasy, strhinto
-- Depends on functions :
-- [G] lfgtrimwhite
-- Status values:
-- * 0 : OK (also if no wall)
-- * 75 : empty string or wall only (both invalid per MediaWiki)
-- * 76 : left empty or whitespace only (both invalid per MediaWiki)
-- * 77 : wall YES and right empty (dubious: "[[gluon|]]")
-- * 78 : right whitespace only (common: "[[Category:Time machines| ]]")
-- * 79 : junk spaces left or right (dubious: "[[Wiktionary:Bots |bot]]")
local function lfigetleftright (strinasy)
local vartrovumuron = 0
local strhinto = '' -- preASSume no right part
local str9tmp = ''
local numlerikodo = 0 -- preASSume innocence
if ((strinasy=='') or (strinasy=='|')) then
numlerikodo = 75
strinasy = '' -- invalid
else
vartrovumuron = string.find(strinasy,'|',1,true)
if (vartrovumuron) then
if (vartrovumuron<(string.len(strinasy))) then
strhinto = string.sub (strinasy,(vartrovumuron+1),-1)
else
numlerikodo = 77 -- right empty, overrides right whitespace only
end--if
if (vartrovumuron>1) then
strinasy = string.sub (strinasy,1,(vartrovumuron-1))
else
numlerikodo = 76 -- left empty, overrides right empty (theoretically)
strinasy = '' -- left part empty, invalid
end--if
end--if (vartrovumuron) then
end--if ((strinasy=='') or (strinasy=='|')) else
if (strinasy~='') then -- possible codes 0 77 so far
str9tmp = lfgtrimwhite (strinasy) -- left
if (str9tmp=='') then
numlerikodo = 76 -- left empty or whitespace only, overrides right empty
end--if
if (strinasy~=str9tmp) then
strinasy = str9tmp
if (numlerikodo==0) then
numlerikodo = 79 -- junk spaces
end--if
end--if
end--if
if (strhinto~='') then
str9tmp = lfgtrimwhite (strhinto) -- right
if ((str9tmp=='') and (numlerikodo==0)) then
numlerikodo = 78 -- right whitespace only, overrides junk spaces left
end--if
if (strhinto~=str9tmp) then
strhinto = str9tmp
if (numlerikodo==0) then
numlerikodo = 79 -- junk spaces
end--if
end--if
end--if
return numlerikodo, strinasy, strhinto
end--function lfigetleftright
------------------------------------------------------------------------
-- Local function LFIVALIDATE6HEX
-- Validate a 6-digit HEX colour, only uppercase.
-- Output : * booh6hisvalid -- true if string is valid
-- Depends on functions :
-- [N] lfnonehextoint
-- Criteria:
-- * length 6 chars
-- * "0"..."9" and "A"..."F"
local function lfivalidate6hex (strmyhexsixcolor)
local numuuinx = 0 -- ZERO-based
local numcyyaar = 0
local booh6hisvalid = false -- preASSume guilt -- will be the final verdict
if (string.len(strmyhexsixcolor)==6) then
booh6hisvalid = true -- preASSume innocence
while true do
if (numuuinx==6) then
break -- done search, all OK
end--if
numcyyaar = string.byte(strmyhexsixcolor,(numuuinx+1),(numuuinx+1))
if (lfnonehextoint(numcyyaar)>15) then
booh6hisvalid = false -- guilt proven
break -- abort search
end--if
numuuinx = numuuinx + 1 -- ZERO-based
end--while
end--if
return booh6hisvalid
end--function lfivalidate6hex
------------------------------------------------------------------------
-- Local function LFIVALIUMDCTLSTR
-- Validate control string against restrictive pattern (dec).
-- Input : * strresdpat -- restrictive pattern (max 200 char:s)
-- * strctldstr -- incoming suspect
-- Output : * numbadpos -- bad position, or 254 wrong length, or 255 success
-- Depends on functions :
-- [N] lfdec1digit
-- Content of restrictive pattern:
-- * "." -- skip check
-- * "-" and "?" -- must match literally
-- * digit "1"..."9" ("0" invalid) -- inclusive upper limit (min ZERO)
local function lfivaliumdctlstr (strresdpat, strctldstr)
local numlenresdpat = 0
local numldninkom = 0
local numcomperindex = 0 -- ZERO-based
local numead2 = 0
local numead3 = 0
local numbadpos = 254 -- preASSume guilt (len differ or too long or ...)
local booddaan = false
numlenresdpat = string.len(strresdpat)
numldninkom = string.len(strctldstr)
if ((numlenresdpat<=200) and (numlenresdpat==numldninkom)) then
while true do
if (numcomperindex==numlenresdpat) then
numbadpos = 255
break -- success
end--if
numead2 = string.byte(strresdpat,(numcomperindex+1),(numcomperindex+1)) -- rest
numead3 = string.byte(strctldstr,(numcomperindex+1),(numcomperindex+1)) -- susp
booddaan = false
if ((numead2==45) or (numead2==63)) then
if (numead2~=numead3) then
numbadpos = numcomperindex
break -- "-" and "?" must match literally
end--if
booddaan = true -- position OK
end--if
if (numead2==46) then -- skip for dot "."
booddaan = true -- position OK
end--if
if (not booddaan) then
numead2 = lfdec1digit(numead2) -- rest
if (numead2>9) then -- limit defined or bad ??
numbadpos = 254
break -- bad restrictive pattern
else
numead3 = lfdec1digit(numead3) -- susp
if (numead3>numead2) then
numbadpos = numcomperindex
break -- value limit violation
end--if
end--if (numead2>9) else
end--if (not booddaan) then
numcomperindex = numcomperindex + 1
end--while
end--if ((numlenresdpat<=200) and (numlenresdpat==numldninkom)) then
return numbadpos
end--function lfivaliumdctlstr
------------------------------------------------------------------------
-- Local function LFICHKPARAM
-- Check one incoming param against type and range.
-- Input : * varmyparam
-- * numtypeofparam -- 0 string | 1 one-digit dec | 2 two-digit dec
-- 6 hex six-digit colour
-- 8 hex integer !!!FIXME!!! incomplete
-- * numzzmin, numzzmax -- relevant for all types except 6
-- Output : * numverdictparam -- 0 nope | 1 exists invalid | 2 exists valid
-- * varparvalue -- copy (for types ZERO and 6) or converted value
-- (for other types) or type "nil", do NOT use to
-- check validity
-- Depends on functions :
-- [I] lfivalidate6hex
-- [N] lfdec1digit lfstrondig2int lfstrtwdig2int lfnonehextoint
local function lfichkparam (varmyparam, numtypeofparam, numzzmin, numzzmax)
local varparvalue = 0 -- preASSume nope
local numverdictparam = 0 -- preASSume nope
local numlenof66param = 0
local num66temp = 0
if (type(varmyparam)=='string') then
numverdictparam = 1 -- preASSume guilt
numlenof66param = string.len(varmyparam)
if ((numtypeofparam==0) and (numlenof66param>=numzzmin) and (numlenof66param<=numzzmax)) then -- 0 string
numverdictparam = 2 -- type ZERO OK !!!
varparvalue = varmyparam
end--if
if (numtypeofparam==1) then -- 1 one-digi
num66temp = lfstrondig2int (varmyparam)
if ((num66temp>=numzzmin) and (num66temp<=numzzmax)) then
numverdictparam = 2 -- type ONE OK !!!
varparvalue = num66temp -- converted
end--if
end--if
if (numtypeofparam==2) then -- 2 two-digi
num66temp = lfstrtwdig2int (varmyparam)
if ((num66temp>=numzzmin) and (num66temp<=numzzmax)) then
numverdictparam = 2 -- type 2 OK !!!
varparvalue = num66temp -- converted
end--if
end--if
if (numtypeofparam==6) then -- 6 hex six-digit colour
if (lfivalidate6hex(varmyparam)) then
numverdictparam = 2 -- type 6 OK !!!
varparvalue = varmyparam
end--if
end--if
end--if (type(varmyparam)=='string') then
if (numverdictparam~=2) then
varparvalue = nil
end--if
return numverdictparam, varparvalue
end--function lfichkparam
------------------------------------------------------------------------
-- Local function LFIFILLNAME
-- Replace placeholder "\@" "\\@" by augmented name of the caller.
-- To be called ONLY from "lfhfillsurrstrtab".
-- The name of the caller is submitted to us as a parameter thus we
-- do NOT access any constants and do NOT have to peek it either.
local function lfifillname (strmessage, strcaller)
local strhasill = ''
local numstrloen = 0
local numindfx = 1 -- ONE-based
local numcjar = 0
local numcjnext = 0
numstrloen = string.len (strmessage)
while true do
if (numindfx>numstrloen) then
break -- empty input is useless but cannot cause major harm
end--if
numcjar = string.byte (strmessage,numindfx,numindfx)
numindfx = numindfx + 1
numcjnext = 0 -- preASSume no char
if (numindfx<=numstrloen) then
numcjnext = string.byte (strmessage,numindfx,numindfx)
end--if
if ((numcjar==92) and (numcjnext==64)) then
strhasill = strhasill .. strcaller -- invalid input is caller's risk
numindfx = numindfx + 1 -- skip 2 octet:s of the placeholder
else
strhasill = strhasill .. string.char (numcjar)
end--if
end--while
return strhasill
end--function lfifillname
------------------------------------------------------------------------
-- Local function LFIKODEOSG
-- Transcode eo X-surrogates to cxapeloj in a single string (eo only).
-- Input : * streosurr -- ANSI string (empty is useless but cannot
-- cause major harm)
-- Output : * strutf8eo -- UTF8 string
-- Depends on functions :
-- [E] mathdiv mathmod
-- Depends on constants :
-- * table "contabtransluteo" inherently holy
-- To be called ONLY from "lfhfillsurrstrtab".
-- * the "x" in a surr pair is case insensitive,
-- for example both "kacxo" and "kacXo" give same result
-- * avoid "\", thus for example "ka\cxo" would get converted but the "\" kept
-- * double "x" (both case insensitive) prevents conversion and becomes
-- reduced to single "x", for example "kacxxo" becomes "kacxo"
local function lfikodeosg (streosurr)
local vareopeek = 0
local strutf8eo = ''
local numeoinplen = 0
local numinpinx = 0 -- ZERO-based source index
local numknar0k = 0 -- current char
local numknaf1x = 0 -- next char (ZERO is NOT valid)
local numknaf2x = 0 -- post next char (ZERO is NOT valid)
local boonext1x = false
local boonext2x = false
local boosudahdone = false
numeoinplen = string.len(streosurr)
while true do
if (numinpinx>=numeoinplen) then
break
end--if
numknar0k = string.byte(streosurr,(numinpinx+1),(numinpinx+1))
numknaf1x = 0 -- preASSume no char
numknaf2x = 0 -- preASSume no char
if ((numinpinx+1)<numeoinplen) then
numknaf1x = string.byte(streosurr,(numinpinx+2),(numinpinx+2))
end--if
if ((numinpinx+2)<numeoinplen) then
numknaf2x = string.byte(streosurr,(numinpinx+3),(numinpinx+3))
end--if
boonext1x = ((numknaf1x==88) or (numknaf1x==120)) -- case insensitive
boonext2x = ((numknaf2x==88) or (numknaf2x==120)) -- case insensitive
boosudahdone = false
if (boonext1x and boonext2x) then -- got "xx"
strutf8eo = strutf8eo .. string.char(numknar0k,numknaf1x) -- keep one "x" only
numinpinx = numinpinx + 3 -- eaten 3 written 2
boosudahdone = true
end--if
if (boonext1x and (not boonext2x)) then -- got yes-"x" and no-"x"
vareopeek = contabtransluteo[numknar0k] -- UINT16 or type "nil"
if (type(vareopeek)=='number') then
strutf8eo = strutf8eo .. string.char(mathdiv(vareopeek,256),mathmod(vareopeek,256)) -- add UTF8 char
numinpinx = numinpinx + 2 -- eaten 2 written 2
boosudahdone = true
end--if
end--if
if (not boosudahdone) then
strutf8eo = strutf8eo .. string.char(numknar0k) -- copy char
numinpinx = numinpinx + 1 -- eaten 1 written 1
end--if
end--while
return strutf8eo
end--function lfikodeosg
------------------------------------------------------------------------
-- Local function LFIKODSVSG
-- Transcode sv blackslash-surrogates in a single string (sv only).
-- Input : * strsvsurr -- ANSI string (empty is useless but cannot
-- cause major harm)
-- Output : * strutf8sv -- UTF8 string
-- Depends on functions :
-- [E] mathdiv mathmod
-- Depends on constants :
-- * table "contabtranslutsv" inherently holy
-- To be called ONLY from "lfhfillsurrstrtab".
-- * the latter letter in a surr triple is case insensitive,
-- for example both "\AEgare" and "\Aegare" give same result
local function lfikodsvsg (strsvsurr)
local varsvpeek = 0
local strutf8sv = ''
local strsvdouble = ''
local numsvinplen = 0
local numinpinx = 0 -- ZERO-based source index
local numsvonechar = 0 -- current char
numsvinplen = string.len(strsvsurr)
while true do
if (numinpinx>=numsvinplen) then
break
end--if
numsvonechar = string.byte(strsvsurr,(numinpinx+1),(numinpinx+1))
strsvdouble = '' -- preASSume no dblchar
if ((numsvonechar==92) and ((numinpinx+2)<numsvinplen)) then
strsvdouble = string.sub(strsvsurr,(numinpinx+2),(numinpinx+3))
end--if
varsvpeek = contabtranslutsv[strsvdouble] -- UINT16 or type "nil"
if (type(varsvpeek)=='number') then
strutf8sv = strutf8sv .. string.char(mathdiv(varsvpeek,256),mathmod(varsvpeek,256)) -- add UTF8 char
numinpinx = numinpinx + 3 -- eaten 3 written 2
else
strutf8sv = strutf8sv .. string.char(numsvonechar) -- copy char
numinpinx = numinpinx + 1 -- eaten 1 written 1
end--if
end--while
return strutf8sv
end--function lfikodsvsg
------------------------------------------------------------------------
-- Local function LFICENQTABQLEFQTXT
-- Outside center inside left, invisible.
local function lficenqtabqlefqtxt (strwhatever)
strwhatever = '<table style="margin:auto;"><tr><td style="text-align:left;">' .. strwhatever .. '</td></tr></table>'
return strwhatever
end--function lficenqtabqlefqtxt
------------------------------------------------------------------------
-- Local function LFILEFQDIVQLEFQTXT
-- Outside left inside left, invisible.
local function lfilefqdivqlefqtxt (strwhootever)
strwhootever = '<div style="text-align:left;">' .. strwhootever .. '</div>'
return strwhootever
end--function lfilefqdivqlefqtxt
------------------------------------------------------------------------
-- Local function LFIPRETABLE
-- Outside left inside left, visible.
local function lfipretable (strpredabletext, numfontsizepercent)
strpredabletext = '<table><tr><td style="border:1px solid #E0E0E0;padding:0 0.15em 0 0.15em;background:#F8F8F8;font-family:monospace;text-align:left;font-size:' .. tostring(numfontsizepercent) .. '%;">' .. strpredabletext .. '</td></tr></table>'
return strpredabletext
end--function lfipretable
------------------------------------------------------------------------
-- Local function LFIRESTOREFROMTRIPLE
-- Restore ordinary doublebracket form from triplebracket workaround.
local function lfirestorefromtriple (strin9x9ut)
local varfiindnes = 0
local booalreadydone = false
while true do -- genuine loop but no index
booalreadydone = true
varfiindnes = string.find(strin9x9ut,'{({',1,true)
if (varfiindnes) then
strin9x9ut = string.sub(strin9x9ut,1,varfiindnes) .. string.sub(strin9x9ut,(varfiindnes+2),-1)
booalreadydone = false
end--if
varfiindnes = string.find(strin9x9ut,'})}',1,true)
if (varfiindnes) then
strin9x9ut = string.sub(strin9x9ut,1,varfiindnes) .. string.sub(strin9x9ut,(varfiindnes+2),-1)
booalreadydone = false
end--if
if (booalreadydone) then
break
end--if
end--while
return strin9x9ut -- same var for in and out
end--function lfirestorefromtriple
------------------------------------------------------------------------
-- Local function LFIRESTOREFROMNETAG
-- Restore ordinary form from ne-workaround for aggressive tags.
-- <pre> <--> <pnere>
-- <nowiki> <--> <nonewiki>
-- <ref> <--> <renef> even for "<ref group=" and "<ref name="
-- <gallery> <--> <gallenery>
local function lfirestorefromnetag (strin9y9ut)
local varfiindtag = 0
local booalreadydoen = false
while true do -- genuine loop but no index
booalreadydoen = true
varfiindtag = string.find(strin9y9ut,'<pnere>',1,true)
if (varfiindtag) then
strin9y9ut = string.sub(strin9y9ut,1,(varfiindtag+1)) .. string.sub(strin9y9ut,(varfiindtag+4),-1)
booalreadydoen = false
end--if
varfiindtag = string.find(strin9y9ut,'</pnere>',1,true)
if (varfiindtag) then
strin9y9ut = string.sub(strin9y9ut,1,(varfiindtag+2)) .. string.sub(strin9y9ut,(varfiindtag+5),-1)
booalreadydoen = false
end--if
varfiindtag = string.find(strin9y9ut,'<nonewiki>',1,true)
if (varfiindtag) then
strin9y9ut = string.sub(strin9y9ut,1,(varfiindtag+2)) .. string.sub(strin9y9ut,(varfiindtag+5),-1)
booalreadydoen = false
end--if
varfiindtag = string.find(strin9y9ut,'</nonewiki>',1,true)
if (varfiindtag) then
strin9y9ut = string.sub(strin9y9ut,1,(varfiindtag+3)) .. string.sub(strin9y9ut,(varfiindtag+6),-1)
booalreadydoen = false
end--if
varfiindtag = string.find(strin9y9ut,'<renef>',1,true)
if (varfiindtag) then
strin9y9ut = string.sub(strin9y9ut,1,(varfiindtag+2)) .. string.sub(strin9y9ut,(varfiindtag+5),-1)
booalreadydoen = false
end--if
varfiindtag = string.find(strin9y9ut,'<renef name=',1,true)
if (varfiindtag) then
strin9y9ut = string.sub(strin9y9ut,1,(varfiindtag+2)) .. string.sub(strin9y9ut,(varfiindtag+5),-1)
booalreadydoen = false
end--if
varfiindtag = string.find(strin9y9ut,'<renef group=',1,true)
if (varfiindtag) then
strin9y9ut = string.sub(strin9y9ut,1,(varfiindtag+2)) .. string.sub(strin9y9ut,(varfiindtag+5),-1)
booalreadydoen = false
end--if
varfiindtag = string.find(strin9y9ut,'</renef>',1,true)
if (varfiindtag) then
strin9y9ut = string.sub(strin9y9ut,1,(varfiindtag+3)) .. string.sub(strin9y9ut,(varfiindtag+6),-1)
booalreadydoen = false
end--if
varfiindtag = string.find(strin9y9ut,'<gallenery>',1,true)
if (varfiindtag) then
strin9y9ut = string.sub(strin9y9ut,1,(varfiindtag+4)) .. string.sub(strin9y9ut,(varfiindtag+7),-1)
booalreadydoen = false
end--if
varfiindtag = string.find(strin9y9ut,'</gallenery>',1,true)
if (varfiindtag) then
strin9y9ut = string.sub(strin9y9ut,1,(varfiindtag+5)) .. string.sub(strin9y9ut,(varfiindtag+8),-1)
booalreadydoen = false
end--if
if (booalreadydoen) then
break
end--if
end--while
return strin9y9ut -- same var for in and out
end--function lfirestorefromnetag
------------------------------------------------------------------------
-- Local function LFIBREWCURLYCALL
local function lfibrewcurlycall (boonsiszero, strcurlytemcall, numbeeg, numennd)
if (boonsiszero) then
strcurlytemcall = ':' .. strcurlytemcall -- add colon for ns ZERO
end--if
if ((numbeeg==10) or (numbeeg==32)) then
strcurlytemcall = string.char (numbeeg) .. strcurlytemcall
end--if
if ((numennd==10) or (numennd==32)) then
strcurlytemcall = strcurlytemcall .. string.char (numennd)
end--if
strcurlytemcall = '{{' .. strcurlytemcall .. '}}'
return strcurlytemcall
end--function lfibrewcurlycall
------------------------------------------------------------------------
local function lfiexpandstatus (numpexpaste)
return '#X' .. lfnumto2digit(numpexpaste)
end--function lfiexpandstatus
local function lfisplitstatus (numzsplitste)
return '#S' .. lfnumto2digit(numzsplitste)
end--function lfisplitstatus
------------------------------------------------------------------------
-- Local function LFICOMBOSTATUS
-- Depends on functions :
-- [I] lfisplitstatus lfiexpandstatus
-- [N] lfnumto2digit
-- [E] mathisintrange mathdiv mathmod
local function lficombostatus (num3exp, num3spl)
local strcomplaint = '' -- keep empty on success
if (num3exp==70) then -- #X70
if (num3spl>=20) then -- #S20
strcomplaint = lfisplitstatus (num3spl) -- exp pass split fail
end--if
else
strcomplaint = lfiexpandstatus (num3exp) -- exp fail split irrelevant
end--if
return strcomplaint
end--function lficombostatus
------------------------------------------------------------------------
-- Local function LFIEXPLAIN
-- Depends on constants :
-- * table "contabxxplain" with string keys
local function lfiexplain (strrezultinut)
local varriskofnil = 0
varriskofnil = contabxxplain[strrezultinut]
if (type(varriskofnil)=='string') then
strrezultinut = strrezultinut .. ' ' .. varriskofnil
end--if
return strrezultinut -- same var for in and out
end--function lfiexplain
------------------------------------------------------------------------
-- Local function LFICONDICELROW
-- Brew either raw or cell <td>...</td> or row <tr>...</tr>.
-- Depends on upvalues :
-- * 2 strings "qstrtdbegin" and "qstrtdendus"
-- * table "qtabmy6columns"
local function lficondicelrow (strmytext, numtype0of5table, numindexofcell)
if (numtype0of5table~=0) then -- add cell "td" for all except ZERO
strmytext = qstrtdbegin .. strmytext .. qstrtdendus
end--if
if (numtype0of5table==5) then -- row of vertical table
strmytext = '<tr>' .. qstrtdbegin .. qtabmy6columns[numindexofcell] .. qstrtdendus .. strmytext .. '</tr>'
end--if
return strmytext -- same var for in and out
end--function lficondicelrow
------------------------------------------------------------------------
---- HIGH LEVEL FUNCTIONS [H] ----
------------------------------------------------------------------------
-- Local function LFHCONSTRUCTERAR
-- Input : * numerar6code -- 1 ... 99 or 2 ... 99 (resistent against invalid
-- data type, giving "??" on such)
-- * boopeek6it -- do peek description #E02...#E99 from table
-- Depends on functions :
-- [N] lfnumto2digit
-- [E] mathisintrange mathdiv mathmod
-- Depends on constants :
-- * maybe table contaberaroj TWO-based (holes permitted)
-- To be called ONLY from lfhbrewerror, lfhbrewerrsm,
-- lfhbrewerrsvr, lfhbrewerrinsi.
local function lfhconstructerar (numerar6code, boopeek6it)
local vardes6krip = 0
local numbottom6limit = 1
local stryt6sux = '#E'
if (boopeek6it) then
numbottom6limit = 2 -- #E01 is a valid code for submodule only
end--if
if (mathisintrange(numerar6code,numbottom6limit,99)) then
stryt6sux = stryt6sux .. lfnumto2digit(numerar6code)
if (boopeek6it) then
vardes6krip = contaberaroj[numerar6code] -- risk of type "nil"
if (type(vardes6krip)=='string') then
stryt6sux = stryt6sux .. ' ' .. vardes6krip
else
stryt6sux = stryt6sux .. ' ??' -- no text found
end--if
end--if (boopeek6it) then
else
stryt6sux = stryt6sux .. '??' -- no valid error code
end--if
return stryt6sux
end--function lfhconstructerar
------------------------------------------------------------------------
-- Local function LFHBREWERROR
-- Input : * numerar7code -- TWO-based error code 2 ... 99 (resistent
-- against invalid data type, giving "??" on such)
-- Depends on functions :
-- [H] lfhconstructerar
-- [N] lfnumto2digit
-- [E] mathisintrange mathdiv mathmod
-- Depends on constants :
-- * 3 strings constrelabg constrelaen constrlaxhu
-- * table contaberaroj TWO-based (holes permitted)
-- #E02...#E99, note that #E00 and #E01 are NOT supposed to be included here.
local function lfhbrewerror (numerar7code)
local stryt7sux = ''
stryt7sux = constrlaxhu .. constrelabg .. lfhconstructerar (numerar7code,true) .. constrelaen .. constrlaxhu
return stryt7sux
end--function lfhbrewerror
------------------------------------------------------------------------
-- Local function LFHFILLSURRSTRTAB
-- Process (fill in, transcode surr) either a single string, or all string
-- items in a table (even nested) using any type of keys/indexes (such as
-- a holy number sequence and non-numeric ones). Items with a non-string
-- value are kept as-is. For filling in own name, and converting eo and
-- sv surrogates (via 3 separate sub:s).
-- Input : * varinkommen -- type "string" or "table"
-- * varfyllo -- string, or type "nil" if no filling-in desired
-- * strlingkod -- "eo" or "sv" to convert surrogates, anything
-- else (preferably type "nil") to skip this
-- Depends on functions :
-- [I] lfifillname (only if filling-in desired)
-- [I] lfikodeosg (only if converting of eo X-surrogates desired)
-- [I] lfikodsvsg (only if converting of sv blackslash-surrogates desired)
-- [E] mathdiv mathmod (via "lfikodeosg" and "lfikodsvsg")
-- Depends on constants :
-- * table "contabtransluteo" inherently holy (via "lfikodeosg")
-- * table "contabtranslutsv" inherently holy (via "lfikodsvsg")
local function lfhfillsurrstrtab (varinkommen, varfyllo, strlingkod)
local varkey = 0 -- variable without type
local varele = 0 -- variable without type
local varutmatning = 0
local boodone = false
if (type(varinkommen)=='string') then
if (type(varfyllo)=='string') then
varinkommen = lfifillname (varinkommen,varfyllo) -- fill-in
end--if
if (strlingkod=='eo') then
varinkommen = lfikodeosg (varinkommen) -- surr
end--if
if (strlingkod=='sv') then
varinkommen = lfikodsvsg (varinkommen) -- surr
end--if
varutmatning = varinkommen -- copy, risk for no change
boodone = true
end--if
if (type(varinkommen)=='table') then
varutmatning = {} -- brew new table
varkey = next (varinkommen) -- try to pick 0:th (in no order) key/index
while true do
if (varkey==nil) then
break -- empty table or end reached
end--if
varele = varinkommen[varkey] -- pick element of unknown type
if ((type(varele)=='string') or (type(varele)=='table')) then
varele = lfhfillsurrstrtab (varele, varfyllo, strlingkod) -- RECURSION
end--if
varutmatning[varkey] = varele -- write at same place in dest table
varkey = next (varinkommen, varkey) -- try to pick next key/index
end--while
boodone = true
end--if
if (not boodone) then
varutmatning = varinkommen -- copy as-is whatever it is
end--if
return varutmatning
end--function lfhfillsurrstrtab
------------------------------------------------------------------------
-- Local function LFHTABLETOHTMLLISTA
-- Convert LUA table into a HTML list optionally inside
-- an invisible HTML table.
-- Input : * tabsomeytems -- ZERO-based LUA table, empty legal
-- * booaddtable
-- Output : * strhotomolo -- * empty string if incoming table is empty
-- * raw string if incoming table has ONE element
-- * else HTML list optionally inside
-- an invisible HTML table
-- Depends on functions :
-- [I] lficenqtabqlefqtxt
-- <li></li> for single items in list
-- <ul></ul> for complete list
local function lfhtabletohtmllista (tabsomeytems, booaddtable)
local var3elemento = 0
local strhotomolo = ''
local numindekso = 0 -- ZERO-based
while true do -- genuine loop over incoming table
var3elemento = tabsomeytems [numindekso]
if (type(var3elemento)~='string') then
break -- done
end--if
if (numindekso==0) then
strhotomolo = var3elemento
end--if
if (numindekso==1) then
strhotomolo = '<li>' .. strhotomolo .. '</li>' -- postponed work for #0
end--if
if (numindekso>=1) then
strhotomolo = strhotomolo .. '<li>' .. var3elemento .. '</li>'
end--if
numindekso = numindekso + 1
end--while
if (numindekso>=2) then
strhotomolo = '<ul>' .. strhotomolo .. '</ul>'
if (booaddtable) then
strhotomolo = lficenqtabqlefqtxt(strhotomolo) -- outsid cent insid left
end--if
end--if
return strhotomolo
end--function lfhtabletohtmllista
------------------------------------------------------------------------
-- Local function LFHATMERGETAB
-- Merge multifield string into table.
-- Input : * streniroat -- string with some "@@", empty legal
-- * tabcolspan -- [0]...[5] booleans whether col active, no holes
-- * tabdefaultat -- [0]...[5] default names, ZERO-based, no holes
-- Output : * tabeliroat -- new table [0]...[5] may have holes,
-- special [9] true on error
-- This is applied on "tit=". Maximally 5 separators "@@" and 6 substrings.
local function lfhatmergetab (streniroat, tabcolspan, tabdefaultat)
local varfiinndd = 0
local tabfromtit = {} -- temp, can be too small or too big, but no holes
local tabeliroat = {} -- final, [0]...[5] may have holes
local numcxeloj0x5x = 0 -- ZERO-based
local numwithholes = 0
local bootitisbad = false -- preASSume innocence
while true do
varfiinndd = string.find (streniroat, "@@", 1, true)
if (not varfiinndd) then
if (streniroat~='') then
tabfromtit[numcxeloj0x5x] = streniroat -- take the last one
end--if
break -- good
end--if
if ((varfiinndd==1) or (varfiinndd==(string.len(streniroat)-1))) then
bootitisbad = true -- baad, found at begin or end
break
end--if
if (numcxeloj0x5x==5) then -- OFF-BY-ONE here the last one is added elsewhere
bootitisbad = true -- baad, exceeded max 6 substrings
break
end--if
tabfromtit[numcxeloj0x5x] = string.sub(streniroat,1,(varfiinndd-1))
streniroat = string.sub(streniroat,(varfiinndd+2),-1)
numcxeloj0x5x = numcxeloj0x5x + 1 -- NOT valid on exit from loop
end--while
if (bootitisbad) then
tabeliroat[9] = true -- baad
else
numcxeloj0x5x = 0
numwithholes = 0
while true do
if (numcxeloj0x5x==6) then
break
end--if
if tabcolspan[numcxeloj0x5x] then -- fill in only if used
if (tabfromtit[numwithholes]) then -- take only if available
tabeliroat[numcxeloj0x5x] = tabfromtit[numwithholes] -- custom
numwithholes = numwithholes + 1
else
tabeliroat[numcxeloj0x5x] = tabdefaultat[numcxeloj0x5x] -- default
end--if
end--if tabcolspan[numcxeloj0x5x] then
numcxeloj0x5x = numcxeloj0x5x + 1 -- INC this irrespective of tabcolspan
end--while
end--if
return tabeliroat
end--function lfhatmergetab
------------------------------------------------------------------------
-- Local function LFHPARSEMAP
-- Parse and map the wikitext and record findings.
-- Input : * strwiki7text
-- Output : * tabmy3table -- nested: [0] findings | [1] main map |
-- [2] boundary map
-- We can avoid maintaining a stack since we count wikilinks only and
-- give a f**k about template calls that could be mixed with them.
-- There is a problem with markers like "[[" and "]]". If they are nested
-- and adjacent like "[[[[" or "]]]]" then we must prevent the same char
-- from being shared among two hits.
local function lfhparsemap (strwiki7text)
local tabmy3table = {} -- nested
local tabmainmap = {} -- risk of type "nil" inside
local tabbouncer = {} -- tristate (1 2 type "nil"), many type "nil" inside
local tabfindings = {[0]=true,[1]=false,[2]=false,[3]=false} -- heterogeneous
local numwiki7len = 0 -- also for embedded func -- upper limit
local numlower7li = 1 -- only for embedded func -- lower limit
local numparseindex = 1 -- also for embedded func -- ONE-based
local numareatype = 0
local numyyyhitlng = 0 -- also for embedded func -- length of hit
local numareabykp = 0 -- only types 0...9 can be backuped
local nummaxdepth = 0 -- 97 under | 98 over
local boogotst4 = false -- strip 4 listed #A14 #M04
local boogotst5 = false -- strip all other #A15 #M05
local boogotshl = false -- !!!FIXME!!! not yet evaluated
local boogotpre = false
local boogotnwk = false
local boogotref = false
local boogotkom = false
local bootreaspace = false -- !!!FIXME!!! not yet evaluated
-- embedded function ie procedure, no output value, includes current char
-- IN PRARAM: stryyyfind
-- IN SHARED: strwiki7text numwiki7len numlower7li
-- numparseindex (ONE-based)
-- UT SHARED: numyyyhitlng
local function compareforwards (stryyyfind)
local booyyyfaund = false -- preASSume NOT found
numyyyhitlng = string.len(stryyyfind) -- searched string
if (numyyyhitlng>=1) then
if ((numparseindex>=numlower7li) and ((numparseindex+numyyyhitlng-1)<=numwiki7len)) then
booyyyfaund = (string.sub(strwiki7text,numparseindex,(numparseindex+numyyyhitlng-1))==stryyyfind)
end--if
end--if
if (not booyyyfaund) then
numyyyhitlng = 0
end--if
end--function compareforwards
-- embedded function ie procedure, no output value, fill
-- IN PRARAM: numyyydx (ONE-based) -- numyyyaratyp
-- triyyybgen (1 beg 2 end) -- numyyysize
-- CH SHARED: tabbouncer tabmainmap
local function filldesti (numyyydx, numyyyaratyp, triyyybgen, numyyysize)
if (numyyysize~=0) then
if (triyyybgen==1) then
tabbouncer [numyyydx] = 1 -- begin flag
end--if
while true do -- genuine loop, at least ONE iteration
tabmainmap [numyyydx] = numyyyaratyp
numyyysize = numyyysize - 1
if (numyyysize==0) then
break
end--if
numyyydx = numyyydx + 1 -- do this AFTER exit check
end--while genuine loop
if (triyyybgen==2) then
tabbouncer [numyyydx] = 2 -- end flag
end--if
end--if (numyyysize~=0) then
end--function filldesti
numwiki7len = string.len(strwiki7text) -- quasi-const
numlower7li = 1 -- const
while true do -- outer genuine loop over wikitext, char after char
if (numparseindex>numwiki7len) then -- ONE-based
break -- completed
end--if
numyyyhitlng = 0 -- preASSume no hit for every position
while true do -- fake loop
if (numareatype==15) then -- !!!FIXME!!! 14 not yet supported
compareforwards ('QINU'..string.char(96,34,39,127))
if (numyyyhitlng~=0) then
filldesti (numparseindex, numareatype, 2, numyyyhitlng) -- old type
numareatype = numareabykp -- after filling
break
end--if
end--if (numareatype==15) then
if (numareatype==22) then
compareforwards ('</pre>')
if (numyyyhitlng~=0) then
filldesti (numparseindex, numareatype, 2, numyyyhitlng) -- old type
numareatype = numareabykp -- after filling
break
end--if
end--if (numareatype==22) then
if (numareatype==23) then
compareforwards ('</nowiki>')
if (numyyyhitlng~=0) then
filldesti (numparseindex, numareatype, 2, numyyyhitlng) -- old type
numareatype = numareabykp -- after filling
break
end--if
end--if (numareatype==23) then
if (numareatype==27) then
compareforwards ('-->')
if (numyyyhitlng~=0) then
filldesti (numparseindex, numareatype, 2, numyyyhitlng) -- old type
numareatype = numareabykp -- after filling
break
end--if
end--if (numareatype==27) then
if (numareatype>=10) then
break -- no more chance for a hit at this position
end--if
compareforwards (']]')
if (numyyyhitlng~=0) then
filldesti (numparseindex, numareatype, 2, numyyyhitlng) -- old type
if (numareatype==0) then
nummaxdepth = 97 -- special value for underflow, recoverable
else
numareatype = numareatype - 1 -- inclusive limit from ONE to ZERO
end--if
break
end--if
compareforwards ('[[')
if (numyyyhitlng~=0) then
if (numareatype==9) then
nummaxdepth = 98 -- special value for overflow, FATAL
numareatype = 0 -- avoid #M03 below
else
numareatype = numareatype + 1 -- inclusive limit from 8 to 9
nummaxdepth = math.max(nummaxdepth,numareatype)
filldesti (numparseindex, numareatype, 1, numyyyhitlng) -- new type
end--if
break
end--if
compareforwards (string.char(127,39,34,96)..'UNIQ') -- '"`UNIQ--pre-00000002-QINU`"'
if (numyyyhitlng~=0) then
numareabykp = numareatype
numareatype = 15 -- #A14 #A15 for now !!!FIXME!!!
boogotst4 = true -- #M04 never to false again
boogotst5 = true -- #M05 never to false again
filldesti (numparseindex, numareatype, 1, numyyyhitlng) -- new type
break
end--if
compareforwards ('<pre>')
if (numyyyhitlng~=0) then
numareabykp = numareatype
numareatype = 22
boogotpre = true -- never to false again
filldesti (numparseindex, numareatype, 1, numyyyhitlng) -- new type
break
end--if
compareforwards ('<nowiki>')
if (numyyyhitlng~=0) then
numareabykp = numareatype
numareatype = 23
boogotnwk = true -- never to false again
filldesti (numparseindex, numareatype, 1, numyyyhitlng) -- new type
break
end--if
compareforwards ('<!--')
if (numyyyhitlng~=0) then
numareabykp = numareatype
numareatype = 27
boogotkom = true -- never to false again
filldesti (numparseindex, numareatype, 1, numyyyhitlng) -- new type
break
end--if
break -- finally to join mark
end--while -- fake loop -- join mark
if (nummaxdepth==98) then
break -- FATAL
end--if
if (numyyyhitlng==0) then
filldesti (numparseindex, numareatype, 0, 1) -- current type, no hit
numparseindex = numparseindex + 1 -- ONE-based, no hit
else
numparseindex = numparseindex + numyyyhitlng -- ONE-based, YES hit
end--if
end--while outer genuine loop over wikitext, char after char
if (numparseindex<=numwiki7len) then -- ONE-based
filldesti (numparseindex, 255, 0, (numwiki7len-numparseindex+1)) -- fill up on FATAL
end--if
while true do -- lower fake loop
if ((numareatype>=16) and (numareatype<=30)) then -- do NOT incl 14 15 her
tabfindings [1] = true -- #M01 no other discovery possible
break -- to join mark
end--if
if ((numareatype==14) or (numareatype==15)) then
tabfindings [2] = true -- #M02 no other discovery possible
break -- to join mark
end--if
if (numareatype~=0) then
tabfindings [3] = true -- #M03 no other discovery possible
break -- to join mark
end--if
tabfindings [20] = nummaxdepth -- #M20 value 97 or 98 is an error
if (nummaxdepth>=10) then
break -- to join mark -- no other discovery possible for both 97 and 98
end--if
tabfindings [ 4] = boogotst4 -- #M04 !!!FIXME!!! does not work yet fully 4 vs 5
tabfindings [ 5] = boogotst5 -- #M05
tabfindings [ 6] = boogotshl -- #M06 !!!FIXME!!! does not work yet
tabfindings [ 8] = boogotpre -- #M08
tabfindings [ 9] = boogotnwk -- #M09
tabfindings [10] = boogotref -- #M10 !!!FIXME!!! does not work yet
tabfindings [11] = boogotkom -- #M11
tabfindings [22] = bootreaspace -- #M22 !!!FIXME!!! does not work yet
break -- finally to join mark
end--while -- lower fake loop -- join mark
tabmy3table = {[0]=tabfindings,[1]=tabmainmap,[2]=tabbouncer}
return tabmy3table
end--function lfhparsemap
------------------------------------------------------------------------
-- Local function LFHSPLITHIDDEN
-- Split one string into two strings based on "*HIDDEN*".
-- Input : * stranontextin -- one complete call without the outer
-- enclosing {{ ... }}, or one or several
-- calls each with its private {{ ... }}
-- Output : * numstratus -- ZERO or #E48 or #E49
-- * strekspandu
-- * strmontru
-- Hidden parameters must not contain [[ ]] {{ (note that "}}" closes
-- a call), violation gives #E48. "*HIDDEN*" must NOT occur without
-- preceding wall, violation gives #E49.
-- For "nsm=2" there can be several calls, each terminated by "}}".
-- Theoretically hidden parameters are on depth ZERO if no enclosing {{ ... }}
-- is included, and on depth ONE if it is there when using "nsm=2", but we do
-- NOT evaluate the depth for {{ ... }} at all when mapping, and do NOT use
-- the map of the incoming anonymous parameter here.
-- Instead we do a very dumb parsing delimited by "|" and "}}" (not by "{{").
-- On every "*HIDDEN*" we skip back until preceding wall (inclusive), and
-- forward until following wall or "}}" or end of string (exclusive). We
-- leave every legal content pass, but do not catch every faulty content.
-- Legal:
-- ax|pagenameoverridetestonly*HIDDEN*Pohon
-- ax|pagenameoverridetestonly*HIDDEN*Pohon|nodog*HIDDEN*true
-- ax|pagenameoverridetestonly*HIDDEN*Pohon|text={{#ifexist:sillypage|COOL}}
-- ax|text={{#ifexist:sillypage|COOL}}|pagenameoverridetestonly*HIDDEN*Pohon|nodog*HIDDEN*true
-- {{ax|pagenameoverridetestonly*HIDDEN*Pohon}}
-- {{ax|pagenameoverridetestonly*HIDDEN*Pohon}}{{bx|pagenameoverridetestonly*HIDDEN*Pohon}}
-- <br>{{ax|pagenameoverridetestonly*HIDDEN*Pohon}}{{bx|pagenameoverridetestonly*HIDDEN*Pohon}}<br>
-- Faulty:
-- pagenameoverridetestonly*HIDDEN*Pohon
-- ax|pagenameoverridetestonly*HIDDEN*[[File:Pohon.png|10000px]]|nodog*HIDDEN*true
-- ax|pagenameoverridetestonly*HIDDEN*{{#ifexist:sillypage|COOL}}|nodog*HIDDEN*true
-- ax|pagenameoverridetestonly*HIDDEN*XX{{#ifexist:sillypage|COOL}}|nodog*HIDDEN*true
-- * strategy:
-- * assign boohad3wall to false
-- * assign boo3hidden boo3bracket to false
-- * walk through text char after char accumulating single chars
-- into one temporary string
-- * on every wall "|" or "}}" or end of input string
-- * if both boo3hidden boo3bracket give #E48
-- * if boo3hidden is true dump from one temporary string
-- only into the expansion output
-- * else dump from one temporary string into both output
-- strings
-- * empty the temporary string and copy the "|" or "}}" to it
-- * assign boohad3wall to true on wall but NOT to false on "}}"
-- * reassign both boo3hidden boo3bracket to false
-- * if *HIDDEN* is found then
-- * if boohad3wall is false give #E49
-- * skip it in the source
-- * drop "=" into the temporary string
-- * assign boo3hidden to true
-- * if doublebracket if found then assign boo3bracket to true but no skip
-- * if nothing else then copy single char
local function lfhsplithidden (stranontextin, tabanonmainmap)
local strekspandu = ''
local strmontru = ''
local strakkumu = ''
local numstratus = 0 -- preASSume innocence
local numin3len = 0
local numin3dex = 0
local num3kk3kk = 0
local numre3serve = 0
local boohad3wall = false
local boo3hidden = false
local boo3bracket = false
local bootwo3same = false
local booprizorgita = false
numin3len = string.len(stranontextin)
while true do
numre3serve = numin3len - numin3dex -- can be ZERO but not less
if (numre3serve~=0) then
num3kk3kk = string.byte(stranontextin,(numin3dex+1),(numin3dex+1))
end--if
bootwo3same = ((numre3serve>=2) and (string.byte(stranontextin,(numin3dex+2),(numin3dex+2))==num3kk3kk))
booprizorgita = false
if ((numre3serve==0) or (num3kk3kk==124) or (bootwo3same and (num3kk3kk==125))) then
if (boo3hidden and boo3bracket) then
numstratus = 48 -- #E48 invalid doublebrackets in hidden
break
end--if
if (not boo3hidden) then
strmontru = strmontru .. strakkumu -- dump to both
end--if
strekspandu = strekspandu .. strakkumu
if (numre3serve==0) then
break -- done !!!
end--if
if (num3kk3kk==124) then
strakkumu = '|'
boohad3wall = true
numin3dex = numin3dex + 1
end--if
if (bootwo3same and (num3kk3kk==125)) then
strakkumu = '}}'
numin3dex = numin3dex + 2
end--if
boo3hidden = false -- & evaluated per parameter
boo3bracket = false -- &
booprizorgita = true -- do NOT copy a char this time
end--if
if ((not booprizorgita) and (numre3serve>=8)) then
if (string.sub(stranontextin,(numin3dex+1),(numin3dex+8))=='*HIDDEN*') then
if (not boohad3wall) then
numstratus = 49 -- #E49 *HIDDEN* without preceding wall "|"
break
end--if
numin3dex = numin3dex + 8 -- reserve soon can be ZERO but not less
strakkumu = strakkumu .. '='
boo3hidden = true
booprizorgita = true -- do NOT copy a char this time
end--if
end--if
if ((not booprizorgita) and bootwo3same) then
if ((num3kk3kk==91) or (num3kk3kk==93) or (num3kk3kk==123)) then
boo3bracket = true -- YES DO copy a char below
end--if
end--if
if (not booprizorgita) then
strakkumu = strakkumu .. string.char(num3kk3kk)
numin3dex = numin3dex + 1
end--if
end--while
if (numstratus~=0) then
strekspandu = ''
strmontru = ''
end--if
return numstratus, strekspandu, strmontru
end--function lfhsplithidden
------------------------------------------------------------------------
-- Local function LFHTABLEWITHMAP
-- Visualize the map by brewing a HTML table from wikitext plus parallel map.
-- Input : * stralltextm -- must NOT be empty
-- * tabthismap -- nested: [0] findings | [1] main map |
-- [2] boundary map -- MUST MATCH THE STRING !!!
-- Depends on functions :
-- [G] lfgtestnum lfgtestuc lfgtestlc lfgis62safe
-- Depends on constants :
-- * table "contabbk" for background colors
-- length 01...08 -> width 8 & 1 row
-- length 09...18 -> width 6 & 2 or 3 rows
-- length 19...64 -> width 8 & 3...8 rows
-- length >=65 -> width 10 & >=6 rows
local function lfhtablewithmap (stralltextm, tabthismap)
local strvisualizedmap = ''
local strhex6color = ''
local stronecell = ''
local numlencofwikitext = 0
local numwidthincells = 0 -- 6 or 8 or 10
local numasciizindex = 0 -- ZERO-based
local numxcoordinate = 0 -- ZERO-based
local numkodchar = 0
local numfrommap = 0
local tribegiend = 0
numlencofwikitext = string.len(stralltextm)
numwidthincells = 8 -- preASSume
if ((numlencofwikitext>=9) and (numlencofwikitext<=18)) then
numwidthincells = 6
end--if
if (numlencofwikitext>=65) then
numwidthincells = 10
end--if
while true do -- genuine loop over double content
if ((numasciizindex==numlencofwikitext) or (numxcoordinate==numwidthincells)) then
strvisualizedmap = '<tr>' .. strvisualizedmap .. '</tr>'
end--if
if (numasciizindex==numlencofwikitext) then
break -- done whole table
end--if
if (numxcoordinate==numwidthincells) then
numxcoordinate = 0 -- done row only
end--if
numkodchar = string.byte(stralltextm,(numasciizindex+1),(numasciizindex+1))
numfrommap = tabthismap[1][numasciizindex+1] -- get area type
tribegiend = tabthismap[2][numasciizindex+1] -- get "B" or "E" maybeee
strhex6color = contabbk[numfrommap] or "58" -- dark grey if bad
if (string.len(strhex6color)==2) then
strhex6color = strhex6color .. strhex6color .. strhex6color -- 2->6 digits ;-)
end--if
stronecell = '<td style="border:1px solid #000000;padding:0 0.2em 0 0.2em;background:#' .. strhex6color .. ';">'
if (tribegiend==1) then
stronecell = stronecell .. '<b>B</b> '
end--if
if (tribegiend==2) then
stronecell = stronecell .. '<b>E</b> '
end--if
stronecell = stronecell .. tostring(numfrommap) .. ':<br>' .. tostring(numkodchar) .. ' '
if (lfgis62safe(numkodchar)) then
stronecell = stronecell .. string.char(numkodchar) .. '</td>'
else
if ((numkodchar>=33) and (numkodchar<=126)) then
stronecell = stronecell .. '&#' .. tostring(numkodchar) .. ';</td>'
else
stronecell = stronecell .. '?</td>'
end--if
end--if (lfgis62safe(numkodchar)) else
strvisualizedmap = strvisualizedmap .. stronecell
numasciizindex = numasciizindex + 1
numxcoordinate = numxcoordinate + 1
end--while
strvisualizedmap = '<table style="margin:auto;">' .. strvisualizedmap .. '</table>' -- done whole table
return strvisualizedmap
end--function lfhtablewithmap
------------------------------------------------------------------------
-- Local function LFHREPORTFINDINGS
-- Input : * tabhugemap -- theoretically ZERO-based, only findings
-- Output : * streirreport -- empty impossible
-- Depends on functions :
-- [H] lfhtabletohtmllista
-- [I] lfiexplain
-- [N] lfnumto2digit
-- [E] mathisintrange mathdiv mathmod
-- Depends on constants :
-- * table "contabxxplain" with string keys
local function lfhreportfindings (tabhugemap)
local varfinding = 0
local tabtemp77q = {}
local numconsecutiveindex = 1 -- ZERO valid but skip #M00
local numdestindex = 0
local streirreport = ''
while true do -- genuine loop 1...40
if (numconsecutiveindex==41) then
break
end--if
varfinding = tabhugemap [numconsecutiveindex] -- type "nil" or "boolean" or "number"
if (varfinding) then
tabtemp77q[numdestindex] = lfiexplain('#M' .. lfnumto2digit(numconsecutiveindex)) .. ': ' .. tostring(varfinding)
numdestindex = numdestindex + 1
end--if
numconsecutiveindex = numconsecutiveindex + 1
end--while
streirreport = 'Mapping done, '
if (numdestindex==0) then
streirreport = streirreport .. 'no finddings'
end--if
if (numdestindex==1) then -- <br> needed
streirreport = streirreport .. 'finding:<br>' .. lfhtabletohtmllista(tabtemp77q,true) .. '<br>'
end--if
if (numdestindex>=2) then -- no <br> here
streirreport = streirreport .. 'findings:' .. lfhtabletohtmllista(tabtemp77q,true)
end--if
return streirreport
end--function lfhreportfindings
------------------------------------------------------------------------
---- MEDIAWIKI INTERACTION FUNCTIONS [W] ----
------------------------------------------------------------------------
-- Local function LFWISTITLESAFE
-- Check whether title is safe (valid, not cat, not file,
-- no interwiki, standard form) returning a boolean.
-- Input : * strsftitle
-- Output : * bootitlecxsafe -- true if safe (false also
-- for non-string and invalid title)
-- Function "mw.title.new":
-- * returns type "nil" on invalid title string, and crashes if
-- input type is not string
-- * is NOT expensive (for our use) and works for non-existent titles too
-- * some useful fields:
-- * ".interwiki" is always a string, empty if no interwiki included
-- * ".namespace" is always a number, values <0 and 6 and 14
-- are unsafe ("Media:" gives -2)
-- * ".nsText" only bare ns prefix such as "Mall"
-- * ".prefixedText" {{FULLPAGENAME}} + maybe interwiki; veryfullpagename
-- including ns prefix and interwiki, a strictly standardized
-- form of title:
-- * adjusts letter case
-- * replaces underscores by spaces
-- * "Category:" becomes "Kategori:" in some languages
-- * removes extraneous spaces around colon ":"
-- * ".fullText" {{FULLPAGENAME}} + maybe interwiki + HTML section "#"
local function lfwistitlesafe (strsftitle)
local tabtitleobject = {}
local numnsoftheobject = 0
local bootitlecxsafe = false -- preASSume guilt
if (type(strsftitle)=='string') then
tabtitleobject = mw.title.new(strsftitle) -- type "nil" for invalid
if (type(tabtitleobject)=='table') then
numnsoftheobject = tabtitleobject.namespace
bootitlecxsafe = ((tabtitleobject.interwiki=='') and (numnsoftheobject>=0) and (numnsoftheobject~=6) and (numnsoftheobject~=14) and (tabtitleobject.prefixedText==strsftitle))
end--if
end--if
return bootitlecxsafe
end--function lfwistitlesafe
------------------------------------------------------------------------
-- Local function LFWGETNSOFTITLE
local function lfwgetnsoftitle (strnstitle)
local tabtitlensobject = {}
local numnsoftheobjk = 65535 -- preASSume guilt
if (type(strnstitle)=='string') then
tabtitlensobject = mw.title.new(strnstitle) -- type "nil" for invalid
if (type(tabtitlensobject)=='table') then
numnsoftheobjk = tabtitlensobject.namespace
end--if
end--if
return numnsoftheobjk
end--function lfwgetnsoftitle
------------------------------------------------------------------------
-- Local function LFWSPLIT3TITLE
local function lfwsplit3title (strsptitle)
local tabtitlespobject = {}
local strunfull = '' -- without prefix
local strnstoxt = ''
local numnsdetheobjk = 65535 -- preASSume guilt
if (type(strsptitle)=='string') then
tabtitlespobject = mw.title.new(strsptitle) -- type "nil" for invalid
if (type(tabtitlespobject)=='table') then
numnsdetheobjk = tabtitlespobject.namespace -- number
if (numnsdetheobjk<=2000) then
strunfull = tabtitlespobject.text -- string
strnstoxt = tabtitlespobject.nsText -- string, can be empty, no colon
else
numnsdetheobjk = 65535
end--if
end--if
end--if
return numnsdetheobjk, strunfull, strnstoxt
end--function lfwsplit3title
------------------------------------------------------------------------
-- Local function LFWBREW3URL
-- Brew httplink to current project from title + http parameters + visible
-- text, making it look like an ordinary wikilink.
-- Input : * arxinp4
-- * strwikipage -- title ie {{FULLPAGENAME}} or
-- for example "Special:WhatLinksHere"
-- * strhttpparam -- for example "hidetrans=1&hidelinks=1" or empty
-- * strvisible -- for example "do NOT click here" or empty
-- * boozordinary -- "true" to look like an ordinary wikilink,
-- "false" if this is undesirable or done outside
-- URL structure:
-- * https://en.wiktionary.org/wiki/Category:Vulgarities
-- * https://en.wiktionary.org/wiki/Category:Vulgarities?action=purge
-- * https://en.wiktionary.org/w/index.php?title=Category:Vulgarities
-- * https://en.wiktionary.org/w/index.php?title=Category:Vulgarities&action=purge
-- * https://en.wiktionary.org/wiki/Special:AllPages
-- * https://en.wiktionary.org/wiki/Special:AllPages?namespace=5
-- * https://en.wiktionary.org/wiki/Special:WhatLinksHere/Template:Bugger
-- * https://en.wiktionary.org/wiki/Special:WhatLinksHere/Template:Bugger?hidetrans=1&hidelinks=1
-- * https://en.wiktionary.org/w/index.php?title=Special:WhatLinksHere/Template:Bugger&hidetrans=1&hidelinks=1
-- * https://en.wiktionary.org/w/index.php?title=Special:WhatLinksHere&target=Template:Bugger&hidetrans=1&hidelinks=1
-- Only 4 ways to brew a URL:
-- * {{canonicalurl:{{FULLPAGENAME}}|action=purge}}
-- we use this one via ":preprocess", will work on any project
-- * {{SERVER}}{{SCRIPTPATH}}/index.php?title={{urlencode:{{FULLPAGENAME}}}}&action=purge
-- unnecessarily complicated
-- * LUA field "canonicalUrl" or "fullUrl" on "mw.uri" or "title object"
-- complicated and dubious
-- * manually
-- where to take project URL from ?? plus routine would land in [I] then
-- <span class="plainlinks">...</span>
local function lfwbrew3url (arxinp4, strwikipage, strhttpparam, strvisible, boozordinary)
local strourresult = ''
if (strhttpparam~='') then
strwikipage = strwikipage .. '|' .. strhttpparam
end--if
strourresult = arxinp4:preprocess ('{{canonicalurl:' .. strwikipage .. '}}')
if (strvisible=='') then
strourresult = '[' .. strourresult .. ' ' .. strourresult .. ']'
else
strourresult = '[' .. strourresult .. ' ' .. strvisible .. ']'
end--if
if (boozordinary) then
strourresult = '<span class="plainlinks">' .. strourresult .. '</span>'
end--if
return strourresult
end--function lfwbrew3url
------------------------------------------------------------------------
-- Local function LFWEATREFERENCES
-- Input : * arxinp5
-- * strgroupname -- digit "1" for default group
local function lfweatreferences (arxinp5, strgroupname)
local strzxcvbn = '<br><b>References '
if (strgroupname=='1') then
strzxcvbn = strzxcvbn .. 'main group'
else
strzxcvbn = strzxcvbn .. 'group "' .. strgroupname .. '"'
end--if
strzxcvbn = strzxcvbn .. ' :</b>'
if (strgroupname=='1') then
strzxcvbn = strzxcvbn .. arxinp5:extensionTag('references')
else
strzxcvbn = strzxcvbn .. arxinp5:extensionTag('references','',{group=strgroupname})
end--if
return strzxcvbn
end--function lfweatreferences
------------------------------------------------------------------------
-- Local function LFWIFEXISIM !!!FIXME!!! use the tightfisted one
-- Simple check whether a wiki page exists. The caller must use "pcall". Here
-- we can crash on the spot if we violate the limit of 500 expensive requests.
-- Input : * strpgnamsi -- fullpagename (default NS 0, not template NS 10)
-- Output : * boomemangada -- "true" on success
local function lfwifexisim (strpgnamsi)
local boomemangada = false
local metaa = 0
metaa = mw.title.new (strpgnamsi) -- 1 param
boomemangada = metaa.exists -- expensive here
return boomemangada
end--function lfwifexisim
------------------------------------------------------------------------
---- VERY HIGH LEVEL FUNCTIONS [Y] ----
------------------------------------------------------------------------
-- Local function LFYSPLITKAT
-- Split wikitext into two parts, namely cat insertions vs originally
-- visible remainder, format those cat insertions into a list, and
-- maybe brew an extra part too.
-- Input : * strwikitextin
-- * tabparsmap -- nested: [0] findings | [1] main map |
-- [2] boundary map -- MUST MATCH THE STRING !!!
-- * boonohynts
-- * boobypass -- allow bypassing "hlt=1"
-- Output : * tabsplout -- 7 elements [0] str | [1] str | [2] str
-- [3] num err | [4] num | [5] num dupes | [6] bypass
-- Depends on functions :
-- [W] lfwsplit3title
-- [H] lfhtabletohtmllista
-- [I] lfikatpaldigu lfigetleftright
-- Depends on constants :
-- * 3 strings (plain text) "constrca3d" "constrca4d" "constrca5d"
-- This is our holy core ;-)
-- We take one string and produce 2 strings, one of them for the cat
-- insertions, and the other one for the remaining ie originally visible
-- content. We walk forwards through string "strwikitextin" char after char
-- from begin of string to the end and take care of all "[[" (maybe a cat
-- insertion that needs to be cut out) and of "<pre>" (#A22, needs special
-- encoding of the affected area). All found cat insertions (except dupes
-- ie same name) are placed into two temporary tables (name and hint) and
-- skipped (also dupes, including both [[ and ]]) from copying as the main
-- visible content. Subsequently we walk through that table and postprocess
-- all those cat insertions. Finally we format them with help of
-- "lfhtabletohtmllista" into "strkattfinal".
-- A template can produce same cat insertion multiple times. This is not
-- optimal but possible. Even worse, the repetitive cat insertions may vary in
-- the sorting hint, or syntax details such as translated vs non-translated,
-- letter case or extra spaces. We grant a dupe if the names are identical,
-- irrespective of ns prefixes and hints. A target template producing
-- differing dupes would be highly dubious.
-- Visible wikilinks on level 2 are tolerated:
-- [[File:Shoplifting.PNG|thumb|a [[shoplifter]] in [[action]]]]
-- Cat insertions on level 2 are not, they give #S24:
-- [[File:Shoplifting.PNG|thumb|a shoplifter in action [[Category:Crime]]]]
-- We must also defend (with same #S24 on violation) against ordinary
-- wikilink inside a cat insertion:
-- [[Category:Crime|I [[be|am]] criminal]]
-- On a level 1...9 we skip from copying and collect instead into 2
-- destinations parallelly, namely "tabcollectlevel" separated by levels,
-- and into "strflatcoll" in a flat manner. At every "[[" the level is
-- increased (done by previous mapping, above 9 impossible). At level ONE
-- we empty "strflatcoll" and assign "boowasnested" to false. At every
-- level 2...9 we set "boowasnested" to true. It remains true when we
-- later drop back to level ONE. At every "]]" we close a level and
-- check title from "tabcollectlevel" invoking "lfwsplit3title" caring
-- about possible ":" whether it's a cat insertion assigning "boocathere".
-- A cat on level different from ONE gives immediate abort with #S24. When
-- closing level ONE going back to ZERO and
-- cat and "boowasnested" true then we abort with #S24, else ("boowasnested"
-- false) we try to store the cat, note that "tabcollectlevel[1]" and
-- "strflatcoll" had same content in that situation (sinking from ONE
-- to ZERO, cat here, and "boowasnested" false). If no cat then we dump
-- the accumulated text inside [[ ]] into "strmainout" instead.
-- The upper loop uses 4 tables, 3 of them are parallel and limited
-- to 12 cat:s (names, hints, bypass flags). A bypassed cat must look like:
-- <span title="bypass-pate">[[Kategori:Tracking-ubx-text-too-long]]</span>
-- Only if parameter "boobypass" requests it, we check for bypassed cat:s.
-- Only if bypass and not dupe, we count it in "booisbypas".
-- Up to 4 such are added into "strallbypass" standardized with possible hint. !!!FIXME!!! imp incomplete
-- Sorting hints are displayed after the categories. For
-- example "[[Category:Crap|tujuh]]" gives visible text
-- "Category:<br>Crap| (<small>tujuh</small>)" where the visible wall must
-- be encoded (there is one more wall before that is NOT encoded). Spaces
-- in the hint are converted to underscores "_". The brackets make !!!FIXME!!! underscores and why this ??
-- hints with spaces (like "[[Category:Crap| tujuh]]") more visible.
-- The cat insertions are formatted here (empty result impossible), whereas
-- the remaining ie originally visible content is raw (empty result possible).
local function lfysplitkat (strwikitextin, tabparsmap, boonohynts, boobypass)
local tabcollectlevel = {} -- for upper loop, collect all wikilinks [[]]
local tabnodupect = {} -- for upper loop, all cat names stored
local tabtmpcatnm = {} -- for upper & lower loop, max 12 cat:s
local tabtmpcathi = {} -- for upper & lower loop, max 12 cat:s
local tabtmpcatby = {} -- for upper & lower loop, only "true", max 12 cat:s
local tabsplout = {} -- 3 strings plus 4 integers inside, our final result
local strkattfinal = '' -- for lower loop, all cat:s formatted -- for caller
local strmainout = '' -- for upper loop, never reset -- for caller
local strallbypass = '' -- for caller
local strmy4left = '' -- for upper loop, split on wall "|"
local strmy4rajt = '' -- for upper loop, split on wall "|"
local strflatcoll = '' -- for upper loop, single cat, regularly reset
local strwancxar = '' -- for upper loop
local strtitfrom3sub = '' -- for upper loop, unfull title
local strnstfrom3sub = '' -- for upper loop, nstext
local strtajtl = '' -- for lower loop
local strhiint = '' -- for lower loop
local strvisible = '' -- for lower loop
local numsperrorko = 0 -- split status / error code -- for caller
local numkcount = 0 -- found cat:s excl dupes, count all -- for caller
local numdupes = 0 -- number of dupes -- for caller
local numbypass = 0 -- number of bypasses -- for caller
local numwallstatus = 0 -- for upper loop, split on wall "|"
local numnsfrom3sub = 0 -- for upper loop
local numstrilen = 0 -- for upper loop
local numchariix = 0 -- for upper loop, current
local numtypearr = 0 -- for upper loop, current
local numbounbb = 0 -- for upper loop, 1 for "B"
local numbounee = 0 -- for upper loop, 2 for "E"
local numreadonepos = 1 -- for upper loop -- ONE-based
local numcnntcat = 0 -- for lower loop
local booisbypass = false -- for upper loop
local booinsidewili = false -- for upper loop
local boowasnested = false -- for upper loop
local boocathere = false -- for upper loop
local booskiptwo = false -- for upper loop
numstrilen = string.len (strwikitextin)
if (tabparsmap[0][6] or tabparsmap[0][9] or tabparsmap[0][12] or tabparsmap[0][22]) then
numsperrorko = 20 -- #S20 split NOT attempted due to other #M06 #M09 ...
end--if
if (tabparsmap[0][1] or tabparsmap[0][2] or tabparsmap[0][3] or (tabparsmap[0][20]>2)) then
numsperrorko = 21 -- #S21 split NOT attempted due to nesting #M01 #M02 #M03 #M20>2
end--if
while true do -- upper genuine loop -- index is "numreadonepos"
if ((numreadonepos>numstrilen) or (numsperrorko>=20)) then
break -- no further hits possible or already f**ked
end--if
booskiptwo = false -- preASSume again for every iteration
numbounee = 0 -- preASSume, worx even for "]]" at end of text
numchariix = string.byte(strwikitextin,numreadonepos,numreadonepos)
numtypearr = tabparsmap[1][numreadonepos] -- current type
numbounbb = tabparsmap[2][numreadonepos] -- maybe "B" from current
if (numreadonepos<numstrilen) then
numbounee = tabparsmap[2][numreadonepos+1] -- maybe "E" on next
end--if
if (booinsidewili and (numbounee==2)) then -- "]]"
numwallstatus, strmy4left, strmy4rajt = lfigetleftright (tabcollectlevel[numtypearr])
tabcollectlevel[numtypearr] = nil -- kick after use
if (numwallstatus==77) then
numsperrorko = 3 -- #S03 wall + empty right, accept with complaint
end--if
if ((numwallstatus==75) or (numwallstatus==76)) then
numsperrorko = 23 -- #S23 all empty or empty left, give up
break
end--if
if (numwallstatus==79) then
numsperrorko = 2 -- #S02 junk spaces, accept with complaint
end--if
numnsfrom3sub, strtitfrom3sub, strnstfrom3sub = lfwsplit3title (strmy4left)
if (numnsfrom3sub>1024) then
numsperrorko = 25 -- invalid title (empty "[[Category:]]" etc) #S25
break -- give up
end--if
boocathere = ((numnsfrom3sub==14) and (string.byte(strmy4left,1,1)~=58))
if (boocathere and (numtypearr~=1)) then
numsperrorko = 24 -- #S24 cat insertion on level different from ONE
break -- give up
end--if
if (numtypearr==1) then -- down from ONE to ZERO here
if (boocathere) then
if (boowasnested) then
numsperrorko = 24 -- #S24 link inside cat insertion is bad too
break -- give up
else
if (tabnodupect[strtitfrom3sub]) then
numdupes = numdupes + 1 -- already in
else
tabnodupect[strtitfrom3sub] = true -- store it
if (numkcount<=11) then
tabtmpcatnm [numkcount] = strtitfrom3sub -- table ZERO-based
tabtmpcathi [numkcount] = strmy4rajt -- table ZERO-based
end--if
numkcount = numkcount + 1 -- ZERO-based for return & table, NOT loop
end--if (tabnodupect[strtitfrom3sub]) then
end--if (boowasnested) else
else
strmainout = strmainout .. '[[' .. strflatcoll .. ']]' -- dump all the skipped stuff
end--if (boocathere) else
strflatcoll = '' -- decommission after use
booinsidewili = false -- copy char:s into "strmainout" again
end--if (numtypearr==1) then
booskiptwo = true
end--if
if ((numbounbb==1) and (numtypearr<=9)) then -- "[["
if (numtypearr==1) then
booinsidewili = true -- do NOT copy char:s into "strmainout" for now
boowasnested = false -- will get true on level 2, false only at ZERO
strflatcoll = '' -- reset now and begin collecting here, incl "[["
else
boowasnested = true
end--if
tabcollectlevel[numtypearr] = '' -- reset on every level
booskiptwo = true
end--if
if (booskiptwo) then
numreadonepos = numreadonepos + 2 -- nothing copied
else
if ((numtypearr==22) and ((numchariix==38) or (numchariix==91) or (numchariix==93))) then
strwancxar = "&#" .. tostring (numchariix) .. ";" -- dec-encode #A22
else
strwancxar = string.char(numchariix) -- pass
end--if
if (booinsidewili) then
strflatcoll = strflatcoll .. strwancxar -- only unencoded possible
tabcollectlevel[numtypearr] = tabcollectlevel[numtypearr] .. strwancxar
else
strmainout = strmainout .. strwancxar -- html-dec-encoded for <pre> only
end--if
numreadonepos = numreadonepos + 1
end--if (booskiptwo) else
end--while -- upper genuine loop
numcnntcat = 0 -- counts up
strkattprefix = mw.site.namespaces[14].name -- "Kategori:" on a sv wiki
while true do -- lower genuine loop over collected cat:s -- postprocess them
if (numsperrorko>=20) then
break -- #S20
end--if
strtajtl = tabtmpcatnm [numcnntcat] -- table is ZERO-based
strhiint = tabtmpcathi [numcnntcat] -- table is ZERO-based
if (type(strtajtl)~='string') then
break -- done
end--if
strvisible = strkattprefix .. ':<br>' .. strtajtl
if (strhiint~='') then
strvisible = strvisible .. ' | (<small>' .. strhiint .. '</small>)'
end--if
tabtmpcatnm [numcnntcat] = lfikatpaldigu (strkattprefix, strtajtl, strvisible, 2) -- table is ZERO-based
numcnntcat = numcnntcat + 1
end--while -- lower genuine loop
if (numsperrorko>=20) then
strmainout = '' -- #S20 FATAL, delete possible partial result
numkcount = 0 -- here too
else
if (numkcount==0) then
strkattfinal = constrca3d -- no cat:s -- this MUST NOT be left empty
else
strkattfinal = lfhtabletohtmllista(tabtmpcatnm,true)
end--if
if (numkcount>=2) then -- no extra boast for ONE
strkattfinal = '<small>' .. constrca4d .. ' ' .. tostring (numkcount) .. ' ' .. constrca5d .. ' :<br></small>' .. strkattfinal
end--if
end--if
tabsplout[0] = strkattfinal -- catlist (cannot be empty unless we are FATAL)
tabsplout[1] = strmainout -- main/noncat (can be empty)
tabsplout[2] = strallbypass -- [[Category:Track-CO2]][[Category:Track-KCN]]
tabsplout[3] = numsperrorko -- split status / error code
tabsplout[4] = numkcount -- number of cat insertions
tabsplout[5] = numdupes -- number of dupes
tabsplout[6] = numbypass
return tabsplout
end--function lfysplitkat
------------------------------------------------------------------------
---- VARIABLES [R] ----
------------------------------------------------------------------------
function exporttable.ek (arxframent)
-- special type "args" AKA "arx"
local arxsomons = 0 -- metaized "args" from our own or caller's "frame"
-- tab
local tabinparmap = {} -- mapping of incoming target parameter, nested
local tabutparmap = {} -- mapping of output from expansion, nested
local tabkolom = {} -- [0]...[5] from "sel=" still dupe of individual
-- str from parameters
local strmainanon = '' -- incoming, later [[ ]] removed
local strsel = '' -- 7 char:s ctl string
local strtit = '' -- title chain to replace values in "contabcolumns"
local strwar = ''
local strmod = '' -- name of function, "1" prohibited
local strrem = ''
local strref = ''
local strreg = ''
-- after split into two for two purposes
local strbigexpander = '' -- for "arxframent:preprocess"
local strcallforshow = '' -- for showing in column "call"
-- str from expansion and split
local strzzfullrs = '' -- full result of expansion before split
local strzzcatlst = '' -- catlist part after split
local strzznoncat = '' -- noncat part after split
local strzzbypass = '' -- bypass part raw chained cat insertions or empty
-- str misc
local strtmplnwp = '' -- target, always with prefix unless "zer=1"
local strfullono = '' -- fullpagename from MediaWiki
local strvorurefojn = '' -- from "strref" & "strreg" with some text & HTML
local strtymp = ''
local strvisgud = '' -- visible good output
local strviserr = '' -- visible error message
local strret = '' -- final result string
-- num from parameters
local numspec = 0 -- ZERO not special | 7 ":top" | 8 res | 9 ":end"
local numxcolumns = 0 -- number of columns requested (1...6, ZERO invalid)
local numtabtype = 0 -- from "tab=" 0...5
local numborwidt = 0 -- from "bor=" 5...80 ("0.05em"..."0.80em")
-- num from anon param
local numwhitebeg = 0 -- 10 or 32 for whitespace at begin after {{
local numwhiteend = 0 -- 10 or 32 for whitespace at end before }}
-- num from expansion and split
local numpexpasta = 0 -- expand sta (0 no att | 70 OK ...)
local numzfullrs = 0 -- len of full result of expansion before split
local numzsplitsta = 20 -- preASSume split status #S20 (ZERO 2...6 20...40)
local numzjumlahkt = 0 -- number of categories (all non-dupes counted)
local numzjumlahdp = 0 -- number of dupes
local numznoncat = 0 -- len of noncat part after split
-- num status
local numerr = 0 -- ZERO OK | 1 ?? | 2 anon | 3 adv anon | 4 "sel="
-- boo from "sel="
local boocall = false -- column "call"
local boosmall = false -- small text, from "2" in "sel=" colu "call"
local booparsed = false -- column "parsed"
local boorem = false -- column "rem" (see also "strrem")
local boocat = false -- column "cat"
local boonohints = false -- omit hints, from "2" in "sel=" colu "cat" !!!FIXME!!!
local booback = false -- column "back"
local boodebug = false -- column "debug"
local booyescolour = false -- have "2" in the digit for "debug"
local boomapinstead = false -- have "3" in the digit for "debug"
-- boo from single parameters
local boozer = false -- have "zer=1"
local boo3nsm12 = false -- have "nsm=1" or "nsm=2" and process {({ })}
local boo3nsm2m = false -- have "nsm=2"
local bootag = false -- have "tag=1"
local boohlt = false -- have "hlt=1"
local booncf = false -- have "ncf=1"
-- boo subsequent from parameters
local bootitrow = false -- title row only for ":top" & table type 3
local boousetit = false -- titles only for ":top" & table types 3 & 5
local boodoexpand = false -- request from "parsed" or "cat" or "debug"
-- boo misc
local boosamepage = false -- keep false for special mode "numspec" too
------------------------------------------------------------------------
---- MAIN [Z] ----
------------------------------------------------------------------------
---- GUARD AGAINST INTERNAL ERROR AGAIN ----
if (qbooguard) then
numerr = 1 -- #E01 internal
end--if
---- PROCESS MESSAGES, FILL IN NEVER, SURR ONLY IF NEEDED ----
if (numerr==0) then
contaberaroj = lfhfillsurrstrtab (contaberaroj, constrkoll, constrpriv)
contabxxplain = lfhfillsurrstrtab (contabxxplain, constrkoll, constrpriv)
constrbalik = lfhfillsurrstrtab (constrbalik, nil, constrpriv)
constrredir = lfhfillsurrstrtab (constrredir, nil, constrpriv)
end--if
---- GET THE ARX (ONE OF TWO) ----
-- must be seized independently on "numerr" even if we already suck
-- give a f**k in possible params other than "caller=true"
arxsomons = arxframent.args -- "args" from our own "frame"
if (type(arxsomons)~='table') then
arxsomons = {} -- guard against indexing error from our own
numerr = 1 -- #E01 internal
end--if
if (arxsomons['caller']=='true') then
arxsomons = arxframent:getParent().args -- "args" from caller's "frame"
end--if
if (type(arxsomons)~='table') then
arxsomons = {} -- guard against indexing error again
numerr = 1 -- #E01 internal
end--if
---- WHINE IF YOU MUST #E01 ----
-- reporting of this error #E01 must NOT depend on
-- uncommentable stuff such as "constrkoll" and "contaberaroj"
-- do NOT use sub "lfhbrewerror", report our name (NOT of template), in EN
if (numerr==1) then -- !!!FIXME!!! seizing pagename below
strtymp = '#E01 Internal error in module "pate".'
strviserr = constrlaxhu .. constrelabg .. strtymp .. constrelaen .. constrlaxhu
end--if
---- SEIZE TWO UNDESIRABLE NAMED PARAMETERS ----
if (type(arxsomons['trackingcategorieshiglow'])=='string') then
numerr = 43 -- #E43 NOT appreciated like this (use "hlt=1")
end--if
if (type(arxsomons['nocat'])=='string') then
numerr = 44 -- #E44 NOT appreciated like this (use "ncf=1") or avoid
end--if
---- SEIZE ONE ANONYMOUS AND OBLIGATORY PARAMETER ----
-- ":top" or ":end" or raw (no wall) or protected (at least one wall)
-- #E03 param absent or wrong length
-- #E04 more advanced faults (namely [[ | ]] [ ] see section below)
-- assign "numspec" to 0,7,(8),9
-- assign "strmainanon" (preliminary content, see below)
strmainanon = '' -- preASSume guilt
if (numerr==0) then
do -- scope
local vartutpum = 0
local numlunng = 0
vartutpum = arxsomons[1] -- required
if (type(vartutpum)=='string') then
numlunng = string.len (vartutpum)
if ((numlunng>0) and (numlunng<10001)) then
strmainanon = lfgtrimwhite (vartutpum) -- wiki does NOT strip anon
end--if
end--if
end--do scope
end--if (numerr==0) then
if ((numerr==0) and (strmainanon=='')) then
numerr = 3 -- #E03
end--if
if (numerr==0) then
if (strmainanon==':top') then
numspec = 7 -- top with title row
strmainanon = '' -- now dead
end--if
if (strmainanon==':end') then
numspec = 9 -- end
strmainanon = '' -- now dead
end--if
end--if (numerr==0) then
---- SEIZE UP TO 14 NAMED PARAMETERS ----
-- tab= (*), sel=, tit=, war=, bor=
-- mod= (*), zer= (*), nsm= (*), tag= (*), rem= (*)
-- ref= (*), reg= (*), hlt= (*), ncf= (*)
-- * 7 give string, two of them "strsel" "strtit" pluprocessed
-- later, one of them "tit=" additionally gives boolean
-- * 2 give integer ("tab=" and "bor=")
-- * 1 is tristate and gives 2 booleans ("nsm=")
-- * 4 are boolean and give boolean ("zer=1" "tag=1" "hlt=1" "ncf=1")
-- those marked with (*) are prohibited for ":top"
-- all are prohibited for ":end"
-- this must follow the seizure of the anonymous parameter due to
-- "numspec" that we query here, and this must precede pluprocessing
-- of the anonymous parameter (call string) due to "zer=1"
if (numerr==0) then
do -- scope
local var38pom = 0
local var38valu = 0
local num38stat = 0
local numluung = 0 -- !!!FIXME!!! remove
numtabtype = 2 -- preASSume default
var38pom = arxsomons['tab'] -- 1 digit, can be "0"..."5", default is "2"
num38stat, var38valu = lfichkparam (var38pom, 1, 0, 5)
if (num38stat==1) then
numerr = 8 -- #E08 "tab=" bad
end--if
if (num38stat==2) then
while true do -- fake loop
if (numspec==9) then
numerr = 6 -- #E06 no named param legal for ":end"
break
end--if
if (numspec~=0) then
numerr = 7 -- #E07 "tab=" prohi for ":top"
break
end--if
numtabtype = var38valu
break -- finally to join mark
end--while -- fake loop -- join mark
end--if
var38pom = arxsomons['sel'] -- 6 + 1 control string column control
num38stat, var38valu = lfichkparam (var38pom, 0, 7, 7)
if (num38stat==1) then
numerr = 21 -- #E21 "sel=" bad -- more checks below
end--if
if (num38stat==2) then
while true do -- fake loop
if (numspec==9) then
numerr = 6 -- #E06 no named param legal for ":end"
break
end--if
strsel = var38valu -- there are 2 defaults, bother about them later
break -- finally to join mark
end--while -- fake loop -- join mark
end--if
var38pom = arxsomons['tit'] -- length 1...200 and 1...6 title strings
num38stat, var38valu = lfichkparam (var38pom, 0, 1, 200)
if (num38stat==1) then
numerr = 23 -- #E23 "tit=" bad -- more checks below
end--if
if (num38stat==2) then
while true do -- fake loop
if (numspec==9) then
numerr = 6 -- #E06 no named param legal for ":end"
break
end--if
if (lfipillegal(var38valu,true,false,true,1,true,true,true)) then
numerr = 23 -- #E23 "tit=" bad -- <...> legal [[...]] illegal
break
end--if
strtit = var38valu -- default empty here & more in "contabcolumns"
break -- finally to join mark
end--while -- fake loop -- join mark
end--if
strwar = '60A0A0' -- preASSume default bluegreen
var38pom = arxsomons['war'] -- table line color, always 6 hex digits
num38stat, var38valu = lfichkparam (var38pom, 6, 0, 0)
if (num38stat==1) then
numerr = 25 -- #E25 "war=" bad
end--if
if (num38stat==2) then
while true do -- fake loop
if (numspec==9) then
numerr = 6 -- #E06 no named param legal for ":end"
break
end--if
strwar = var38valu -- strictly validated now
break -- finally to join mark
end--while -- fake loop -- join mark
end--if
numborwidt = 20 -- preASSume default "0.20em"
var38pom = arxsomons['bor'] -- TWO digits, legal range "05" ... "80"
num38stat, var38valu = lfichkparam (var38pom, 2, 5, 80)
if (num38stat==1) then
numerr = 26 -- #E26 "bor=" bad
end--if
if (num38stat==2) then
while true do -- fake loop
if (numspec==9) then
numerr = 6 -- #E06 no named param legal for ":end"
break
end--if
numborwidt = var38valu
break -- finally to join mark
end--while -- fake loop -- join mark
end--if
var38pom = arxsomons['mod'] -- name of LUA function
num38stat, var38valu = lfichkparam (var38pom, 0, 1, 60)
if (num38stat==1) then
numerr = 28 -- #E28 "mod=" bad
end--if
if (num38stat==2) then
while true do -- fake loop
if (numspec==9) then
numerr = 6 -- #E06 no named param legal for ":end"
break
end--if
if (numspec~=0) then
numerr = 7 -- #E07 "mod=" prohi for ":top"
break
end--if
if (var38valu=='1') then -- this is a string, NOT number
numerr = 28 -- #E28 "mod=" bad, need name of function, not "1"
break
end--if
strmod = var38valu
break -- finally to join mark
end--while -- fake loop -- join mark
end--if
var38pom = arxsomons['zer'] -- 1 digit, boolean
num38stat, var38valu = lfichkparam (var38pom, 1, 0, 1)
if (num38stat==1) then
numerr = 29 -- #E29 "zer=" bad
end--if
if (num38stat==2) then
while true do -- fake loop
if (numspec==9) then
numerr = 6 -- #E06 no named param legal for ":end"
break
end--if
if (numspec~=0) then
numerr = 7 -- #E07 "zer=" prohi for ":top"
break
end--if
boozer = (var38valu==1)
break -- finally to join mark
end--while -- fake loop -- join mark
end--if
var38pom = arxsomons['nsm'] -- 1 digit, tristate
num38stat, var38valu = lfichkparam (var38pom, 1, 0, 2)
if (num38stat==1) then
numerr = 31 -- #E31 "nsm=" bad
end--if
if (num38stat==2) then
while true do -- fake loop
if (numspec==9) then
numerr = 6 -- #E06 no named param legal for ":end"
break
end--if
if (numspec~=0) then
numerr = 7 -- #E07 "nsm=" prohi for ":top"
break
end--if
boo3nsm2m = (var38valu==2)
boo3nsm12 = boo3nsm2m or (var38valu==1)
break -- finally to join mark
end--while -- fake loop -- join mark
end--if
var38pom = arxsomons['tag'] -- 1 digit, boolean
num38stat, var38valu = lfichkparam (var38pom, 1, 0, 1)
if (num38stat==1) then
numerr = 32 -- #E32 "tag=" bad
end--if
if (num38stat==2) then
while true do -- fake loop
if (numspec==9) then
numerr = 6 -- #E06 no named param legal for ":end"
break
end--if
if (numspec~=0) then
numerr = 7 -- #E07 "tag=" prohi for ":top"
break
end--if
bootag = (var38valu==1)
break -- finally to join mark
end--while -- fake loop -- join mark
end--if
strrem = constrempt -- preASSume placeholder
var38pom = arxsomons['rem'] -- length 1...1000, prohibited for special
num38stat, var38valu = lfichkparam (var38pom, 0, 1, 1000)
if (num38stat==1) then
numerr = 34 -- #E34 "rem=" bad -- more checks below
end--if
if (num38stat==2) then
while true do -- fake loop
if (numspec==9) then
numerr = 6 -- #E06 no named param legal for ":end"
break
end--if
if (numspec~=0) then
numerr = 7 -- #E07 "rem=" prohi for ":top"
break
end--if
if (lfipillegal(var38valu,true,false,true,0,true,true,true)) then
numerr = 34 -- #E34 "rem=" bad -- <...> legal [[...]] legal
break
end--if
strrem = var38valu -- default see above
break -- finally to join mark
end--while -- fake loop -- join mark
end--if
var38pom = arxsomons["ref"] -- length 1...20, prohibited for special !!!FIXME!!!
if (type(var38pom)=='string') then
numluung = string.len (var38pom)
if ((numluung>=1) and (numluung<=20) and (numspec==0)) then
strref = var38pom
else
numerr = 7 -- #E07 "ref=" prohi for ":top"
numerr = 35 -- #E35 "ref=" bad
end--if
end--if
var38pom = arxsomons["reg"] -- length 1...20, prohibited for special !!!FIXME!!!
if (type(var38pom)=='string') then
numluung = string.len (var38pom)
if ((numluung>=1) and (numluung<=20) and (numspec==0) and (strref~='') and (var38pom~=strref)) then
strreg = var38pom
else
numerr = 7 -- #E07 "reg=" prohi for ":top"
numerr = 35 -- #E35 "reg=" bad
end--if
end--if
var38pom = arxsomons["hlt"] -- length 1 only, prohibited for special !!!FIXME!!!
if (type(var38pom)=='string') then
if ((string.len(var38pom)==1) and (numspec==0)) then -- boolean
boohlt = (var38pom=="1")
else
numerr = 7 -- #E07 "hlt=" prohi for ":top"
numerr = 36 -- #E36 "hlt=" bad
end--if
end--if
var38pom = arxsomons['ncf'] -- 1 digit, boolean
num38stat, var38valu = lfichkparam (var38pom, 1, 0, 1)
if (num38stat==1) then
numerr = 37 -- #E37 "ncf=" bad
end--if
if (num38stat==2) then
while true do -- fake loop
if (numspec==9) then
numerr = 6 -- #E06 no named param legal for ":end"
break
end--if
if (numspec~=0) then
numerr = 7 -- #E07 "ncf=" prohi for ":top"
break
end--if
booncf = (var38valu==1)
break -- finally to join mark
end--while -- fake loop -- join mark
end--if
end--do scope
end--if (numerr==0) then
---- PICK ONE OF 2 DEFAULTS ----
-- this must follow seizure of anon (-> "numspec") and
-- named ("numtabtype", "strsel")
-- do this for special work ":top" too
if ((numerr==0) and (numspec~=9) and (strsel=='')) then
if (numtabtype==0) then
strsel = '010-000' -- show only parsed result
else
strsel = '111-110' -- show all except debug
end--if
end--if
---- PLUPROCESS CONTROL STRING TO 6 BOOLEANS ----
-- this must follow assigning default value to "sel="
-- do this for special work ":top" (numspec=7) too
-- assign 6 + 4 booleans as well as tabkolom
-- assign "numxcolumns" to 1...6 (ZERO is illegal)
-- assign "boodoexpand"
if ((numerr==0) and (numspec~=9)) then
do -- scope
local numsilur = 0
while true do -- fake loop
if (numspec==0) then
numsilur = lfivaliumdctlstr ('211-213',strsel) -- tri and four legal
else
numsilur = lfivaliumdctlstr ('111-111',strsel) -- only binary legal
end--if
if (numsilur~=255) then
break -- less than 255 is bad above, 777 would be good below
end--if
numsilur = string.byte (strsel,1,1) -- tristate "call"
boocall = (numsilur~=48)
boosmall = (numsilur==50)
tabkolom[0] = boocall
numxcolumns = numxcolumns + contabboo2int[boocall]
numsilur = string.byte (strsel,2,2)
booparsed = (numsilur==49)
tabkolom[1] = booparsed
numxcolumns = numxcolumns + contabboo2int[booparsed]
numsilur = string.byte (strsel,3,3)
boorem = (numsilur==49)
tabkolom[2] = boorem
numxcolumns = numxcolumns + contabboo2int[boorem]
numsilur = string.byte (strsel,5,5) -- tristate "cat"
boocat = (numsilur~=48)
boonohints = (numsilur==50)
tabkolom[3] = boocat
numxcolumns = numxcolumns + contabboo2int[boocat]
numsilur = string.byte (strsel,6,6)
booback = (numsilur==49)
tabkolom[4] = booback
numxcolumns = numxcolumns + contabboo2int[booback]
numsilur = string.byte (strsel,7,7) -- fourstate "debug"
boodebug = (numsilur~=48)
booyescolour = (numsilur==50) -- not useful for ":top"
boomapinstead = (numsilur==51) -- not useful for ":top"
tabkolom[5] = boodebug
numxcolumns = numxcolumns + contabboo2int[boodebug]
if (numxcolumns==0) then -- empty table not legal
break -- 777 would be good below, 48 or 49 is bad too
end--if
boodoexpand = booparsed or boocat or boodebug
numsilur = 777 -- magic for "all OK"
break -- finally to join mark
end--while -- fake loop -- join mark
if (numsilur~=777) then
numerr = 21 -- #E21 "sel=" bad
end--if
end--do scope
end--if ((numerr==0) and (numspec~=9)) then
---- CATCH SOME TOXIC MIXTURES ----
if ((numerr==0) and (numxcolumns>=2) and (numtabtype==0)) then
numerr = 40 -- #E40 "sel=" conflicts with "tab="
end--if
if ((numerr==0) and (strmod~='') and boozer) then
numerr = 41 -- #E41 "mod=" and "zer=1" must NOT be used together
end--if
---- MINIMALLY PLUPROCESS THE HOLY CALL STRING FOR RAW MODE ----
-- minimal content is "[[{({a})}]]" (call) or "[[a]]" (no call,
-- degenerated but valid)
if ((numerr==0) and (numspec==0) and boo3nsm2m) then -- "nsm=2"
while true do -- fake loop
if (string.len(strmainanon)<5) then
numerr = 4 -- #E04
break -- to join mark
end--if
if ((string.sub(strmainanon,1,2)~='[[') or (string.sub(strmainanon,-2,-1)~=']]')) then
numerr = 4 -- #E04
break -- to join mark
end--if
strmainanon = lfgtrimwhite(string.sub(strmainanon,3,-3)) -- strip [[ ]] + trim white
break -- finally to join mark
end--while -- fake loop -- join mark
end--if
---- PLUPROCESS THE HOLY CALL STRING FOR SINGLE TARGET ----
-- separate bare name from complete template call inside
-- unorthodox brackets, and bother with namespace prefixes
-- not needed for "special" mode ":top" & ":end"
-- not needed for the raw mode
-- incoming "strmainanon", length is 1...10'000, we do NOT alter it
-- in any way except strip off [[ ]] and adjacent whitespace if present
-- this depends on "numspec" and "zer=1"
-- to assess the string as complete template call:
-- * 3 discoveries [[ | ]] must be consistently true
-- * length must be over 7 -- minimal content is "[[a|b]]"
-- output:
-- * complete template call "strmainanon" -- possible prefix for ns 10 is
-- not added and not stripped either, other prefix possible, used for
-- both expansion and display
-- * prefixed name "strtmplnwp" -- always has a ns prefix (unless "zer=1")
-- order of work:
-- * do some checks on "strmainanon" and assign scoped
-- "boohavparip", risk of #E04
-- * if param then strip off [[ ]] + ws from "strmainanon" and do
-- more checks, split off parameter chain + ws, result is
-- "strcommon", risk of #E04
-- * else (if no param) no strip no split but perform other checks,
-- "strcommon" copied from "strmainanon", and "strmainanon"
-- unchanged, risk of #E04
-- * check whether the title is safe, risk of #E05
-- * split off ns prefix and assign "strtmplnwp" re-adding it
-- for both expansion and display we will later possibly add ":" and
-- always add {{ }} , but there are some intermediate steps for expansion
-- thus we MUST NOT do it here, and before that we will fix nesting for both
if ((numerr==0) and (numspec==0) and (not boo3nsm2m)) then
do -- scope
local varfindwall = 0
local strcommon = ''
local strunfu7ll = ''
local strnom7spaco = ''
local numthisleen = 0
local numnonsens = 0
local boohavbigwall = false
local boorectabegin = false
local boorectaakhir = false
local boohavparip = false -- have param inside anon param thus [[ | ]]
while true do -- fake loop
numthisleen = string.len(strmainanon)
numnonsens = string.byte(strmainanon,1,1) -- string cannot be empty
if ((numnonsens==58) or (numnonsens==93) or (numnonsens==123) or (numnonsens==124) or (numnonsens==125)) then
numerr = 4 -- #E04
break -- to join mark -- invalid char at begin :]{|}
end--if
if (strmainanon=='[') then
numerr = 4 -- #E04
break -- to join mark -- invalid one-char name "["
end--if
if (numthisleen>=2) then -- chk consistency
boohavbigwall = (string.find(strmainanon,'|',1,true)~=nil)
boorectabegin = (string.sub(strmainanon,1,2)=='[[')
boorectaakhir = (string.sub(strmainanon,-2,-1)==']]')
if ((boohavbigwall~=boorectabegin) or (boohavbigwall~=boorectaakhir) or (boorectabegin~=boorectaakhir)) then
numerr = 4 -- #E04
break -- to join mark -- inconsistent discoveries
end--if
boohavparip = boohavbigwall
if (boohavparip and (numthisleen<7)) then
numerr = 4 -- #E04
break -- to join mark -- below minimal content "[[a|b]]"
end--if
end--if (numthisleen>=2) then
if (boohavparip) then -- length at least 7 guaranteed
strmainanon = string.sub(strmainanon,3,-3) -- strip [[ ]] no ws yet
numwhitebeg = string.byte(strmainanon,1,1) -- & will later recover
numwhiteend = string.byte(strmainanon,-1,-1) -- & ws to sane degree
strmainanon = lfgtrimwhite(strmainanon) -- !!!CRUCIAL!!! trim white
if (string.len(strmainanon)<3) then
numerr = 4 -- #E04
break -- to join mark -- below minimal content "a|b"
end--if
if ((string.byte(strmainanon,1,1)==124) or (string.byte(strmainanon,-1,-1)==124)) then
numerr = 4 -- #E04
break -- to join mark -- wall misplaced
end--if
varfindwall = string.find(strmainanon,'|',1,true) -- must find it
strcommon = lfgtrimwhite(string.sub(strmainanon,1,(varfindwall-1))) -- isolate name
else
if ((string.find(strmainanon,'[',1,true)) or (string.find(strmainanon,']',1,true))) then
numerr = 4 -- #E04
break -- to join mark -- illegal [ ] in raw template name
end--if
strcommon = strmainanon
end--if (boohavparip) else
if (not lfwistitlesafe (strcommon)) then
numerr = 5 -- #E05 invalid title
break
end--if
numnonsens, strunfu7ll, strnom7spaco = lfwsplit3title (strcommon)
if (numnonsens>200) then
numerr = 5 -- #E05 invalid title
break
end--if
if ((numnonsens~=0) and boozer) then
numerr = 29 -- #E29 bad use of "zer=1"
break
end--if
if ((numnonsens==0) and (not boozer)) then -- add prefix for ns 10
strcommon = mw.site.namespaces[10].name .. ':' .. strcommon
numnonsens, strunfu7ll, strnom7spaco = lfwsplit3title (strcommon)
if (numnonsens==0) then -- hopefully impossible
numerr = 5 -- #E05 invalid title
break
end--if
end--if
if (boozer) then
strtmplnwp = strunfu7ll -- would have prefix but there is none
else
strtmplnwp = strnom7spaco .. ':' .. strunfu7ll -- add prefix
end--if
break -- finally to join mark
end--while -- fake loop -- join mark
end--do scope
end--if ((numerr==0) and (numspec==0) and (not boo3nsm2m)) then
---- SEIZE FULLPAGENAME AND COMPARE ----
-- not needed for "special" mode ":top" & ":end"
-- note that "prefixedText" contains translated ns prefix, thus
-- "strtmplnwp" must use same pattern
-- flag "boosamepage" affects the structure of the "call"
-- cell to avoid self-link
if ((numerr==0) and (numspec==0)) then
strfullono = mw.title.getCurrentTitle().prefixedText
boosamepage = (strfullono==strtmplnwp) -- both are standardized ;-)
end--if
---- PREPARE TITLES ----
-- titles are needed for ":top" (also HTML row) and table
-- type 3 (hor) (also HTML row) and type 5 (ver) (but no HTML row)
-- split "tit=" in "strtit" at "@@" and merge into
-- "qtabmy6columns" using defaults from "contabcolumns"
-- do this for special work ":top" too
if (numerr==0) then
bootitrow = (numspec==7) or (numtabtype==3) -- ":top" or compete hor table
boousetit = bootitrow or (numtabtype==5) -- titles yes but no row for 5
end--if
if (boousetit) then
qtabmy6columns = lfhatmergetab (strtit, tabkolom, contabcolumns) -- "strtit" can be empty
if (qtabmy6columns[9]) then
numerr = 23 -- #E23 "tit=" bad
end--if
end--if
---- SPLIT AND PREPARE FOR EXPANSION AND SHOWING ----
-- * incoming target parameter "strmainanon"
-- * [[ and ]] removed
-- * possible prefix for ns 10 is not added and not stripped
-- either, other prefix possible
-- * also exists prefixed name "strtmplnwp" -- always has
-- a ns prefix (unless "zer=1")
-- * here we maybe restore the ordinary form from
-- * workarounded inner doublebrackets ie "{({"..."})}"
-- * workarounded aggressive tags ("nonewiki", variations of
-- "renef", ...) even if we don't expand
-- for both target call parameter and "rem="
-- * here "strmainanon" is split into "strbigexpander" for
-- "arxframent:preprocess" only, and "strcallforshow", thus
-- "strmainanon" is decommissioned, but "strtmplnwp" is preserved
while true do -- fake loop
if ((numerr~=0) or (numspec~=0)) then
break
end--if
if (boo3nsm12) then
strmainanon = lfirestorefromtriple (strmainanon) -- "nsm=1" or "nsm=2"
strrem = lfirestorefromtriple (strrem)
end--if
if (bootag) then
strmainanon = lfirestorefromnetag (strmainanon) -- "tag=1"
strrem = lfirestorefromnetag (strrem)
end--if
tabinparmap = lfhparsemap (strmainanon) -- BIG MAP HERE !!!FIXME!!! detect {{ }} too ??
if (tabinparmap[0][4] or tabinparmap[0][5]) then
numerr = 46 -- #E46 strip NOT appreciated
break
end--if
numerr, strbigexpander, strcallforshow = lfhsplithidden (strmainanon)
break -- finally to join mark
end--while -- fake loop -- join mark
strmainanon = '' -- & now dead for both success and error
tabinparmap = {} -- &
if ((numerr==0) and (numspec==0) and boodoexpand and (not boo3nsm2m)) then
strcallforshow = lfibrewcurlycall (boozer,strcallforshow,numwhitebeg,numwhiteend) -- maybe ":" SPC LF always {{ }}
strtymp = lfgdeleteallwhite(strbigexpander)
if (string.find(strtymp,'|trackingcategorieshiglow=',1,true)) then
numerr = 43 -- #E43 NOT appreciated
end--if
if (string.find(strtymp,'|nocat=',1,true)) then
numerr = 44 -- #E44 NOT appreciated
end--if
if (numerr==0) then
if (boohlt) then
strbigexpander = strbigexpander .. '|trackingcategorieshiglow=true' -- add after check
end--if
if (booncf) then
strbigexpander = strbigexpander .. '|nocat=false' -- add after check
end--if
strbigexpander = lfibrewcurlycall (boozer,strbigexpander,0,0) -- last step
end--if (numerr==0) then
end--if
---- CHECK WHETHER THE TARGET PAGE (TEMPLATE) EXISTS AT ALL ----
-- here YES "msgnw:" !!!FIXME!!!
if (boodoexpand and (numerr==0) and (numspec==0)) then
if (boo3nsm2m) then
numpexpasta = 1 -- #X01 skip check for "nsm=2"
else
if (lfwifexisim(strtmplnwp)) then
numpexpasta = 1 -- #X01 good so far
else
numpexpasta = 80 -- #X80 target does NOT exist
end--if
end--if
end--if
---- EXPAND THE TEMPLATE AND SPLIT THE OUTPUT IF NEEDED ----
-- here use "arxframent:preprocess" and NO "msgnw:"
-- * the {{-}}-syntax assumes ns 10 if no prefix and no colon
-- * if the split fails and the "debug" column is available then we must NOT
-- brew any FATAL, instead show the full text plus the status code there
-- "strzzfullrs" full result of expansion, len is "numzfullrs"
-- "strzzcatlst" catlist part after split, no len, see "numzjumlahkt"
-- "strzznoncat" noncat part after split, len is "numznoncat"
-- "numzsplitsta" split status (ZERO or 2...6 or 20...40)
-- "numzjumlahkt" number of categories (all non-dupes counted)
-- "numzjumlahdp"
if (numpexpasta==1) then -- expand requested and target exists
do -- scope
local tabrezu3v = {}
strzzfullrs = arxframent:preprocess (strbigexpander)
if ((type(strzzfullrs))=='string') then
numpexpasta = 70 -- preASSume expand success #X70
numzfullrs = string.len(strzzfullrs) -- total bloat
if (numzfullrs==0) then
numpexpasta = 82 -- #X82 empty string
end--if
else
numpexpasta = 81 -- #X81 expand failure in wiki parser
end--if ((type(strzzfullrs))=='string') else
if (numpexpasta==70) then
tabutparmap = lfhparsemap (strzzfullrs) -- BIG MAP HERE
tabrezu3v = lfysplitkat (strzzfullrs, tabutparmap, boonohints, boohlt) -- BIG SPLIT HERE
numzsplitsta = tabrezu3v[3] -- split status
numzjumlahkt = tabrezu3v[4] -- number of cat:s (all non-dupes counted)
numzjumlahdp = tabrezu3v[5] -- dupes
if (numzsplitsta<=6) then -- ZERO OK | 2...6 non-fatal | 20...40 bad
strzzcatlst = tabrezu3v[0] -- cat:s
strzznoncat = tabrezu3v[1] -- main/noncat
strzzbypass = tabrezu3v[2] -- empty string if not used
numznoncat = string.len(strzznoncat) -- len of main/noncat part
end--if
end--if (numpexpasta==70) then
end--do scope
end--if (numpexpasta==1) then
---- ASSIGN ---
-- insert 2 digits then 6 digits, whereas margin is fixed
-- <table style="margin:0.6em;border:0.20em solid #60A0A0;border-collapse:collapse;">
-- <td style="border:0.20em solid #60A0A0;padding:0.5em;text-align:center;">
-- "qstrtdbegin" and "qstrtdendus" used in "lficondicelrow"
qstrtabegin = contabtabeg[0] .. lfnumto2digit(numborwidt) .. contabtabeg[1] .. strwar .. contabtabeg[2]
qstrtdbegin = contabtdbeg[0] .. lfnumto2digit(numborwidt) .. contabtdbeg[1] .. strwar .. contabtdbeg[2]
qstrtdendus = '</td>'
qstrtaendus = '</table>'
---- BOTHER WITH REFERENCES ----
-- "strvorurefojn" is later dumbly attached to "strzznoncat"
-- and the result lands in the "parsed" cell
-- result from "lfweatreferences" has a "<br>" at begin
if ((numerr==0) and (strref~='')) then
strvorurefojn = '<br>' .. lfweatreferences (arxframent, strref)
if (strreg~='') then
strvorurefojn = strvorurefojn .. lfweatreferences (arxframent, strreg)
end--if
end--if
---- BREW TITLE ROW FOR SPECIAL 7 OR TYPE 3 BUT NOT TYPE 5 ----
if ((numerr==0) and bootitrow) then
strtymp = '' -- important to start with empty
if (boocall) then
strtymp = strtymp .. qstrtdbegin .. qtabmy6columns[0] .. qstrtdendus
end--if
if (booparsed) then
strtymp = strtymp .. qstrtdbegin .. qtabmy6columns[1] .. qstrtdendus
end--if
if (boorem) then
strtymp = strtymp .. qstrtdbegin .. qtabmy6columns[2] .. qstrtdendus
end--if
if (boocat) then
strtymp = strtymp .. qstrtdbegin .. qtabmy6columns[3] .. qstrtdendus
end--if
if (booback) then
strtymp = strtymp .. qstrtdbegin .. qtabmy6columns[4] .. qstrtdendus
end--if
if (boodebug) then
strtymp = strtymp .. qstrtdbegin .. qtabmy6columns[5] .. qstrtdendus
end--if
if (numtabtype==3) then
strtymp = strtymp .. '</tr><tr>' -- separate rows now, outer <tr> later
end--if
strvisgud = strtymp
end--if ((numerr==0) and bootitrow) then
---- BREW THE RESULT ORDINARY ----
-- "call", "parsed", "rem", "cat", "back", "debug"
-- 0 raw | 1 bunch of cells | 2 (defa) row | 3 compl hori 1+1 rows
-- 4 compl hori 1 row | 5 compl vert 1...6 rows
-- note that in output from a module {{ }} is NO LONGER processed
-- by wiki parser but [[ ]] still is
if ((numerr==0) and (numspec==0)) then
do -- scope
local strkombo = ''
local strt7mp = ''
local strt8mp = ''
local strrezord = '' -- important to start with empty
local boogoodresult = false
strkombo = lficombostatus (numpexpasta,numzsplitsta) -- empty string on success
boogoodresult = (strkombo=='')
if (boocall) then
strt8mp = lfidecencodbr (strcallforshow,true) -- see "Encoding of text"
if (boosamepage or boo3nsm2m) then
strt7mp = strt8mp -- avoid selflink or broken link from raw wikitext
else
strt7mp = '[[' .. strtmplnwp .. '|' .. strt8mp .. ']]' -- "}}" is visible but "]]" is NOT
end--if
strt7mp = lfipretable (strt7mp,contabboo2siz[boosmall]) -- inner table with font size
strrezord = strrezord .. lficondicelrow (strt7mp,numtabtype,0)
end--if (boocall) then
if (booparsed) then
if (boogoodresult) then
strt7mp = strzznoncat .. strvorurefojn -- both can be empty, no #X82
if (numtabtype~=0) then
strt7mp = lfilefqdivqlefqtxt(string.char(10) .. strt7mp) -- add LF due wiki parser, outside left inside left full width
end--if
else
strt7mp = lfiexplain (strkombo)
end--if
strrezord = strrezord .. lficondicelrow (strt7mp,numtabtype,1)
end--if (booparsed) then
if (boorem) then
strrezord = strrezord .. lficondicelrow (strrem,numtabtype,2)
end--if (boorem) then
if (boocat) then
if (boogoodresult) then
strt7mp = strzzcatlst -- already formatted
else
strt7mp = strkombo -- do NOT explain again, keep code only
end--if
strrezord = strrezord .. lficondicelrow (strt7mp,numtabtype,3)
end--if (boocat) then
if (booback) then
if (boo3nsm2m) then
strt7mp = constrempt -- placeholder for "nsm=2"
else
strt8mp = 'target=' .. mw.uri.encode (strtmplnwp, "WIKI") -- no quest "?" and no and "&" here
strt7mp = lfwbrew3url (arxframent, constrprli, strt8mp, constrbalik, true) .. '<br><br>' -- all
strt8mp = strt8mp .. '&hidetrans=1&hidelinks=1'
strt7mp = strt7mp .. lfwbrew3url (arxframent, constrprli, strt8mp, constrredir, true) -- redirects
strt7mp = '<small>' .. strt7mp .. '</small>'
end--if
strrezord = strrezord .. lficondicelrow (strt7mp,numtabtype,4)
end--if (booback) then
if (boodebug) then
strt7mp = 'Same page: ' .. tostring(boosamepage) .. '<br>' -- always
strt7mp = strt7mp .. 'Expand status: ' .. lfiexpandstatus(numpexpasta) .. '<br>' -- always
if (numpexpasta==70) then
strt7mp = strt7mp .. 'Total out size: ' .. tostring(numzfullrs) .. '<br>' -- only on expand success #X70
strt7mp = strt7mp .. lfhreportfindings (tabutparmap[0]) -- only on expand success #X70
strt7mp = strt7mp .. 'Split status: ' .. lfisplitstatus(numzsplitsta) .. '<br>' -- only on expand success #X70
if (numzsplitsta<20) then
strt7mp = strt7mp .. 'Number of cat insertions: ' .. tostring(numzjumlahkt) .. '<br>' -- only on
strt7mp = strt7mp .. 'Number of cat dupes: ' .. tostring(numzjumlahdp) .. '<br>' -- split success
strt7mp = strt7mp .. 'Decategorized size: ' .. tostring(numznoncat) .. '<br>' -- less than #S20
end--if
if (boomapinstead) then
strt8mp = lfhtablewithmap(strzzfullrs,tabutparmap) -- only on expand success #X70
else
strt8mp = lfiultencode(strzzfullrs,48,booyescolour,false) -- only on expand success #X70
strt8mp = lficenqtabqlefqtxt(strt8mp) -- outsid cent insid left
end--if
strt7mp = strt7mp .. '<br>' .. strt8mp
end--if
strrezord = strrezord .. lficondicelrow (strt7mp,numtabtype,5) -- always
end--if (boodebug) then
strvisgud = strvisgud .. strrezord
end--do scope
end--if ((numerr==0) and (numspec==0)) then
---- FINALIZE ROW OR COMPLETE TABLE IF WE HAVE SUCH ----
-- 0 raw | 1 bunch of cells | 2 (defa) row | 3 compl hori 1+1 rows
-- 4 compl hori 1 row | 5 compl vert 1...6 rows
if (numerr==0) then
if ((numspec==7) or (numtabtype==2) or (numtabtype==3) or (numtabtype==4)) then
strvisgud = '<tr>' .. strvisgud .. '</tr>' -- finalize row
end--if
if ((numspec==0) and (numtabtype>=3)) then
strvisgud = qstrtabegin .. strvisgud .. qstrtaendus -- finalize table
end--if
if (numspec==7) then
strvisgud = qstrtabegin .. strvisgud -- begin table only, have one row
end--if
if (numspec==9) then
strvisgud = qstrtaendus -- terminate table only, no other content
end--if
end--if
---- WHINE IF YOU MUST #E02...#E99 ----
if (numerr>1) then
strviserr = lfhbrewerror(numerr)
end--if
---- RETURN THE JUNK STRING ----
-- on #E02 and higher we risk partial results in "strvisgud"
if (numerr==0) then
strret = strvisgud
else
strret = strviserr
end--if
return strret
end--function
---- RETURN THE JUNK TABLE ----
return exporttable