Modul:twoimage
Dokumentasi untuk modul ini dapat dibuat di Modul:twoimage/doc
--[===[
MODULE "TWOIMAGE" (two images)
"eo.wiktionary.org/wiki/Modulo:twoimage" <!--2024-Jun-13-->
"id.wiktionary.org/wiki/Modul:twoimage"
Purpose: places one image or two images on the right side of the
screen, 2 images are arranged horizontally
Utilo: lokigas unu bildon aux du bildojn dekstre sur la
ekrano, 2 bildoj estas arangxitaj horizontale
Manfaat: meletakkan satu atau dua gambar di tepi kanan ...
Syfte: placerar en eller tvaa bilder paa hoeger sida av
skaermen, 2 bilder anordnas horisontellt
Used by templates / Uzata far sxablonoj / Digunakan oleh templat:
* bildodek (EO) | gamkan (ID)
Required submodules / Bezonataj submoduloj / Submodul yang diperlukan:
* none
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: * 1...4 anonymous parameters
* a) (1) image name
* b) (2) image name and description
* c) (2) two image names
* d) (3) two image names and one description
* e) (4) image name, description, image name, description
Same rules apply to both image names and descriptions:
* must be 2...160 octet:s long
* must not contain double rectangular
brackets [[ ]] {{ }} nor "<center>" nor "[http"
nor strip markers resulting from some tags
* 1 named parameter "duon=1" or "half=1" (acceptance
depends on site language, reduces lengths by factor ca
1.5 and areas by factor ca 2.25)
* 3 hidden named parameters
* "pagenameoverridetestonly="
* "nsnumberoverridetestonly="
* "nocat=true" !!!FIXME!!! deprecated
Returned: * one string with a HTML table or inline error message
Note that it is indeed possible to feed in {{ }} by means of
{<noinclude/>{
otherwise the inner template gets expanded first.
To distinguish cases b) and c) both with 2 parameters the latter
parameter is analyzed in the following way:
if (less than 7 octet:s) then
assume b)
done
endif
loop (walk back from the end copying into a new string writing backwards too)
if (length of copied text is 5) then
assume b)
exit loop and done
endif
pick char
if (dot found) then
exit loop
endif
if (other value than ASCII letter found) then
assume b)
exit loop and done
endif
keep UPPERcase, change lowercase to UPPERcase
store char into new string backwards
endloop
if (new string is equal PNG BMP GIF JPG JPEG SVG OGV WEBM) then
assume c)
else
assume b)
endif
The 5 input cases map onto 3 possible output cases and tables:
b) one image (two table rows each with one cell)
d) two images with a common description (two table rows, the upper one
with two cells and the lower one with "colspan=2")
e) two images with two separate descriptions (2 table rows,
each with 2 cells)
If no description is provided then {{PAGENAME}} is seized,
and a) maps to b) and c) maps to d).
The image syntax fed to the wiki parser used (see also string "strsizes") is
[[File: (name) |center| (size) ]]
thus we do not use the description parameter. The reasons for doing so are:
* allow for a common description for the case d)
* avoid risk that a description like "999px" or similar breaks the layout
* reserve sufficient horizontal space for the text even if the image
is high and very narrow
One image is showed with "size" parameter "240x240px" or reduced "160x160px",
two images with "240x160px" or reduced "160x120px".
]===]
local exporttable = {}
------------------------------------------------------------------------
---- CONSTANTS [O] ----
------------------------------------------------------------------------
-- uncommentable EO vs ID constant strings (core site-related features)
-- local constrpriv = "eo" -- EO (privileged site language)
local constrpriv = "id" -- ID (privileged site language)
-- local constrkatq = "Kategorio" -- EO (tracking cat:s only, good and bad)
local constrkatq = "Kategori" -- ID (tracking cat:s only, good and bad)
-- 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
-- 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 (augmented name of the caller for error messages)
-- this goes through "lfifillname" and subsequently
-- through "lfhfillsurrstrtab", X-surrogates permitted
-- local constrkoll = 'sxablono "bildodek"' -- EO augmented name of the caller (semi-hardcoded, we do NOT peek it)
local constrkoll = 'templat "gamkan"' -- ID augmented name of the caller (semi-hardcoded, we do NOT peek it)
-- uncommentable EO vs ID constant table (error messages)
-- #E02...#E99, holes permitted
-- note that #E00 and #E01 are NOT supposed to be included here
-- separate "constrkoll" needed for "\\@"
local contaberaroj = {}
-- contaberaroj[ 8] = 'Erara uzo de \\@, legu gxian dokumentajxon' -- EO #E08 number of params
contaberaroj[ 8] = 'Penggunaan salah \\@, bacalah dokumentasinya' -- ID #E08
-- contaberaroj[ 9] = 'Erara uzo de \\@ pro transdonita signocxeno, estu 2...160 bitokoj' -- EO #E09 length of param
contaberaroj[ 9] = 'Penggunaan salah \\@ oleh karena string datang, sebaiknya 2...160 oktet' -- ID #E09
-- contaberaroj[10] = 'Erara uzo de \\@ pro nomspaco, estu 0 (kapvorto) aux 4 aux 102 (Aldono:)' -- EO #E10 ns
contaberaroj[10] = 'Penggunaan salah \\@ oleh karena ruang nama, sebaiknya 0 (lema) atau 4 atau 102 (Lampiran:)' -- ID #E10
-- contaberaroj[14] = 'Erara uzo de \\@ cxar en transdonita signocxeno trovita problemhava signaro' -- EO #E14
contaberaroj[14] = 'Penggunaan salah \\@ bahwa dalam string datang ditemukan karakter bermasalah' -- ID #E14
-- contaberaroj[15] = 'Erara uzo de \\@ cxar en transdonita signocxeno trovita "strip marker" pro <gallery> aux simile' -- EO #E15
contaberaroj[15] = 'Penggunaan salah \\@ bahwa dalam string datang ditemukan "strip marker" oleh karena <gallery> dsb' -- ID #E15
-- constant table (HTML)
-- note that we need "clear:right", not "clear:both" !!!
local contabhtml = {}
contabhtml[0] = '<table style="clear:right; float:right; margin:0 0 0.3em 0.3em; padding:0.2em; border:2px solid #909090;">'
contabhtml[1] = '<td style="padding:0.2em;">' -- cell with image
contabhtml[2] = '<td style="padding:0.2em; text-align:center;">' -- cell with text
contabhtml[3] = '<td style="padding:0.2em; text-align:center;" colspan="2">' -- cell with common description
contabhtml[4] = '</table>'
-- uncommentable EO vs ID constant table (cat:s)
local contabkatoj = {}
-- contabkatoj = {"Kapvortaj pagxoj kun bildo","Aldonaj vortaraj pagxoj kun bildo" ,"Erara uzo de sxablono (bildodek)" ,"Erara uzo de sxablono" } -- EO
contabkatoj = {"Halaman lema dengan gambar","Halaman lampiran kamus dengan gambar","Penggunaan salah templat (gamkan)","Penggunaan salah templat"} -- ID
-- contabkatoj[7] = "Permana tago (br) por sxablono (bildodek)" -- EO tracking cat !!!FIXME!!! not yet used
-- contabkatoj[7] = "Tag manual (br) untuk templat (gamkan)" -- ID
-- contabkatoj[8] = "Longa priskribo por sxablono (bildodek)" -- EO tracking cat !!!FIXME!!! not yet used
-- contabkatoj[8] = "Deskripsi panjang untuk templat (gamkan)" -- ID
-- constant table (3 integers for preliminary parameter check)
local contabparam = {}
contabparam[0] = 1 -- minimal number of anon parameters
contabparam[1] = 4 -- maximal number of anon parameters
contabparam[2] = 200 -- maximal length of single para (min is hardcoded ONE)
------------------------------------------------------------------------
---- SPECIAL STUFF OUTSIDE MAIN [B] ----
------------------------------------------------------------------------
---- VAR:S ----
local qbooguard = false -- only for the guard test, pass to other var ASAP
---- GUARD AGAINST INTERNAL ERROR ----
qbooguard = ((type(constrpriv)~='string') or (type(constrkatq)~='string') or (type(constrkoll)~='string'))
------------------------------------------------------------------------
---- MATH FUNCTIONS [E] ----
------------------------------------------------------------------------
local function mathisintrange (numinpuut, numzjmin, numzjmax)
local numclean = 0
local booisclean = false
if (type(numinpuut)=='number') then -- no non-numbers, thanks
numclean = math.floor (numinpuut) -- no transcendental
numclean = math.max (numclean,numzjmin) -- not below minimum
numclean = math.min (numclean,numzjmax) -- no trillions
booisclean = (numclean==numinpuut)
end--if
return booisclean
end--function mathisintrange
local function mathdiv (xdividens, xdivisero)
local resultdiv = 0 -- DIV operator lacks in LUA :-(
resultdiv = math.floor (xdividens / xdivisero)
return resultdiv
end--function mathdiv
local function mathmod (xdividendo, xdivisoro)
local resultmod = 0 -- MOD operator is "%" and bitwise AND operator lack too
resultmod = xdividendo % xdivisoro
return resultmod
end--function mathmod
------------------------------------------------------------------------
---- NUMBER CONVERSION FUNCTIONS [N] ----
------------------------------------------------------------------------
-- 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
------------------------------------------------------------------------
---- LOW LEVEL STRING FUNCTIONS [G] ----
------------------------------------------------------------------------
-- 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
------------------------------------------------------------------------
---- 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 -- unit octet, number 1...4, or ZERO if invalid
-- Does NOT thoroughly check the validity, looks at ONE 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
------------------------------------------------------------------------
-- Local function LFULNUTF8STRING
-- Evaluate length of a string in UTF8 char:s.
-- Input : * strutf8masu6k -- empty is useless but cannot cause major harm
-- Output : * numpanjan6g -- unit UTF8 char, -1 if invalid
-- Depends on functions :
-- [U] lfulnutf8char
-- Does NOT thoroughly check the validity, looks at ONE octet
-- of every char only.
local function lfulnutf8string (strutf8masu6k)
local numpanjan6g = 0 -- unit UTF8 char, becomes length of string
local numdepoin = 0 -- unit octet, ZERO-based index
local numoktle6n = 0
local numbeg6val = 0
local numchrlen = 0
numoktle6n = string.len(strutf8masu6k) -- limit
while true do
if (numdepoin>numoktle6n) then
numpanjan6g = -1 -- truncated -> invalid
end--if
if (numdepoin>=numoktle6n) then
break -- good or bad
end--if
numbeg6val = string.byte(strutf8masu6k,(numdepoin+1),(numdepoin+1))
numchrlen = lfulnutf8char (numbeg6val)
if (numchrlen==0) then
numpanjan6g = -1
break -- broken char -> invalid
end--if
numdepoin = numdepoin + numchrlen -- step 1...4 -- can overflow
numpanjan6g = numpanjan6g + 1 -- unit octet, step ONE
end--while
return numpanjan6g
end--function lfulnutf8string
------------------------------------------------------------------------
-- Local function LFUELEKTU
-- Called only from lfucututf8byspc.
local function lfuelektu (numpozzia, numdiista, numpozzib, numdiistb)
local nummynresult = -1 -- preASSume guilt
if ((numpozzia~=-1) and (numpozzib==-1)) then
nummynresult = numpozzia
end--if
if ((numpozzia==-1) and (numpozzib~=-1)) then
nummynresult = numpozzib
end--if
if ((numpozzia~=-1) and (numpozzib~=-1)) then
if (numdiista<numdiistb) then
nummynresult = numpozzia
else
nummynresult = numpozzib
end--if
end--if
return nummynresult
end--function lfuelektu
------------------------------------------------------------------------
-- Local function LFUCUTUTF8BYSPC
-- Find position for very clean UTF8 cutting between words (NOT in the middle
-- of a word, even less middle of char) by incoming UTF8 char position.
-- Input : * strutf8masu9k -- at least 10 octet:s, shorter rejected
-- * numtheopos -- unit UTF8 char, theoretical position (usually a
-- fraction of value obtained from lfulnutf8string,
-- at least 2 char:s away from begin and 2 char:s
-- away from end)
-- * nummaxdist -- unit UTF8 char, maximal distance from theoretical
-- position to found boundary (min 2, max 20, and
-- at most 1/4 of the length of the incoming string
-- measured in UTF8 char:s)
-- Output : * numcutpos -- best position, unit octet, -1 if failed
-- Depends on functions :
-- [U] lfulnutf8char
-- [U] lfuelektu (strictly internal, reserved for us)
-- Does NOT thoroughly check the validity, looks at ONE octet
-- of every char only.
-- Cutting priorities:
-- * on a space (returned position AT the space, caller probably will want
-- to suppress the space if replaced by EOL)
-- * on tuation "+,-./:;" (returned position AFTER the found char, caller
-- probably will NOT want to suppress it)
-- * anywhere between 2 UTF8 char:s
-- Thus we can happen to suggest cutting in the middle of a word in
-- worst case, but never in the middle of a UTF8 char.
-- We care about different lengths of UTF8 char:s, but not about
-- more. For useful results, the incoming string MUST NOT contain:
-- * combining decorations
-- * invisible ZWSP-spaces, RTL-marks, BOM-marks
-- * wikilinks
-- * HTML tags or HTML comments (for <i> and <b> see below)
-- * repetitive spaces
-- We do not care about bold and italic either, but limited use (say up to one
-- occurrence per 20 UTF8 char:s) will not have a remarkable negative impact.
-- There are some peculiarities when registering promising boundaries.
-- * BEFORE the theoretical position we register EVERY HIT, overwriting
-- a possible previous one, and resetting distance to ZERO
-- * AFTER the theoretical position we register the EARLIEST HIT ONLY, and
-- skip possible later hits, and writing in the only final distance
-- from a separate variable
-- * BEFORE the theoretical position we increase the distance for
-- entries we have ALREADY found, but if we exceed "nummaxdist" then
-- we reinvalidate the position
-- * AFTER the theoretical position we increase a separate variable that
-- we maybe write in on hit
local function lfucututf8byspc (strutf8masu9k, numtheopos, nummaxdist)
local tabposisi = { [0]= -1,-1,-1,-1} -- unit octet
local tabdistan = { [0]= 0, 0, 0, 0} -- unit UTF8 char
local numcutpos = -1 -- preASSume guilt, unit octet, the final result
local numpanjan9g = 0 -- unit UTF8 char, grow to numtheopos plus tiny margin
local numpo9in = 0 -- unit octet, ZERO-based index
local numoktle9n = 0
local numbeg9val = 0
local numchr9len = 0
local numoffset = 0 -- ZERO for preceding | 2 for passed
local numdistafter = 0 -- unit UTF8 char, BEFORE: keep ZERO | AFTER: grow
local boospejs = false
local bootuation = false
local boopassed = false -- set to true after theoretical position passed
local boodoone = false -- true if analyzing loop failed or fully succeeded
numoktle9n = string.len(strutf8masu9k) -- limit
while true do
if ((numoktle9n<10) or (numtheopos<2) or (nummaxdist<2) or (nummaxdist>20) or (numpo9in>numoktle9n)) then
numcutpos = -1
boodoone = true -- too short string or ... or trunc in middle of char
break
end--if
if (numpo9in==numoktle9n) then
if ((numpanjan9g<(numtheopos+2)) or (numpanjan9g<(nummaxdist*4))) then
numcutpos = -1
boodoone = true -- too close to end of string or "nummaxdist" too high
end--if
break -- done or not
end--if
numbeg9val = string.byte(strutf8masu9k,(numpo9in+1),(numpo9in+1))
numchr9len = lfulnutf8char (numbeg9val)
if (numchr9len==0) then
numcutpos = -1
boodoone = true -- broken char -> invalid
break
end--if
boospejs = (numbeg9val==32)
bootuation = ((numbeg9val>=43) and (numbeg9val<=47)) or (numbeg9val==58) or (numbeg9val==59)
if (numpanjan9g==numtheopos) then
numcutpos = numpo9in -- unit octet, maybe will get replaced later
if (boospejs) then
boodoone = true
break -- yeah the best imaginable outcome
end--if
end--if
if ((not boopassed) and (tabposisi[0]~=-1)) then
tabdistan[0] = tabdistan[0] + 1 -- unit UTF8 char
if (tabdistan[0]>nummaxdist) then -- reinvalidate the position
tabdistan[0] = 0
tabposisi[0] = -1
end--if
end--if
if ((not boopassed) and (tabposisi[1]~=-1)) then
tabdistan[1] = tabdistan[1] + 1 -- unit UTF8 char
if (tabdistan[1]>nummaxdist) then -- reinvalidate the position
tabdistan[1] = 0
tabposisi[1] = -1
end--if
end--if
if (boospejs and ((not boopassed) or (tabposisi[numoffset]==-1))) then
tabposisi[numoffset] = numpo9in -- unit octet
tabdistan[numoffset] = numdistafter -- unit UTF8 char
end--if
if (bootuation and ((not boopassed) or (tabposisi[1+numoffset]==-1))) then
tabposisi[1+numoffset] = numpo9in -- unit octet
tabdistan[1+numoffset] = numdistafter -- unit UTF8 char
end--if
if ((numdistafter>nummaxdist) or ((tabposisi[2]~=-1) and (tabposisi[3]~=-1))) then
break -- nothing to be gained anymore or got all
end--if
numpo9in = numpo9in + numchr9len -- step 1...4 -- can overflow
numpanjan9g = numpanjan9g + 1 -- unit octet, step ONE
boopassed = (numpanjan9g>=numtheopos)
if (boopassed) then
numoffset = 2
numdistafter = numdistafter + 1
end--if
end--while
if (not boodoone) then -- try to buy space
numoffset = lfuelektu (tabposisi[0],tabdistan[0],tabposisi[2],tabdistan[2])
if (numoffset~=-1) then
numcutpos = numoffset -- succeeded to buy space
boodoone = true -- prefer space over tuation
end--if
end--if
if (not boodoone) then -- try to buy tuation
numoffset = lfuelektu (tabposisi[1],tabdistan[1],tabposisi[3],tabdistan[3])
if (numoffset~=-1) then
numcutpos = numoffset + 1 -- succeeded to buy tuation
end--if
end--if
return numcutpos
end--function lfucututf8byspc
------------------------------------------------------------------------
---- HIGH LEVEL STRING FUNCTIONS [I] ----
------------------------------------------------------------------------
-- Local function LFICHECKFORBABR
-- Check whether a parameter is illegal.
-- Output : * numerarko -- non-ZERO on error
-- Note that we tolerate "<br>" as well as double and triple apos:s here.
local function lficheckforbabr (strinputstring,numminlen,nummaxlen)
local numlongoo = 0
local numerarko = 0 -- ZERO OK | 9 len | 14 bad generic | 15 strip
local boobrottsligt = false
while true do -- fake loop
if ((type(numminlen)=='number') and (type(nummaxlen)=='number')) then
if (numminlen<nummaxlen) then
numlongoo = string.len (strinputstring)
if ((numlongoo<numminlen) or (numlongoo>nummaxlen)) then
numerarko = 9
break -- to join mark
end--if
end--if
end--if
boobrottsligt = (string.find(strinputstring," ",1,true)~=nil) -- multiple spaces
boobrottsligt = boobrottsligt or (string.find(strinputstring,"[[",1,true)~=nil) -- wikilinks
boobrottsligt = boobrottsligt or (string.find(strinputstring,"]]",1,true)~=nil) -- wikilinks
boobrottsligt = boobrottsligt or (string.find(strinputstring,"{{",1,true)~=nil) -- possible
boobrottsligt = boobrottsligt or (string.find(strinputstring,"}}",1,true)~=nil) -- possible
boobrottsligt = boobrottsligt or (string.find(strinputstring,"<center>",1,true)~=nil) -- !!!FIXME!!! this is weak
boobrottsligt = boobrottsligt or (string.find(strinputstring,"<centre>",1,true)~=nil)
boobrottsligt = boobrottsligt or (string.find(strinputstring,"<BR>",1,true)~=nil) -- !!!FIXME!!! this is weak
boobrottsligt = boobrottsligt or (string.find(strinputstring,"</br>",1,true)~=nil)
boobrottsligt = boobrottsligt or (string.find(strinputstring,"</ br>",1,true)~=nil)
boobrottsligt = boobrottsligt or (string.find(strinputstring,"<br/>",1,true)~=nil)
boobrottsligt = boobrottsligt or (string.find(strinputstring,"<br />",1,true)~=nil)
boobrottsligt = boobrottsligt or (string.find(strinputstring,"[http",1,true)~=nil)
if (boobrottsligt) then
numerarko = 14
break -- to join mark
end--if
if (string.find(strinputstring,(string.char(127,39,34,96)..'UNIQ'),1,true)) then -- striptease markers
numerarko = 15
end--if
break -- finally to join mark
end--while -- fake loop -- join mark
return numerarko
end--function lficheckforbabr
------------------------------------------------------------------------
---- HIGH LEVEL FUNCTIONS [H] ----
------------------------------------------------------------------------
-- Local function LFHBREWERROR
-- Depends on functions :
-- [N] lfnumto2digit
-- [E] mathisintrange mathdiv mathmod
-- Depends on constants :
-- * 3 strings constrelabg constrelaen constrlaxhu
-- * table contaberaroj TWO-based
local function lfhbrewerror (numerrorcode)
local vardeskrip = 0
local strytsux = '#E'
if (mathisintrange(numerrorcode,2,99)) then
strytsux = strytsux .. lfnumto2digit(numerrorcode) .. ' '
vardeskrip = contaberaroj[numerrorcode] -- risk of type "nil"
if (type(vardeskrip)=='string') then
strytsux = strytsux .. vardeskrip
else
strytsux = strytsux .. '??' -- no text
end--if
else
strytsux = strytsux .. '??' -- no valid error code
end--if
strytsux = constrlaxhu .. constrelabg .. strytsux .. constrelaen .. constrlaxhu
return strytsux
end--function lfhbrewerror
------------------------------------------------------------------------
-- Local function LFHSPLITMANAUTO !!!FIXME!!! trim spaces
-- Depends on functions :
-- [U] lfulnutf8char lfulnutf8string lfucututf8byspc
-- [E] mathdiv
local function lfhsplitmanauto (strdescriiption)
local strbeginpart = ''
local numleninutf8chars = 0 -- unit UTF8 char
local numcuthere = 0 -- unit octet
local boomanualsplit = false
boomanualsplit = (string.find(strdescriiption,'<br>',1,true)~=nil)
if (not boomanualsplit) then
numleninutf8chars = lfulnutf8string (strdescriiption)
if (numleninutf8chars>80) then
numcuthere = lfucututf8byspc(strdescriiption,mathdiv(numleninutf8chars,3),10)
strbeginpart = string.sub(strdescriiption,1,numcuthere) .. '<br>'
strdescriiption = string.sub(strdescriiption,(numcuthere+1),-1)
end--if
numleninutf8chars = lfulnutf8string (strdescriiption) -- reevaluate !!!
if ((numleninutf8chars>40) or (strbeginpart~='')) then
numcuthere = lfucututf8byspc(strdescriiption,mathdiv(numleninutf8chars,2),10)
strdescriiption = string.sub(strdescriiption,1,numcuthere) .. '<br>' .. string.sub(strdescriiption,(numcuthere+1),-1)
end--if
strdescriiption = strbeginpart .. strdescriiption
end--if
return strdescriiption
end--function lfhsplitmanauto
------------------------------------------------------------------------
-- Local function LFHTESTFILE
-- Check whether parameter can be a filename ie name of a picture or video.
-- Example:
-- "blackhole.png" len = 13 (positions 1...13 ONE-based)
-- 1234567890123 last dot at position 10 (ONE-based)
-- difference 3 (4 would be OK too)
-- seized substring comes from positions 11...13 (difference 2, length 3)
local function lfhtestfile (strparanometer)
local strsubu = ''
local numlen = 0
local numchhar = 0
local numiindeks = 0
local boogotcee = false -- "false" is b) and "true" is c)
while true do -- fake loop
numlen = string.len (strparanometer)
if (numlen<7) then
break -- no way, minimal is "Saw.png" or like that
end--if
numiindeks = numlen -- ONE-based counts down
while true do -- inner loop
if ((numiindeks+5)==numlen) then
numiindeks = 0 -- F**K
break -- inner loop -- no dot found, this is NOT a filename extension
end--if
numchhar = string.byte (strparanometer,numiindeks,numiindeks)
if (numchhar==46) then
break -- inner loop -- dot is here, do NOT store it
end--if
if ((lfgtestuc(numchhar)==false) and (lfgtestlc(numchhar)==false)) then
numiindeks = 0 -- F**K
break -- inner loop -- faulty value, this is NOT a filename extension
end--if
if (lfgtestlc(numchhar)) then
numchhar = numchhar - 32 -- make UPPERcase
end--if
strsubu = string.char (numchhar) .. strsubu -- ueglstr
numiindeks = numiindeks - 1 -- ONE-based counts down
end--while -- inner loop
if (numiindeks==0) then
break -- this is NOT a filename extension
end--if
boogotcee = ((strsubu=='PNG') or (strsubu=='BMP') or (strsubu=='GIF') or (strsubu=='JPG') or (strsubu=='JPEG') or (strsubu=='SVG') or (strsubu=='OGV') or (strsubu=='WEBM'))
break -- finally
end--while -- fake loop
return boogotcee
end--function lfhtestfile
------------------------------------------------------------------------
-- 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 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
-- NOPE 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 NOPE "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] NOPE lfikodsvsg
-- [E] mathdiv mathmod (via "lfikodeosg" and NOPE "lfikodsvsg")
-- Depends on constants :
-- * table "contabtransluteo" inherently holy (via "lfikodeosg")
-- * NOPE table "contabtranslutsv"
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
------------------------------------------------------------------------
---- VARIABLES [R] ----
------------------------------------------------------------------------
function exporttable.ek (arxframent)
-- general unknown type
local vartmp = 0 -- variable without type multipurpose
-- special type "args" AKA "arx"
local arxsomons = 0 -- metaized "args" from our own or caller's "frame"
-- general str
local strpagenam = '' -- from "{{PAGENAME}}" o "pagenameoverridetestonly"
local strruangna = '' -- "{{NAMESPACENUMBER}}" o "nsnumberoverridetestonly"
local strsizes = '' -- actually more than x and y
local strtmp = '' -- temp
local strimagkk = '' -- name left or one
local strdesckk = '' -- desc left or one
local strimagll = '' -- name right
local strdescll = '' -- desc right
local strviserr = '' -- visible error
local strvisgud = '' -- visible good output ie table
local strinvkat = '' -- invisible category part
local strret = '' -- final result string
-- general num (no var for namespace)
local numerr = 0 -- 0 OK 1 inter 2 param 3 deskripsi 11 ns
local numpindex = 0 -- number of anon params
local numcase = 0 -- decimal 97...101 for a) to e)
local numsizxx = 0
local numsizyy = 0
local numtamp = 0
-- general boo
local boonocat = false -- from "nocat=true"
local booreduced = false -- from "duon=1" "half=1"
local booprojekto = false -- "true" if ns = 4 (no num var exists)
local booaldono = false -- "true" if ns = 102 (no num var exists)
------------------------------------------------------------------------
---- MAIN [Z] ----
------------------------------------------------------------------------
---- GUARD AGAINST INTERNAL ERROR AGAIN ----
-- later reporting of #E01 may NOT depend on uncommentable strings
if (qbooguard) then
numerr = 1 -- #E01 internal
end--if
---- PROCESS MESSAGES, FILL IN ALWAYS, SURR ONLY IF NEEDED ----
-- placeholder "\@" "\\@" is replaced by augmented name of the caller
-- from "constrkoll" in any case, for example 'sxablono "test"' or
-- 'templat "test"'
-- only for some languages the surr-transcoding is subsequently performed
if (numerr==0) then
contaberaroj = lfhfillsurrstrtab (contaberaroj, constrkoll, constrpriv)
contabkatoj = lfhfillsurrstrtab (contabkatoj, constrkoll, 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 anon params for now (would cause #E08)
arxsomons = arxframent.args -- "args" from our own "frame"
if (type(arxsomons)~="table") then
arxsomons = {} -- guard against indexing error
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
---- PROCESS 3 HIDDEN NAMED PARAMS ----
-- this may override "mw.title.getCurrentTitle().text" and
-- stipulate content in "strpagenam", missing is OK, empty is NOT valid
-- bad "pagenameoverridetestonly=" can give #E01
-- give a f**k in possible anon params for now (could otherwise cause #E08)
strpagenam = ""
if (numerr==0) then
vartmp = arxsomons['pagenameoverridetestonly']
if (type(vartmp)=='string') then
numtamp = string.len(vartmp)
if ((numtamp>=1) and (numtamp<=160)) then
strpagenam = vartmp -- empty is not legal
else
numerr = 1 -- #E01 internal
end--if
end--if
end--if (numerr==0) then
strruangna = ""
if (numerr==0) then
vartmp = arxsomons['nsnumberoverridetestonly']
if (type(vartmp)=='string') then
numtamp = string.len(vartmp)
if ((numtamp>=1) and (numtamp<=4)) then
strruangna = vartmp -- empty is not legal but ignore crime
end--if
end--if
end--if
boonocat = (arxsomons['nocat']=='true') -- "arxsomons" must be a table !!!
---- SEIZE THE PAGENAME FROM MW AFTER OVERRIDE AND PROHIBIT EMPTY ----
-- later reporting of #E01 may NOT depend on uncommentable strings
-- must be 1...160 octet:s keep consistent with "pagenameoverridetestonly="
if ((numerr==0) and (strpagenam=='')) then
vartmp = mw.title.getCurrentTitle().text -- without namespace prefix
if (type(vartmp)=='string') then -- this can leave bhnd "strpagenam" empty
numtamp = string.len(vartmp)
if ((numtamp>=1) and (numtamp<=160)) then
strpagenam = vartmp -- pagename here (empty is NOT legal)
else
numerr = 1 -- #E01 internal
end--if
end--if
end--if
if (strpagenam=='') then
numerr = 1 -- #E01 internal -- no other error number is possible so far
end--if
---- WHINE IF YOU MUST #E01 ----
-- reporting of this error #E01 may NOT depend on
-- uncommentable strings such as "constrkoll" and "contaberaroj"
-- do NOT use sub "lfhbrewerror", report our name (NOT of template) and in EN
if (numerr==1) then
strtmp = '#E01 Internal error in module "twoimage".'
strviserr = constrlaxhu .. constrelabg .. strtmp .. constrelaen .. constrlaxhu
end--if
---- SEIZE THE NAMESPACE FROM MW AND CHECK IT ----
-- assign "booprojekto" "booaldono" on success or brew #E10 on failure
if ((numerr==0) and (strruangna=='')) then
vartmp = mw.title.getCurrentTitle().namespace -- this is a number
if (type(vartmp)=="number") then -- this can leave bhnd "strruangna" empty
if ((vartmp>=0) and (vartmp<=9999)) then
strruangna = tostring(vartmp) -- empty is not legal but ignore crime
end--if
end--if
end--if
if (numerr==0) then
booprojekto = (strruangna=='4')
booaldono = (strruangna=='102')
if ((strruangna~='0') and (not booprojekto) and (not booaldono)) then
numerr = 10 -- #E10 wrong ns (overrides #E08 and #E09)
end--if
end--if
---- PRELIMINARILY ANALYZE ANONYMOUS PARAMETERS ----
-- this will catch holes, empty parameters, too long parameters,
-- and wrong number of parameters, and give #E08 on a violation
-- below on exit var "numpindex" will contain number of
-- prevalidated anonymous params
-- this depends on 3 constants:
-- * contabparam[0] minimal number
-- * contabparam[1] maximal number
-- * contabparam[2] maximal length
if (numerr==0) then
numpindex = 0 -- ZERO-based
numtamp = contabparam[1] -- maximal number of params
while true do
vartmp = arxsomons [numpindex+1] -- can be "nil"
if ((type(vartmp)~="string") or (numpindex>numtamp)) then
break -- good or bad (can go one iteration too long)
end--if
numlong = string.len (vartmp)
if ((numlong==0) or (numlong>contabparam[2])) then
numerr = 8 -- #E08 param/RTFD
break -- only bad here
end--if
numpindex = numpindex + 1 -- on exit has number of valid parameters
end--while
if ((numpindex<contabparam[0]) or (numpindex>numtamp)) then
numerr = 8 -- #E08 param/RTFD
end--if
end--if
---- SEIZE 1...4 ANONYMOUS PARAMETERS ----
-- here we assign "numcase" to "a)" to "e)" ie 97 to 101
-- "lficheckforbabr" returns non-ZERO if illegal giving #E09 #E14 #E15
if (numerr==0) then
while true do -- fake loop
strimagkk = arxsomons [1] -- assign in any valid case
numerr = lficheckforbabr(strimagkk,2,160)
if (numerr~=0) then
break -- #E09 #E14 #E15
end--if
if (numpindex==1) then
numcase = 97 -- a) (1) image name
break
end--if
if (numpindex==2) then -- b) or c)
strtmp = arxsomons [2]
numerr = lficheckforbabr(strtmp,2,160)
if (numerr~=0) then
break -- #E09 #E14 #E15
end--if
if (lfhtestfile(strtmp)) then -- c)
numcase = 99 -- c) (2) two image names
strimagll = strtmp
else
numcase = 98 -- b) (2) image name and description
strdesckk = strtmp
end--if
break
end--if (numpindex==2) then
if (numpindex==3) then -- d)
numcase = 100 -- d) (3) two image names and one description
strimagll = arxsomons [2]
strdesckk = arxsomons [3]
numerr = lficheckforbabr(strimagll,2,160)
if (numerr~=0) then
break -- #E09 #E14 #E15
end--if
numerr = lficheckforbabr(strdesckk,2,160)
if (numerr~=0) then
break -- #E09 #E14 #E15
end--if
else
numcase = 101 -- e) (4) image name, description, image name, description
strdesckk = arxsomons [2]
strimagll = arxsomons [3]
strdescll = arxsomons [4]
numerr = lficheckforbabr(strdesckk,2,160)
if (numerr~=0) then
break -- #E09 #E14 #E15
end--if
numerr = lficheckforbabr(strimagll,2,160)
if (numerr~=0) then
break -- #E09 #E14 #E15
end--if
numerr = lficheckforbabr(strdescll,2,160)
if (numerr~=0) then
break -- #E09 #E14 #E15
end--if
end--if (numpindex==3) else
break -- finally
end--while -- fake loop
end--if (numerr==0) then
---- WHINE IF YOU MUST #E02...#E99 ----
-- reporting of errors #E02...#E99 depends on uncommentable strings
-- and name of the caller filled in from "constrkoll"
if (numerr>1) then
strviserr = lfhbrewerror(numerr)
end--if
---- SEIZE 1 NAMED PARAMETER ----
-- this cannot cause any error but "arxsomons" must be a table !!!
booreduced = false
if (constrpriv=="eo") then
booreduced = (arxsomons['duon']=='1')
end--if
if (constrpriv=="id") then
booreduced = (arxsomons['half']=='1')
end--if
---- REDUCE 5 CASES TO 3 BY MAGIC MAPPING ----
if (numerr==0) then
if (numcase==97) then
strdesckk = strpagenam
numcase = 98 -- a) becomes b) -- one image one description
end--if
if (numcase==99) then
strdesckk = strpagenam
numcase = 100 -- c) becomes d) -- two images one common description
end--if
end--if
---- RANDOMGENERATE THE SIZES ----
if (numerr==0) then
if (numcase==98) then
if (booreduced) then
numsizxx = 160 -- one reduced, case b)
numsizyy = 160
else
numsizxx = 240 -- one full, case b)
numsizyy = 240
end--if
else
if (booreduced) then
numsizxx = 160 -- two reduced, cases d) e)
numsizyy = 120
else
numsizxx = 240 -- two full, cases d) e)
numsizyy = 160
end--if
end--if
strsizes = "|center|" .. tostring (numsizxx) .. "x" .. tostring (numsizyy) .. "px]]"
end--if
---- SPLIT THE DESCRIPTIONS ----
strdesckk = lfhsplitmanauto (strdesckk)
if (numcase==101) then -- e)
strdescll = lfhsplitmanauto (strdescll)
end--if
---- BREW THE TABLE ----
-- this depends on "contabhtml"
-- [[File: (name) |center| (size) ]]
-- "strsizes" begins with the left wall "|" and includes the final "]]"
-- b) one image (two table rows each with one cell)
-- d) two images with a common description (two table rows, the upper one
-- with two cells and the lower one with "colspan=2")
-- e) two images with two separate descriptions (2 table rows,
-- each with 2 cells)
if (numerr==0) then
strvisgud = contabhtml[0] -- begin table
if (numcase==98) then -- b)
strvisgud = strvisgud .. '<tr>' .. contabhtml[1] .. '[[File:' .. strimagkk .. strsizes .. '</td></tr>'
strvisgud = strvisgud .. '<tr>' .. contabhtml[2] .. strdesckk .. '</td></tr>'
end--if
if (numcase==100) then -- d)
strvisgud = strvisgud .. '<tr>' .. contabhtml[1] .. '[[File:' .. strimagkk .. strsizes .. '</td>' .. contabhtml[1] .. '[[File:' .. strimagll .. strsizes .. '</td></tr>'
strvisgud = strvisgud .. '<tr>' .. contabhtml[3] .. strdesckk .. '</td></tr>'
end--if
if (numcase==101) then -- e)
strvisgud = strvisgud .. '<tr>' .. contabhtml[1] .. '[[File:' .. strimagkk .. strsizes .. '</td>' .. contabhtml[1] .. '[[File:' .. strimagll .. strsizes .. '</td></tr>'
strvisgud = strvisgud .. '<tr>' .. contabhtml[2] .. strdesckk .. '</td>' .. contabhtml[2] .. strdescll .. '</td></tr>'
end--if
strvisgud = strvisgud .. contabhtml[4] -- close table
end--if
---- BREW THE CAT PART ----
-- one cat for numerr=0, two cats for numerr>=2, no cats for numerr=1
-- "constrkatq" is the cat prefix NOT including the colon ":"
if (not boonocat) then
if (numerr==0) then
if (booprojekto or booaldono) then
strinvkat = contabkatoj[2] -- aldo (alt project/internal)
else
strinvkat = contabkatoj[1] -- lemma
end--if
strinvkat = '[[' .. constrkatq .. ':' .. strinvkat .. ']]'
end--if
if (numerr>=2) then
strinvkat = '[[' .. constrkatq .. ':' .. contabkatoj[3] .. ']][['.. constrkatq .. ':' .. contabkatoj[4] .. ']]' -- both
end--if
end--if
---- RETURN THE JUNK STRING ----
strret = strviserr .. strvisgud .. strinvkat
return strret
end--function
---- RETURN THE JUNK LUA TABLE ----
return exporttable