Modulo:pate
MODULO | ||
Memtesto disponeblas sur la paĝo Ŝablono:pate. |
--[===[
MODULE "PATE" (proxy for analysis of template output)
"id.wikipedia.org/wiki/Modul:Pate" <!--2024-Mar-18-->
"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:
* 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:
* can be one of 4 types:
* bare name of the target template (no walls)
* complete call of the target template protected by
rectangular brackets (at least one wall required)
* more than call, wikitext containing calls to multiple
templates, or one template + something more, only
for "nsm=2", always requires rectangular brackets, inside
them requires "enhanced" curly brackets "{({" ... "})}"
(except for a degenerated case with ZERO template calls)
* special value
* special value ":top" begins the HTML table (incl title row)
* special value ":end" ends the HTML table
* notes:
* 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
* 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
* 15 named and optional parameters:
* 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=" cell control string, always 6 + 1 digits 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 digits (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
have to be 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", note that equal
sign "=" and wall "|" are problematic (see below), total
length 1...200
* "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, references
in parameters or more/multi mode, "1" to enable nesting, "2" for
more/multi mode, prohibited for special work, see "Notes on
protection" below
* "tag=1" activate workaround for aggressive tags and
replace for example "<nonewiki>" <--> "<nowiki>", see
below under "Misc technical stuff"
* "hid=" list of 1...8 hidden named parameters, 2...16 (even !!!FIXME!!! deprecated, use ((HID=DEN))
number) strings in the list of names and values have to be
attached together by 1...15 (odd number) double at-signs "@@",
note that we rarely have more than one hidden parameter, total
length 4...1000, minimal content "a@@b" becomes "a=b",
prohibited for special work, hidden parameters must NOT
contain wikilinks, also no nested templates even with "nsm=1"
* "rem=" remark ie extra usage information for the target
template, note that equal sign "=" and wall "|" are problematic
(see below), LF is prohibited (LF + star "*" or cross "#" would
break layout), total length 1...1000, plain cross "#" at begin
is safe (such as "#T99") ie no begin-of-line-specific rules
apply, 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
------------------------------------------------------------------------
### Usage (user manual)
Features:
* calls a target (usually template) and separates cat insertions
from remaining wikitext, thus performs category suppression, 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 !!!FIXME!!! remove "hid="
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 "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")
* nested template calls will NOT work out of the box since the innermost
template is expanded at the earliest, but there is a solution, see below
"Notes on protection"
* references passed as template parameters don't work out of the box, but
there is a solution, see below "Notes on protection"
* uncommon syntax of nested inner template calls using {({ })} (same here,
this will NOT get "fixed" to "standard" double curly brackets)
* 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 ("pate" does NOT
bother with them one at a time), but there is a size limit max 10'000
octet:s resulting in a theoretical limit a bit below 5'000 anonymous
parameters, also there IS a limit of MAX 8 HIDDEN 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"
* uncommon syntax of the hidden forwarded parameters (parameter "hid=")
that have to be separated by "@@" instead of "|" or "=" and any single
parameter must NOT be empty (limitation comes from the wiki parser)
* 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 used in 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!!!
Notes on protection:
* some char:s, most notably equal sign "=" and wall "|", are problematic
in template calls, while particularly 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 "|"
* 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
* similar applies to some aggressive tags, for example with
{{umbox|text=There is a God|ref=<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
* this principle is bad for "pate" and and thus we must workaround it,
otherwise the concept of "pate" will NOT work at all
* the main workaround is to place the forwarded template call into double
rectangular brackets: [[umbox|text=NO WE CAN'T]] for
{{umbox|text=NO WE CAN'T}}, this "protects" walls and equal signs
used to delimit template parameters, but not such in the content
of those parameters, from premature expansion
* in some cases a further layer 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 to write
[[umbox|text=NO WE{({br})}CAN'T]], and let "pate" replace {({...})}
by ordinary {{...}} after it has been smuggled in behind the back of
the parser, the "nsm=1" or "nsm=2" parameter activates this
* 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 (not "nsm=1" here), write [[{({doit|})}]]
* for some aggressive tags in parameters (pre, nowiki, ref, gallery), we
have to do a similar thing, write for example <renef>...</renef> and let
"pate" fix it back to <ref>...</ref>, this is activated by "tag=1"
* 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 as the [[-]]-protected parameter or via "hid=" intended for
target template. Doing so in any of those 3 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:" 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
* reliably detect "((HID=DEN))" and split one wikitext into two wikitexts: !!!FIXME!!! not yet
* one with "((HID=DEN))" replaced by "=" intented to be fed into
expansion ie "arxframent:preprocess"
* one with parameters using "((HID=DEN))" removed intended to be
showed in the table
* 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 output is handled by:
* lfhparsemap -- brew
* lfhtablewithmap -- read only
* lfysplitkat -- read only
Only the subtable [0] of 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= hid= 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
* #E09 "sel=" bad
* #E10 "tit=" bad
* #E11 "war=" bad
* #E12 "bor=" bad
* #E28 "mod=" bad (equal "1", ...)
* #E29 "zer=" bad (also for target NOT in ns ZERO)
* #E31 "nsm=" bad
* #E32 "tag=" bad
* #E33 "hid=" bad (bad char:s, ...) !!!FIXME!!! deprecated
* #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 multi columns
* #E41 "mod=" and "zer=1" must NOT be used together
* #E43 "trackingcategorieshiglow=" sent into "pate" in at least ONE of 3 ways
* #E44 "nocat=" sent into "pate" in at least ONE of 3 ways
* #E46 strip marker detected in incoming target parameter
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.
* Simplified string "hiddendate@@1999-12-31@@hiddentime@@23:59" only
named parameters supported (but try "1="), used in "hid=", converted
in "lfipairxatxalt" into ordinary raw string form for expansion
beginning with a wall.
* We do NOT use a table with parameters for a call.
* Still we must look for "trackingcategorieshiglow=" or "nocat=" and
whine if found.
* We apply "partial preservation of trimmed whitespace" unless in the
more/multi mode by "nsm=2". Then [[ ]] serve as replacement of {{ }}
and we preserve ONE SPACE or ONE LF separately on every side, 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
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
* "hid=" does NOT work
* "hlt=1" and "ncf=1" do NOT work
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[ 9] = '"sel=" bad' -- EN #E09
contaberaroj[ 9] = '"sel=" erara' -- EO #E09
-- contaberaroj[ 9] = '"sel=" salah' -- ID #E09
-- 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
-- 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 (numinpuut, numzjmin, numzjmax)
local numclean = 0
local booisclean = false
numclean = math.floor (numinpuut) -- no transcendental
numclean = math.max (numclean,numzjmin) -- not below minimum
numclean = math.min (numclean,numzjmax) -- no trillions
booisclean = (numclean==numinpuut)
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 LFICHECKFORBAD
-- Output : * booisbaad -- true if string is bad
local function lficheckforbad (streniro)
local booisbaad = false
booisbaad = (string.find(streniro,"''",1,true)~=nil) -- dbl apo
booisbaad = booisbaad or (string.find(streniro,"[[",1,true)~=nil)
booisbaad = booisbaad or (string.find(streniro,"]]",1,true)~=nil)
booisbaad = booisbaad or (string.find(streniro,"{{",1,true)~=nil)
booisbaad = booisbaad or (string.find(streniro,"}}",1,true)~=nil)
return booisbaad
end--function lficheckforbad
------------------------------------------------------------------------
-- 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 LFIPAIRXATXALT
-- In multifield string convert "@@" to equal sign "=" and wall "|".
-- Input : * strdblinutat -- empty NOT legal
-- Output : * strdblinutat -- empty on error
-- Number of parts must be even, thus number of separators "@@" must be
-- odd, at least ONE. The incoming string must NOT begin or end with "@@",
-- length must be 4...1'000. This is applied on "hid=".
local function lfipairxatxalt (strdblinutat)
local varfyynndd = 0
local tabswitchwaltrue = {[false]='=',[true]='|'}
local numlimytkauntr = 0
local boonowwall = false
local boocrapss = false
while true do
varfyynndd = string.find (strdblinutat, "@@", 1, true)
if (not varfyynndd) then
break -- good or baad, decide below
end--if
if ((varfyynndd==1) or (varfyynndd==(string.len(strdblinutat)-1))) then
boocrapss = true -- baad, found at begin or end
break
end--if
if (numlimytkauntr==16) then
boocrapss = true -- baad, exceeded max 8 pairs
break
end--if
strdblinutat = string.sub(strdblinutat,1,(varfyynndd-1)) .. tabswitchwaltrue[boonowwall] .. string.sub(strdblinutat,(varfyynndd+2),-1)
boonowwall = not boonowwall
numlimytkauntr = numlimytkauntr + 1
end--while
if (boocrapss or (not boonowwall)) then
strdblinutat = '' -- more than 16 parts or odd number of parts or ...
else
strdblinutat = '|' .. strdblinutat -- begin with wall
end--if
return strdblinutat -- same var for in and out
end--function lfipairxatxalt
------------------------------------------------------------------------
-- Local function LFIRESTOREFROMNESTED
-- Restore ordinary form from nested workaround.
local function lfirestorefromnested (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 lfirestorefromnested
------------------------------------------------------------------------
-- Local function LFIRESTOREFROMNETAG
-- Restore ordinary form from tag workaround.
-- <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 invalid type ignored
-- * boopeek6it -- peek description #E02...#E99
-- 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 (type(numerar6code)~='number') then
numerar6code = 0 -- invalid
end--if
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 -- 2 ... 99
-- 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 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 !!!
-- 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 !!!
-- * 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 strhid = '' -- either empty or 4...1'000, see "lfipairxatxalt"
local strrem = ''
local strref = ''
local strreg = ''
-- 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 strbigexpander = '' -- for "arxframent:preprocess"
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
end--if
if (strmainanon==':end') then
numspec = 9 -- end
end--if
end--if (numerr==0) then
---- SEIZE UP TO 15 NAMED PARAMETERS ----
-- tab= (*), sel=, tit=, war=, bor=
-- mod= (*), zer= (*), nsm= (*), tag= (*), hid= (*), rem= (*)
-- ref= (*), reg= (*), hlt= (*), ncf= (*)
-- * 8 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 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!!!
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 = 9 -- #E09 "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 = 10 -- #E10 "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
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 = 11 -- #E11 "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
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 = 12 -- #E12 "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
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'] -- length 1 only, prohibited for special
if (type(var38pom)=='string') then
if ((string.len(var38pom)==1) and (numspec==0)) then
boozer = (var38pom=="1")
else
numerr = 7 -- #E07 "zer=" prohi for ":top"
numerr = 29 -- #E29 "zer=" bad
end--if
end--if
var38pom = arxsomons['nsm'] -- length 1 only, prohibited for special !!!FIXME!!!
if (type(var38pom)=='string') then
if ((string.len(var38pom)==1) and (numspec==0)) then -- tristate
boo3nsm2m = (var38pom=="2")
boo3nsm12 = boo3nsm2m or (var38pom=="1")
else
numerr = 7 -- #E07 "nsm=" prohi for ":top"
numerr = 31 -- #E31 "nsm=" bad
end--if
end--if
var38pom = arxsomons['tag'] -- length 1 only, prohibited for special !!!FIXME!!!
if (type(var38pom)=='string') then
if ((string.len(var38pom)==1) and (numspec==0)) then
bootag = (var38pom=="1")
else
numerr = 7 -- #E07 "tag=" prohi for ":top"
numerr = 32 -- #E32 "tag=" bad
end--if
end--if
var38pom = arxsomons["hid"] -- length 4...1000, prohibited for special
if (type(var38pom)=='string') then
while true do -- fake loop
if (numspec==9) then
numerr = 6 -- #E06 no named param legal for ":end"
break
end--if
numluung = string.len (var38pom)
if ((numluung<4) or (numluung>1000) or (numspec~=0)) then
numerr = 7 -- #E07 "hid=" prohi for ":top"
numerr = 33 -- #E33 "hid=" bad early detect
break
end--if
if (lficheckforbad(var38pom)) then
numerr = 33 -- #E33 "hid=" bad [[ ]] {({ })} ''
break
end--if
strhid = lfipairxatxalt (var38pom)
if (strhid=='') then -- empty legal but NOT here
numerr = 33 -- #E33 "hid=" bad due to @@
end--if
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
if (type(var38pom)=='string') then
numluung = string.len (var38pom)
if ((numluung>=1) and (numluung<=1000) and (numspec==0)) then
strrem = var38pom
else
numerr = 7 -- #E07 "rem=" prohi for ":top"
numerr = 34 -- #E34 "rem=" bad
end--if
end--if
var38pom = arxsomons["ref"] -- length 1...20, prohibited for special
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
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
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'] -- length 1 only, prohibited for special
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 = 9 -- #E09 "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
---- PLUPROCESS THE HOLY CALL STRING FOR MORE/MULTI ----
-- minimal content is "[[{({a})}]]" or "[[a]]" (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 more/multi 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 = 10 -- #E10 "tit=" bad
end--if
end--if
---- PREPARE FOR EXPANSION ----
-- * incoming target parameter "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")
-- * "strbigexpander" is for "arxframent:preprocess" only
-- * "strhid" is either empty or begins with a wall
-- * here we maybe restore ordinary form from
-- * nested protection ie "{({"..."})}"
-- * aggressive tags ("nonewiki", variations of "renef", ...)
-- even if we don't expand
-- * done on "strmainanon" without "strhid", this affetcs
-- both the showed text and the string fed into expansion
if ((numerr==0) and (numspec==0) and boo3nsm12) then
strmainanon = lfirestorefromnested (strmainanon)
end--if
if ((numerr==0) and (numspec==0) and bootag) then
strmainanon = lfirestorefromnetag (strmainanon)
end--if
tabinparmap = lfhparsemap (strmainanon) -- BIG MAP HERE !!!FIXME!!!
if (tabinparmap[0][4] or tabinparmap[0][5]) then
numerr = 46 -- #E46 strip NOT appreciated
end--if
if ((numerr==0) and (numspec==0) and boodoexpand and boo3nsm2m) then
strbigexpander = strmainanon -- take as-is
end--if
if ((numerr==0) and (numspec==0) and boodoexpand and (not boo3nsm2m)) then
strbigexpander = strmainanon .. strhid -- attach hidden !!!FIXME!!!
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 = strmainanon
if (not boo3nsm2m) then
strt8mp = lfibrewcurlycall (boozer,strt8mp,numwhitebeg,numwhiteend) -- maybe ":" SPC LF always {{ }}
end--if
strt8mp = lfidecencodbr (strt8mp,true) -- see "Encoding of text"
if (boosamepage or boo3nsm2m) then
strt7mp = strt8mp -- avoid selflink or link to more/multi text
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 ----
-- reporting of errors #E02...#E99 depends on uncommentable stuff
-- and name of the caller filled in from "constrkoll"
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