Módulo:SimpleArgs
Uso
Utilizado por otros módulos para comprobación de parámetros pasados.
Para traducir o revisar la traducción a su idioma del módulo, edite con cuidado Data:I18n/SimpleArgs.tab.
Funciones
- Arg(ument)s son los argumentos del frame actual.
- Par(armeter)Id(entificator) es el nombre/s o el orden del parámetro.
- La marca * indica que es un parámetro opcional. Si no se quiere asignar un valor opcional no correlativo se puede asignar el valor de nil.
- Ejemplo: función_de_número (Args, paridas, LimInf*, LimSup*) -> función_de_número (args, 1, nil, 12), comprobará que el número no sea mayor de 12.
- Obviamente sería correcto -> función_de_número (args, 1), sin ninguna comprobación de los valores de los números.
- Str(ing): Cadena.
- Num(ber): Número.
- Int(teger): Entero.
- Pos(itive)Num/Int: Número/entero positivo.
- ZeroOrPosNum/Int: Cero o número/entero positivo.
- Char(acter): Caracter.
- Tab(ble): Tabla.
Principal
- GetArgs (frame, HandleError*, SameSize*) - Devuelve los argumentos y su número.
- Si
HandleError == true
->Error.handle = true
- Si
SameSize == true
->Error.samesize = true
- Si
Manipulación de los errores
- Error = {
- handle = false,
- yes = false,
- msg = ,
- samesize = false,
- }
- MsgError (S)
Si handle = false
, cuando se produce un error se presenta un error de lua. Así: Error Lua: error.
Si handle = true
, es el que hace el módulo quien deberá hacer un return
con el error, así return MsgError()
, devolviendo la fuente de un error de lua. Así: error. Se hace una comprobación parámetro a parámetro si no se detecta ningún error.
- El error se anota en una variable.
- Se anota que ha habido un error y así no se comprueba más errores en el resto de parámetros.
- Al final de la comprobación y entrada de variables el programador debería escribir:
if SA.Error.yes then return SA.MsgError() end
(dondeSA
está definida cómolocal SA = require "Module:SimpleArgs"
).
Si handle = true
y samesize = true
entonces el mensaje devuelto será con letra en negrita y de color rojo. Así: error.
Vea los ejemplos.
Comprobación de los nombres de los parámetros
V/F | nombre | Parámetros o Valores |
Descripción |
---|---|---|---|
F | CheckParams | args, UsualArgs | Comprobación de los nombres de los parámetros (de args ) según la tabla de nombres permitidos para los parámetros (UsualArgs ). Si un mismo parámetro tiene varios nombres, estos nombres se pueden agrupar en una tabla, como se muestra en ejemplo más abajo (modo sencillo). Se genera un error indicando el nombre de palabra no encontrado.
|
V | HasChild | HasChild | Utilizado en CheckParamsM
|
F | CheckParamsM | args, UsualArgs, OtherArgs*, ArgNamesIn1 | Realiza la comprobación de los parámetros como CheckParams pero con tablas más complejas.
Devuelve dos tablas con los dos tipos de errores encontrados. Una lista con los nombres de los parámetros no encontrados y el otro con duplicados. Un parámetro duplicado es un error raro que se puede producir cuando un parámetro puede tener más de una denominación y en la llamada desde una plantilla se hace más de una llamada con el mismo parámetro. |
Tablas UsualArgs
1. Ejemplos para CheckParams
y CheckParamsM
o modo sencillo:
{"name", "surname"}
Modo sencillo con más de un nombre por parámetro:
{{"name","Name"}, {"surname","Surname"}}
2. Ejemplos para CheckParamsM
o modo complejo:
Utilizando ArgNamesIn1 = true
, se indica que es el primer elemento o tabla lo que contiene el nombre o los nombres de los parámetros:
['birth'] = {{"birth_year",1}, "P569"}, ['death'] = {{"death_year",2}, "P570"}, ['intro'] = {"intro", "Q305178"},
Utilizando HasChild
:
[SA.HasChild] = true, ['year'] = { ['birth'] = {"birth_year",1}, ['death'] = {"death_year",2}, }, ['other'] = { ['intro'] = "intro", },
Otras
- p.ParamsSep = '/' - Variable usada para la siguiente función.
- ConcatParams (tab) - Se utiliza cuando un parámetro tiene más de un nombre para el mismo parámetro.
Comprobación de números
Devuelven el número N si este número es correcto, de lo contrario devuelven un mensaje de error.
Nombre | Parámetros |
---|---|
CheckNum | N, ParId, LimInf, LimSup |
CheckNumIsInt | N, ParId, LimInf*, LimSup*) |
CheckNumIsPos | N, ParId, LimInf*, LimSup*) |
CheckNumIsZeroOrPos | N, ParId, LimSup*) |
Comprobación de si las cadenas son números
Devuelven un número si la cadena es un número correcto, de lo contrario devuelven un mensaje de error.
Nombre | Parámetros |
---|---|
CheckSIsNum | S, ParId, LimInf*, LimSup* |
CheckSIsInt | S, ParId, LimInf*, LimSup* |
CheckSIsPosInt | S, ParId, LimInf*, LimSup* |
CheckSIsZeroOrPosInt | S, ParId, LimSup* |
Valores de los parámetros específicos del frame
Las funciones con una R inicial indican que el parámetro es necesario. Devuelven el valor del tipo pedido del parámetro si es correcto, de lo contrario devuelven un mensaje de error.
Mire los ejemplos de Módulo:SimpleArgs/Tests/SVals
Cadenas
Nombre | Parámetros |
---|---|
Str_Par | Args, ParId, Default* |
RStr_Par | Args, ParId, OKEmpty* |
Char_Par | Args, ParId, Pattern, Default* |
RChar_Par | Args, ParId, Pattern |
NulOrWhitespace_Par | Args, ParId |
StrChkTab_Par | Args, ParId, Tab, CaseSens*, Default* |
RStrChkTab_Par | Args, ParId, Tab, CaseSens* |
StrIdxChkTab_Par | Args, ParId, Tab, CaseSens*, Default* |
RStrIdxChkTab_Par | Args, ParId, Tab, CaseSens* |
Números reales
Nombre | Parámetros |
---|---|
Num_Par | Args, ParId, Default*, LimInf*, LimSup* |
RNum_Par | Args, ParId, LimInf*, LimSup* |
PosNum_Par | Args, ParId, Default*, LimInf*, LimSup* |
RPosNum_Par | Args, ParId, LimInf*, LimSup* |
ZeroOrPosNum_Par | Args, ParId, Default*, LimSup* |
RZeroOrPosNum_Par | Args, ParId, LimSup* |
Números enteros
Nombre | Parámetros |
---|---|
Int_Par | Args, ParId, Default*, LimInf*, LimSup* |
RInt_Par | Args, ParId, LimInf*, LimSup* |
PosInt_Par | Args, ParId, Default*, LimInf*, LimSup* |
RPosInt_Par | Args, ParId, LimInf*, LimSup* |
ZeroOrPosInt_Par | Args, ParId, Default*, LimSup* |
RZeroOrPosInt_Par | Args, ParId, LimSup* |
Tamaño, html
Donde limits es una tabla con los márgenes inferior y superior de los 3 tipos de tamaño posibles: porcentaje (perc), em y píxel (px):
Por ejemplo: {perc={20,100}, em={12,119}, px={200,1900}}
Nombre | Parámetros |
---|---|
Size_Par | Args, ParId, WithPerc, limits*, Default* |
RSize_Par | Args, ParId, WithPerc, limits* |
Colores, html
Devuelve, con las siguientes funciones el color pasado como parámetro es devuelto como cadena y sólo la parte "numérica" (NNNNNN). Así si el parámetro es "Green" devuelve '008000', y si es '#00800B' devuelve '00800B'. Admite los nombres de colores web.
Nombre | Parámetros |
---|---|
Color_Par | Args, ParId, Default* |
RColor_Par | Args, ParId |
También existe la siguiente función ReverseColor
que permite encontrar el color "contrario" al introducido para conseguir el máximo contraste. Esto facilita determinar el color del texto para un fondo de color determinado o viceversa. Así, por ejemplo:
{{#invoke:SimpleArgs|ReverseColor|Red}}
devuelve Aqua{{#invoke:SimpleArgs|ReverseColor|#000000}}
devuelve White
Existe la función _ReverseColor (rgb)
a llamar desde otro módulo donde rgb es el color en formato NNNNNN. Para convertir el color a formato NNNNNN existe la función CheckSIsColor
.
Alineación horizontal
Donde los valores posibles son: left|izquierdo|izquierda, center|centro y right|derecho|derecha.
Nombre | Parámetros |
---|---|
HAlign_Par | Args, ParId, Default* |
RHAlign_Par | Args, ParId |
Alineación vertical
Donde los valores posibles son: top|arriba, center|centro y bottom|abajo.
Nombre | Parámetros |
---|---|
VAlign_Par | Args, ParId, Default* |
RVAlign_Par | Args, ParId |
Booleano
Donde los valores posibles son: sí|si|s|yes|y|true|verdad|t|1 y no|n|false|falso|f|0.
Nombre | Parámetros |
---|---|
Bool_Par | Args, ParId, Default* |
RBool_Par | Args, ParId |
Índice de una lista
Nombre | Parámetros |
---|---|
StrIdxChkTab | Args, ParId, CaseSens, Default, ... |
RStrIdxChkTab | Args, ParId, CaseSens, ... |
StrIdxChkTabE | Args, ParId, CaseSens, Default, ... |
RStrIdxChkTabE | Args, ParId, CaseSens, ... |
Tablas de tablas de cadenas o números
MinItemNum y MaxItemNum, indican el mínimo y el máximo de elementos insertados en la tabla.
Cuando alguno de los valores no esté asignado actuará según OnEmpty: 0: Se incluirá. 1: No se incluirá. 2. Activará un error y su mensaje.
De un parámetro
Para el mismo parámetro con los elementos separados por Sep. Ejemplo, con "sep" = ":" y el parámetro = "12: 1: 1,3" devuelve {12, 1, 1.3}
Nombre | Parámetros |
---|---|
StrTab_1Par | Args, ParId, Sep, MinItemNum*, MaxItemNum*, OnEmpty* |
NumTab_1Par | Args, ParId, Sep, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty* |
PosNumTab_1Par | Args, ParId, Sep, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty* |
ZeroOrPosNumTab_1Par | Args, ParId, Sep, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty* |
IntTab_1Par | Args, ParId, Sep, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty* |
PosIntTab_1Par | Args, ParId, Sep, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty* |
ZeroOrPosIntTab_1Par | Args, ParId, Sep, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty* |
De varios parámetros
Nota diferencial, para Par(armeter)Id(entificator):
- Si es una posición:
- Y es un 1: captará todos los parámetros desde el primero hasta el último que no sea un número. Así puede contener parámetros no numéricos (no posicionales a la vez).
{{Función|a|b|c|opcional=si}}
-> StrTab_NPar (args, 4, 1} -> {a,b,c}{{Función|opcional=sí|a|b|c}}
-> StrTab_NPar (args, 4, 1} -> {a,b,c}{{Función|a|b|c}}
-> StrTab_NPar (args, 3, 1} -> {a,b,c}
- Y es otro número: captará todos los parámetros desde la posición hasta el último (pasado por NArgs).
{{Función|Palabra|a|b|c}}
-> StrTab_NPar (args, 4, 2} -> {a,b,c}{{Función|Palabra|a|b|c}}
-> StrTab_NPar (args, 4, 3} -> {b,c}
- Y es un 1: captará todos los parámetros desde el primero hasta el último que no sea un número. Así puede contener parámetros no numéricos (no posicionales a la vez).
Los parámetros pueden ser:
- Si es una cadena, ésta deberá contener un $d que será sustituido por un entero correlativo (a partir del 1) hasta que no se encuentre ningún parámetro. Ejemplo: 'para $d, buscará 'para 1', 'para 2', etc.
- Si es una tabla, se hará la misma búsqueda que el anterior punto por cada uno de los valores. Ejemplo: {'para $d, param $d}, buscará 'para 1' y 'param 1', después 'para 2' y 'param 2', etc.
Las funciones:
Nombre | Parámetros |
---|---|
StrTab_NPar | Args, NArgs, ParId, MinItemNum*, MaxItemNum*, OnEmpty* |
NumTab_NPar | Args, NArgs, ParId, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty* |
PosNumTab_NPar | Args, NArgs, ParId, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty* |
ZeroOrPosNumTab_NPar | Args, NArgs, ParId, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty* |
IntTab_NPar | Args, NArgs, ParId, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty* |
PosIntTab_NPar | Args, NArgs, ParId, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty* |
ZeroOrPosIntTab_NPar | Args, NArgs, ParId, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty* |
Mire los ejemplos de Módulo:SimpleArgs/Tests/SVals
Otras
F/V | Nombre | Parámetros | Explicación |
---|---|---|---|
F | HasValue | v | Devuelve true si (v ~= nil) and (v ~= '')
|
F | deep_copy_table | orig | Devuelve una copia de la tabl orig
|
F | tableMerge | t1, t2 | Sencilla fusión de tablas, utilitzado en loadI18n .
|
V | wiki_langcode | El idioma de la Wikipedia | |
F | get_lang | langcode | Devuelve langcode si tiene un valor, de lo contrario devuelve el idioma del usuario si es que éste no se encuentra en una página de artículo, en este caso devuelve el idioma de la Wikipedia.
|
V | lang_to_use | Contiene el valor de get_lang .
| |
F | I18nName | ModName | Devuelve el nombre del módulo i18n, en caso de wiki_langcode ~= lang_to_use devuelve i18n/lang_to_use si existe.
|
F | loadI18n | ModName, DefTable | Devuelve la tabla fusionada i18n con DefTable .
|
F | TemplateName | frame | Devuelve el nombre de la plantilla desde la cual es llamada. Así en la Plantilla:LaMía, escribiendo {{#invoke:SimpleArg|TemplateName}} , o invocando desde una función (llamada desde la plantilla) de un módulo con TemplateName(frame) retornarían: LaMía.
|
F | MainTemplateName | frame | Similar a la anterior, para cuando se utiliza desde plantillas de prueba. Así en la Plantilla:LaMía/prueba devolvería igualmente: LaMía. |
F | CheckIsStr | v, S | Comprueba que v sea una cadena con un valor, de lo contrario genera un error. |
F | CheckIsStrOrTab | v, S | Comprueba que v sea una cadena con un valor o una tabla de cadenas con valor, de lo contrario genera un error. |
F | CheckIsAnyStrOrTab | v, S | Comprueba que v sea una cadena o una tabla de cadenas, también genera un error. |
Colores
ColorToHex (frame)
convierte el nombre del color en formato hexadecimal.
color_black_contrast (frame)
determina la luminosidad de un color, con algunas correcciones para grises. A utilizar para el fondo de un texto de superposición. Proviene en parte de Three algorithms for converting color to grayscale. Existe la función _color_black_contrast (rgb)
a llamar desde otro módulo.
txtcolor_for_bg (frame)
, permite encontrar el color "contrario" al introducido para conseguir el máximo contraste del texto, determinando si debe ser blanco o negro. Existe la función _txtcolor_for_bg (rgb)
a llamar desde otro módulo.
ReverseColor (frame)
, alternativo a color_black_contrast
permite encontrar el color "contrario" al introducido para conseguir el máximo contraste. Esto facilita determinar el color del texto para un fondo de color determinado o viceversa. Existe la función _ReverseColor (rgb)
a llamar desde otro módulo. Ejemplo:
{{#invoke:SimpleArgs|ReverseColor|Red}}
devuelve Aqua{{#invoke:SimpleArgs|ReverseColor|#000000}}
devuelve White
Color de fondo y su nombre |
ColorToHex |
color_black_contrast |
Con fondo de texto teniendo en cuenta los valores de la columna anterior(1) |
txtcolor_for_bg |
(2) |
---|---|---|---|---|---|
255 | -- | ||||
LightCyan | E0FFFF | 242 | LightCyan | LightCyan | |
yellow | FFFF00 | 235 | yellow | yellow | |
Wheat | F5DEB3 | 213 | Wheat | Wheat | |
200 | 0.3 | ||||
aqua | 00FFFF | 184 | aqua | aqua | |
lime | 00FF00 | 163 | lime | lime | |
silver | C0C0C0 | 159 | silver | silver | |
Violet | EE82EE | 143 | Violet | Violet | |
140 | 0.5 | ||||
fuchsia | FF00FF | 92 | fuchsia | fuchsia | |
olive | 808000 | 88 | olive | olive | |
80 | 0.7 | ||||
red | FF0000 | 71 | red | red | |
teal | 008080 | 69 | teal | teal | |
gray | 808080 | 63 | gray | gray | |
green | 008000 | 61 | green | green | |
maroon | 800000 | 27 | maroon | maroon | |
blue | 0000FF | 20 | blue | blue | |
navy | 000080 | 8 | navy | navy |
1: Utilizando <span style="background-color:rgba(255,255,255,opacity)> {{{1|}}} </span>
opacity
= número de 0 a 1, utilizando los valores 0,3, 0,5 y 0,7
2: Utilizando ReverseColor
local p = {}
--[[
Version 2020-08-28
1. Get parameters (whether the parameters are called with #invoke or from a template)
2. Get parameters (of several types with their verification) from frame parameters.
ParId parameter is identified by a position (1, 2, 3 ... ), single name (|name= |other name=) or table of two names for each parameter.
This last options is used in translations that retain the original language (or main), usually English, i.e.:
local keywords = { -- in this case with Spanish
name = {'name', 'nombre'},
other name = {'other name', 'otro nombre'},
}
Then the parameter can be obtained with p.GetStr_Par (Args, keywords[name])
--]]
local RS = {
NotFoundArgName = 'NotFoundArgName',
SIsNotNumber = 'SIsNotNumber',
NIsNotPosNumber = 'NIsNotPosNumber',
NIsNotZeroOrPosNumber = 'NIsNotZeroOrPosNumber',
NIsNotInt = 'NIsNotInt',
NIsNotInRange = 'NIsNotInRange',
NIsLessThan = 'NIsLessThan',
NIsGreaterThan = 'NIsGreaterThan',
InvalColorLength = 'InvalColorLength',
InvalColorChar = 'InvalColorChar',
InvalColorName = 'InvalColorName',
STabIsNotInRange = 'STabIsNotInRange',
STabFewItems = 'STabFewItems',
SIsNotAssigned = 'SIsNotAssigned',
CharNotFoundInPattern = 'CharNotFoundInPattern',
SNotFoundInTab = 'SNotFoundInTab',
EmptyValue = 'EmptyValue',
SizeUnitRequired = 'SizeUnitRequired',
InvalSizeUnit = 'InvalSizeUnit',
SizeWithoutNumber = 'SizeWithoutNumber',
InvalAlign = 'InvalAlign',
InvalBool = 'InvalBool',
left = 'left',
right = 'right',
top = 'top',
bottom = 'bottom',
center = 'center',
Yes = 'Yes',
No = 'No',
PossibleValues = 'PossibleValues',
}
local SD = require('Module:SimpleDebug')
local I18n = 'SimpleArgs'
local i18n = {
[RS.NotFoundArgName] = "The parameter name \"$1\" is invalid",
[RS.SIsNotNumber] = "\"$1\" is not a number",
[RS.NIsNotPosNumber] = "$1 is not a positive number",
[RS.NIsNotZeroOrPosNumber] = "$1 is not zero or a positive number",
[RS.NIsNotInt] = "$1 is not an integer.",
[RS.NIsNotInRange] = "$1 is not between $2 and $3",
[RS.NIsLessThan] = "$1 is less than $2",
[RS.NIsGreaterThan] = "$1 is greater than $2",
[RS.InvalColorLength] = 'Invalid color code length, after "#", 6 valid characters (0-F) are required (found "$1")',
[RS.InvalColorChar] = 'Invalid character in the code color (from "$1")',
[RS.InvalColorName] = 'Color name ($1) is not a valid HTML color name',
[RS.STabIsNotInRange] = "The item number ($1) is not between $2 and $3",
[RS.STabFewItems] = "There are too few elements ($1), at least $2 are required",
[RS.SIsNotAssigned] = "Required parameter is missing",
[RS.CharNotFoundInPattern] = "\"$1\" is not a character of \"$2\"",
[RS.SNotFoundInTab] = "\"$1\" is not found in \"$2\"",
[RS.EmptyValue] = "\"$1\" has not a value",
[RS.SizeUnitRequired] = "Size unit required (em, px or %)",
[RS.InvalSizeUnit] = "Invalid unit ($1)",
[RS.SizeWithoutNumber] = "Without number",
[RS.InvalAlign] = "Invalid alignment ($1)",
[RS.InvalBool] = "Invalid boolean ($1)",
[RS.left] = "left",
[RS.right] = "right",
[RS.top] = "top",
[RS.bottom] = "bottom",
[RS.center] = "center",
[RS.Yes] = "yes|y|true|t|1",
[RS.No] = "no|n|false|f|0",
[RS.PossibleValues] = "Possible values: $1",
}
function p.HasValue (v)
return (v ~= nil) and (v ~= '')
end
--http://lua-users.org/wiki/CopyTable:
function p.deep_copy_table (orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[p.deep_copy_table(orig_key)] = p.deep_copy_table(orig_value)
end
setmetatable(copy, p.deep_copy_table(getmetatable(orig)))
else -- number, string, boolean, etc
copy = orig
end
return copy
end --deep_copy_table
-- Credit to http://stackoverflow.com/a/1283608/2644759
-- cc-by-sa 3.0
function p.tableMerge (t1, t2)
for k,v in pairs(t2) do
if type(v) == "table" then
if type(t1[k] or false) == "table" then
p.tableMerge(t1[k] or {}, t2[k] or {})
elseif ((v ~= nil) and (t1[k] == nil)) or p.HasValue(v) then --old version ...else t1[k] = v end
t1[k] = v
end
elseif ((v ~= nil) and (t1[k] == nil)) or p.HasValue(v) then --old version ...else t1[k] = v end
t1[k] = v
end
end
return t1
end --tableMerge
local wiki_langcode = mw.language.getContentLanguage().code
function p.get_lang (langcode)
--form Module:Wikidades
if mw.language.isKnownLanguageTag(langcode or '') == false then
if not mw.title.getCurrentTitle().isContentPage then
local cframe = mw.getCurrentFrame()
langcode = cframe:preprocess('{{int:lang}}')
end
if mw.language.isKnownLanguageTag(langcode or '') == false then
langcode = wiki_langcode
end
end
return langcode
end --get_lang
p.lang_to_use = p.get_lang ()
function p.I18nName (ModName)
local i18n_suffix0 = "/i18n"
local i18n_suffix = ''
if p.lang_to_use ~= wiki_langcode then
i18n_suffix = i18n_suffix0..'/'..p.lang_to_use
else
i18n_suffix = i18n_suffix0
end
local FN = "Module:"..ModName
local title = mw.title.new (FN..i18n_suffix)
if title.exists then
return FN..i18n_suffix
else
FN = FN..i18n_suffix0
title = mw.title.new (FN)
if title.exists then
return FN
else
error (string.format('Not found "%s"',FN)) -- Translation not required
end
end
end --I18nName
function p.loadI18n (ModName, DefTable)
local FN = p.I18nName (ModName)
return p.tableMerge(DefTable, require(FN).i18n)
end --loadI18n
---
function p.I18nStrParams (S, ...)
local result = mw.message.newRawMessage (S, ...)
return result:plain()
end
function p.TrimWdTab (tab)
for k, i in ipairs(tab) do
tab[k] = mw.text.trim (i)
end
return tab
end --TrimWdTab
function p.I18nParamsTab (Wds, MaxTrans)
local tab = mw.text.split (Wds, '|')
if (MaxTrans ~= nil) and (#tab > MaxTrans) then
error (string.format('Found %s translations for "%s"',#tab,S)) -- Translation not required
end
return p.TrimWdTab (tab)
end --I18nParamsTab
function p.I18nParamsTabCS (Wds, CaseSensitive)
CaseSensitive = ((CaseSensitive ~= nil) and (CaseSensitive == true)) or true
if not CaseSensitive then
Wds = string.lower (Wds)
end
tab = mw.text.split (Wds, '|')
return p.TrimWdTab (tab)
end --I18nParamsTabCS
function p.SFoundInWdTab (WdTable, val, CaseSensitive, S)
if (S == nil) or (S == '') then
error('Not parameters trying to find "'..val..'"') --It doesn't require translation, only for degug
end
local Arr = p.I18nParamsTabCS (WdTable[S], CaseSensitive)
if not CaseSensitive then
val = string.lower (val)
end
for _, W in ipairs(Arr) do
if W == val then
return true
end
end
return false
end --SFoundInWdTab
function p.IdxFromWdTab (WdTable, val, CaseSensitive, ...)
local Arr = unpack(arg)
if Arr == nil then
error('Not parameters trying to find "'..val..'"') --It doesn't require translation, only for degug
end
local Idx = 0
for I, W in ipairs(Arr) do
if p.SFoundInWdTab (WdTable, val, CaseSensitive, W) then
Idx = I
break
end
end
return Idx
end --IdxFromWdTab
function p.JoinI18nTables (tabs)
local res = {}
for _, v in ipairs(tabs) do
for _, vv in pairs(v) do
table.insert (res, vv)
end
end
return res
end --JoinTables
----------
i18n = p.loadI18n (I18n, i18n)
local function I18nStr (S, ...)
return p.I18nStrParams (i18n[S], ...)
end
function p.i18n_vals (frame)
local args = p.GetArgs (frame)
local res = i18n[p.RStr_Par(args,1)]
if res == nil then
error ('Invalid word')
else
return res
end
end --i18n_vals
----------
p.Error = {
handle = false,
yes = false,
msg = '',
samesize = false
}
function p.MsgError (S)
if S == nil then
if p.Error.samesize then
return '<span style="color:red;font-weight:bold">'..p.Error.msg..'</span>'
else
return '<strong class="error">'..p.Error.msg..'</strong>'
end
else
if p.Error.handle then
p.Error.msg = S
p.Error.yes = true
else
error (S, 0)
end
end
end--MsgError
function p.GetAndClearError ()
local E = p.Error.msg
p.Error.msg = ''
p.Error.yes = false
return E
end --GetAndClearError
function p.TableSize (tab)
Count = 0
for _, v in pairs(tab) do
Count = Count + 1
end
return Count
end --TableSize
function p.TableWithItems (tab)
if #tab > 0 then
return true
else
for _, v in pairs(tab) do
return true
end
return false
end
end --TableWithItems
function p.GetArgs (frame, HandleError, SameSize)
local origArgs
if frame == mw.getCurrentFrame() then
-- We're being called via #invoke. If the invoking template passed any parameters,
-- use them. Otherwise, use the parameters that were passed into the template.
origArgs = frame:getParent().args
for _, v in pairs( frame.args ) do
origArgs = frame.args
break
end
else
-- We're being called from another module or from the debug console, so assume
-- the parameters are passed in directly.
origArgs = frame
end
NArgs = p.TableSize (origArgs)
if (HandleError ~= nil) and (HandleError == true) then
p.Error.handle = true
if (SameSize ~= nil) and (SameSize == true) then
p.Error.samesize = true
end
end
if p.Error.handle and (NArgs == 0) then
p.MsgError ('')
end
return origArgs, NArgs
end --GetArgs
function p.GetArgsT (frame, HandleError, SameSize)
--Get paramenters,num from template that call to module (returned 1st,2nd) and from module (returned 3rd,4th)
local origArgs, NArgs = p.GetArgs (frame, HandleError, SameSize)
pargs = frame:getParent().args
NPArgs = p.TableSize(pargs)
if NPArgs == 0 then
return pargs, NPArgs, origArgs, NArgs
else
return origArgs, NArgs, pargs, NPArgs
end
end --GetArgsT
function p.GetArgsTMerge (frame, HandleError, SameSize)
local arg1, NArg1, arg2, NArg2 = p.GetArgsT (frame, HandleError, SameSize)
local args = {}
for k, val in pairs(arg1) do
args[k] = val
end
for k, val in pairs(arg2) do
args[k] = val
end
return args
end --GetArgsTMerge
p.ParaSep = '/'
function p.ConcatParams (tab)
return '"'..table.concat(tab,p.ParaSep)..'"'
end
local function ParamErrorS (ParId, S)
if ParId == nil then
error ('Not assigned ParId') --Not require translation, only debug
elseif ParId ~= '' then
local SParaId = ''
if type(ParId)=='table' then
SParaId = p.ConcatParams (ParId)
else
if type(ParId)=='number' then
ParId = '#'..ParId
end
SParaId = ParId
end
S = SParaId..' = '..S
end
p.MsgError (S)
end--ParamErrorS
local function ParamError (ParId, RS, Value)
if Value == '' then
Value = '""'
end
local S = I18nStr (RS, tostring(Value))
ParamErrorS (ParId, S)
end--ParamError
----------
local function GetArgsPass (args)
local ArgsPass = {}
for k, v in pairs(args) do
if type(k) == 'string' then
table.insert (ArgsPass, k)
end
end
return ArgsPass
end --GetArgsPass
function p.ErrNotFoundArgName (v)
p.MsgError (I18nStr (RS.NotFoundArgName, v))
end
function p.CheckParams (args, UsualArgs)
if p.Error.yes then return end
local ArgsPass = GetArgsPass (args)
local UsualArgsC = p.deep_copy_table (UsualArgs)
for _, v in ipairs(ArgsPass) do
local found = false
for kk, vv in pairs(UsualArgsC) do
if type(vv) == 'table' then
for j, w in ipairs(vv) do
if v == w then
found = true
UsualArgsC[kk][j] = nil
break
end
end
else
if v == vv then
found = true
UsualArgsC[kk] = nil
end
end
if found then
break
end
end
if not found then
p.ErrNotFoundArgName (v)
break
end
end
end --CheckParams
p.HasChild = 'HasChild'
function p.CheckParamsM (args, UsualArgs, OtherArgs, ArgNamesIn1)
--[[ Warning!: UsualArgs is a table of table or parameters,
e.g.{args_main_module, args_shared_module1, args_shared_module2} or
{args_main_module}
In ArgNamesIn1 mode, each parameter has the name/s and type: e.g.
["key"] = {"Arg_name", "i+"} or
["key"] = {{"Arg_name","arg_name"} "i+"}
in this case "i+" indicates a positive integer.
--]]
if p.Error.yes then return end
if p.Error.handle then
unknown_param = {}
end
local ArgsPass = GetArgsPass (args)
local flags_dupli_args = {}
local flags_dupli_args_s = {}
local dupli_args = {}
local key = ''
local UsualArgsC = p.deep_copy_table (UsualArgs)
for _, v in ipairs(ArgsPass) do
local found = false
for kk, vv in ipairs(UsualArgsC) do
if vv[p.HasChild] == true then
for j, w in pairs(vv) do
if j ~= p.HasChild then
for jj, ww in pairs(w) do
if ArgNamesIn1 then
ww = ww[1] --skip type
end
if type(ww) == 'table' then
for jjj, www in ipairs(ww) do
if v == www then
found = true
key = jj
break
end
end
else
if v == ww then
key = jj
found = true
end
end
if found then
break
end
end
end
if found then
break
end
end
else
for j, w in pairs(vv) do
if ArgNamesIn1 then
w = w[1] --skip type
end
if type(w) == 'table' then
for jj, ww in ipairs(w) do
if v == ww then
key = j
found = true
break
end
end
else
if v == w then
key = j
found = true
end
end
if found then
break
end
end
end
if found then
break
end
end
if found then
if flags_dupli_args[key] then
table.insert (dupli_args, key..' ('..flags_dupli_args_s[key]..'-'..v..')')
else
flags_dupli_args[key] = true
flags_dupli_args_s[key] = v
end
end
if (not found) and (OtherArgs ~= nil) then
if type(OtherArgs) == 'table' then
for _, vv in ipairs(OtherArgs) do
if v == vv then
found = true
break
end
end
else
found = v == vv
end
end
if not found then
p.ErrNotFoundArgName (v)
if p.Error.handle then
table.insert (unknown_param, p.GetAndClearError())
else
break
end
end
end
if p.Error.handle and ((#unknown_param > 0) or (#dupli_args > 0)) then
return unknown_param, dupli_args
end
end --CheckParamsM
----------
local function prepNum (N)
return mw.getContentLanguage():formatNum (N)
end
function p.CheckNum (N, ParId, LimInf, LimSup)
if (p.Error.yes) or (not N) then return end
if ((LimInf ~= nil) and (N < LimInf)) and ((LimSup ~= nil) and (N > LimSup)) then
ParamErrorS (ParId, I18nStr (RS.NIsNotInRange, prepNum(N), prepNum(LimInf), prepNum(LimSup)))
elseif (LimInf ~= nil) and (N < LimInf) then
ParamErrorS (ParId, I18nStr (RS.NIsLessThan, prepNum(N), prepNum(LimInf)))
elseif (LimSup ~= nil) and (N > LimSup) then
ParamErrorS (ParId, I18nStr (RS.NIsGreaterThan, prepNum(N), prepNum(LimSup)))
end
end --p.CheckNum
function p.CheckNumIsInt (N, ParId, LimInf, LimSup)
if p.Error.yes then return end
if N == math.floor(N) then
p.CheckNum (N, ParId, LimInf, LimSup)
else
ParamError (ParId, RS.NIsNotInt, prepNum(N))
end
end --CheckNumIsInt
function p.CheckNumIsPos (N, ParId, LimInf, LimSup)
if p.Error.yes then return end
if N > 0 then
p.CheckNum (N, ParId, LimInf, LimSup)
else
ParamError (ParId, RS.NIsNotPosNumber, N)
end
end --CheckNumIsPos
function p.CheckNumIsZeroOrPos (N, ParId, LimSup)
if p.Error.yes then return end
if N >= 0 then
p.CheckNum (N, ParId, 0, LimSup)
else
ParamError (ParId, RS.NIsNotZeroOrPosNumber, N)
end
end --CheckNumIsZeroOrPos
-----
function p.CheckSIsNum (S, ParId, LimInf, LimSup)
if p.Error.yes then return end
local N = tonumber(S)
if not N then
ParamError (ParId, RS.SIsNotNumber, S)
else
p.CheckNum (N, ParId, LimInf, LimSup)
end
end --CheckSIsNum
function p.CheckSIsInt (S, Where, LimInf, LimSup)
if p.Error.yes then return end
p.CheckSIsNum (S, Where, LimInf, LimSup)
if p.Error.yes then return end
p.CheckNumIsInt (tonumber(S), Where)
end
function p.CheckSIsPosInt (S, ParId, LimInf, LimSup)
if p.Error.yes then return end
p.CheckSIsInt (S, ParId, LimInf, LimSup)
if p.Error.yes then return end
p.CheckNumIsPos (tonumber(S), ParId)
end
function p.CheckSIsZeroOrPosInt (S, ParId, LimSup)
if p.Error.yes then return end
p.CheckSIsInt (S, ParId, 0, LimSup)
if p.Error.yes then return end
p.CheckNumIsZeroOrPos (tonumber(S), ParId)
end
function p.NotAssignedValue (ParId)
ParamErrorS (ParId, I18nStr (RS.SIsNotAssigned))
end
----------
p.OKEmptyVal = true
function p.Str_Par (Args, ParId, Default)
if p.Error.yes then return end
local S = nil
if type(ParId) == 'table' then
for _, W in ipairs(ParId) do
S = Args[W]
if S ~= nil then
break
end
end
else
S = Args[ParId]
end
if S == nil then
if Default ~= nil then
S = Default
end
else
S = mw.text.trim (S)
if S == '' then
if Default ~= nil then
S = Default
elseif not p.OKEmptyVal then
S = nil
end
end
end
return S
end --Str_Par
function p.RStr_Par (Args, ParId, OKEmpty)
if p.Error.yes then return end
local S = p.Str_Par (Args, ParId)
if (S == nil) or ((S == '') and ((OKEmpty == nil) or (not OKEmpty))) then
p.NotAssignedValue (ParId)
else
return S
end
end --RStr_Par
function p.Char_Par (Args, ParId, Pattern, Default)
if p.Error.yes then return end
local Char = p.Str_Par (Args, ParId, Default)
if p.Error.yes then return end
if Char ~= nil then
local Valid = ((Default ~= nil) and (Char == Default)) or (string.len(Char) == 1) and (string.find(Pattern,Char) ~= nil)
if not Valid then
ParamErrorS (ParId, I18nStr (RS.CharNotFoundInPattern, Char, Pattern))
end
end
return Char
end --Char_Par
function p.RChar_Par (Args, ParId, Pattern)
if p.Error.yes then return end
local Char = p.Char_Par (Args, ParId, Pattern)
if p.Error.yes then return end
if Char == nil then
p.NotAssignedValue (ParId)
else
return Char
end
end --RChar_Par
function p.NulOrWhitespace_Par (Args, ParId)
if p.Error.yes then return end
local S = p.Str_Par (Args, ParId)
if p.Error.yes then return end
return (S == nil) or (S == '')
end
local function PerhapsLow (CaseSens, Wd)
if CaseSens then
return Wd
else
return string.lower(Wd)
end
end --PerhapsLow
function p.StrChkTab_Par0 (ParId, S, Tab, CaseSens, Default)
if (S ~= nil) and (S ~= Default) then
local SIni = S
S = PerhapsLow(CaseSens,S)
local found = false
for _, W in ipairs(Tab) do
if S == PerhapsLow(CaseSens,W) then
S = W
found = true
break
end
end
if not found then
ParamErrorS (ParId, I18nStr (RS.SNotFoundInTab, SIni, table.concat(Tab,', ')))
S = nil
end
end
return S
end --StrChkTab_Par0
function p.StrChkTab_Par (Args, ParId, Tab, CaseSens, Default)
if p.Error.yes then return end
local S = p.Str_Par (Args, ParId, Default)
if p.Error.yes then return end
return p.StrChkTab_Par0 (ParId, S, Tab, CaseSens, Default)
end --StrChkTab_Par
function p.RStrChkTab_Par (Args, ParId, Tab, CaseSens)
if p.Error.yes then return end
local S = p.StrChkTab_Par (Args, ParId, Tab)
if p.Error.yes then return end
if S == nil then
p.NotAssignedValue (ParId)
else
return S
end
end --RStrChkTab_Par
function p.StrIdxChkTab_Par (Args, ParId, Tab, CaseSens, Default)
if p.Error.yes then return end
local S = p.Str_Par (Args, ParId, Default)
if p.Error.yes then return end
if (S ~= nil) and (S ~= Default) then
local SIni = S
S = PerhapsLow(CaseSens,S)
local found = false
for I, W in ipairs(Tab) do
if S == PerhapsLow(CaseSens,W) then
S = I
found = true
break
end
end
if not found then
ParamErrorS (ParId, I18nStr (RS.SNotFoundInTab, SIni, table.concat(Tab,', ')))
S = nil
end
end
return S
end --StrIdxChkTab_Par
function p.RStrIdxChkTab_Par (Args, ParId, Tab, CaseSens)
if p.Error.yes then return end
local S = p.StrIdxChkTab_Par (Args, ParId, Tab)
if p.Error.yes then return end
if S == nil then
p.NotAssignedValue (ParId)
else
return S
end
end --RStrIdxChkTab_Par
--Used in parameters to force an integer, number and others to return "NONE" (parameter to non-use)
p.AcceptNone = false
p.None = "NONE"
local function IsNone (S)
return p.AcceptNone and (S == p.None)
end
function p.Num_Par (Args, ParId, Default, LimInf, LimSup)
if p.Error.yes then return end
local N = p.Str_Par (Args, ParId)
if p.Error.yes then return end
if IsNone(N) then return p.None end
if N == nil then
if Default ~= nil then
N = Default
end
return N, true
else
p.CheckSIsNum (N, ParId, LimInf, LimSup)
if p.Error.yes then return end
return tonumber(N), false
end
end --Num_Par
function p.RNum_Par (Args, ParId, LimInf, LimSup)
if p.Error.yes then return end
local N = p.Num_Par (Args, ParId, nil, LimInf, LimSup)
if p.Error.yes then return end
if N == nil then
p.NotAssignedValue (ParId)
else
return N, false
end
end --RNum_Par
function p.PosNum_Par (Args, ParId, Default, LimInf, LimSup)
if p.Error.yes then return end
local N, IsDefault = p.Num_Par (Args, ParId, Default, LimInf, LimSup)
if IsNone(N) then return p.None end
if p.Error.yes then return end
if not IsDefault then
p.CheckNumIsPos (N, ParId)
if p.Error.yes then return end
end
return N
end --PosNum_Par
function p.RPosNum_Par (Args, ParId, LimInf, LimSup)
if p.Error.yes then return end
local N = p.PosNum_Par (Args, ParId, nil, LimInf, LimSup)
if p.Error.yes then return end
if N == nil then
p.NotAssignedValue (ParId)
else
return N
end
end --RNum_Par
function p.ZeroOrPosNum_Par (Args, ParId, Default, LimSup)
if p.Error.yes then return end
local N, IsDefault = p.Num_Par (Args, ParId, Default, 0, LimSup)
if IsNone(N) then return p.None end
if p.Error.yes then return end
if not IsDefault then
p.CheckNumIsZeroOrPos (N, ParId)
if p.Error.yes then return end
end
return N
end --ZeroOrPosNum_Par
function p.RZeroOrPosNum_Par (Args, ParId, LimSup)
if p.Error.yes then return end
local N = p.ZeroOrPosNum_Par (Args, ParId, nil, LimSup)
if p.Error.yes then return end
if N == nil then
p.NotAssignedValue (ParId)
else
return N
end
end --RZeroOrPosNum_Par
function p.Int_Par (Args, ParId, Default, LimInf, LimSup)
N, IsDefault = p.Num_Par (Args, ParId, Default, LimInf, LimSup)
if IsNone(N) then return p.None end
if p.Error.yes then return end
if not IsDefault then
p.CheckNumIsInt (N, ParId)
if p.Error.yes then return end
end
return N
end --Int_Par
function p.RInt_Par (Args, ParId, LimInf, LimSup)
if p.Error.yes then return end
local N = p.Int_Par (Args, ParId, nil, LimInf, LimSup)
if p.Error.yes then return end
if N == nil then
p.NotAssignedValue (ParId)
else
return N, true
end
end --RInt_Par
function p.PosInt_Par (Args, ParId, Default, LimInf, LimSup)
if p.Error.yes then return end
local N = p.Int_Par (Args, ParId, Default, LimInf, LimSup)
if IsNone(N) then return p.None end
if p.Error.yes then return end
if N ~= nil then
p.CheckNumIsPos (N, ParId)
if p.Error.yes then return end
end
return N
end --PosInt_Par
function p.RPosInt_Par (Args, ParId, LimInf, LimSup)
if p.Error.yes then return end
local N = p.PosInt_Par (Args, ParId, nil, LimInf, LimSup)
if p.Error.yes then return end
if N == nil then
p.NotAssignedValue (ParId)
else
return N, false
end
end --RPosInt_Par
function p.ZeroOrPosInt_Par (Args, ParId, Default, LimSup)
if p.Error.yes then return end
local N = p.Int_Par (Args, ParId, Default, 0, LimSup)
if IsNone(N) then return p.None end
if p.Error.yes then return end
if N ~= nil then
p.CheckNumIsZeroOrPos (N, ParId)
if p.Error.yes then return end
end
return N
end --ZeroOrPosInt_Par
function p.RZeroOrPosInt_Par (Args, ParId, LimSup)
if p.Error.yes then return end
local N = p.ZeroOrPosInt_Par (Args, ParId, nil, LimSup)
if p.Error.yes then return end
if N == nil then
p.NotAssignedValue (ParId)
else
return N, true
end
end --RZeroOrPosInt_Par
---
local function PossibleValues (tab)
local S = ''
for _, W in ipairs(tab) do
if S ~='' then
S = S..', '
end
local tab = {}
tab2 = p.I18nParamsTabCS (i18n[W])
S = S..table.concat (tab2, p.ParaSep)
end
return I18nStr (RS.PossibleValues, S)
end --PossibleValues
---
function p.CheckSize (CurCol, width) --used in XCols
local val = string.match (width, '%d[%d.,]*')
if val == nil then
ParamErrorS (CurCol, I18nStr (RS.SizeWithoutNumber))
else
local unit = string.sub (width, #val+1)
if unit == '' then
ParamErrorS (CurCol, I18nStr (RS.SizeUnitRequired))
elseif (unit ~= '%') and (unit ~= 'em') and (unit ~= 'px') then
ParamErrorS (CurCol, I18nStr (RS.InvalSizeUnit, unit))
end
end
end --CheckSize
function p.Size_Par (Args, ParId, WithPerc, limits, Default)
if p.Error.yes then return end
local width = p.Str_Par (Args, ParId, Default)
if p.Error.yes then return end
if p.HasValue (width) then
local val = string.match (width, '%d[%d.,]*')
if val == nil then
ParamErrorS (ParId, I18nStr (RS.SizeWithoutNumber))
else
local unit = string.sub (width, #val+1)
if unit == '' then
ParamErrorS (ParId, I18nStr (RS.SizeUnitRequired))
elseif (not WithPerc) and (unit == '%') then
ParamErrorS (ParId, I18nStr (RS.InvalSizeUnit, unit))
elseif (unit ~= '%') and (unit ~= 'em') and (unit ~= 'px') then
ParamErrorS (ParId, I18nStr (RS.InvalSizeUnit, unit))
elseif limits ~= nil then
checked = false
val = tonumber (val)
function Check (sel_lim, sel_unit)
if (not checked) and (sel_lim ~= nil) and (unit == sel_unit) then
if ((sel_lim[1] ~= nil) and (val < sel_lim[1])) or ((sel_lim[2] ~= nil) and (val > sel_lim[2])) then
ParamErrorS (ParId, I18nStr (RS.NIsNotInRange, width, sel_lim[1]..sel_unit, sel_lim[2]..sel_unit))
end
checked = true
end
end
Check (limits['em'], 'em')
Check (limits['px'], 'px')
if WithPerc then
Check (limits['perc'], '%')
end
end
end
end
return width
end --Size_Par
function p.RSize_Par (Args, ParId, WithPerc, limits)
if p.Error.yes then return end
local width = p.Size_Par (Args, ParId, WithPerc, limits)
if p.Error.yes then return end
if width == nil then
p.NotAssignedValue (ParId)
else
return width
end
end --RSize_Par
p.Colors = {
-- Pink colors
["pink"] = 'FFC0CB', -- Pink
["lightpink"] = 'FFB6C1', -- LightPink
["hotpink"] = 'FF69B4', -- HotPink
["deeppink"] = 'FF1493', -- DeepPink
["palevioletred"] = 'DB7093', -- PaleVioletRed
["mediumvioletred"] = 'C71585', -- MediumVioletRed
-- Red colors
["lightsalmon"] = 'FFA07A', -- LightSalmon
["salmon"] = 'FA8072', -- Salmon
["darksalmon"] = 'E9967A', -- DarkSalmon
["lightcoral"] = 'F08080', -- LightCoral
["indianred"] = 'CD5C5C', -- IndianRed
["crimson"] = 'DC143C', -- Crimson
["firebrick"] = 'B22222', -- Firebrick
["darkred"] = '8B0000', -- DarkRed
["red"] = 'FF0000', -- Red
-- Orange colors
["orangered"] = 'FF4500', -- OrangeRed
["tomato"] = 'FF6347', -- Tomato
["coral"] = 'FF7F50', -- Coral
["darkorange"] = 'FF8C00', -- DarkOrange
["orange"] = 'FFA500', -- Orange
-- Yellow colors
["yellow"] = 'FFFF00', -- Yellow
["lightyellow"] = 'FFFFE0', -- LightYellow
["lemonchiffon"] = 'FFFACD', -- LemonChiffon
["lightgoldenrodyellow"] = 'FAFAD2', -- LightGoldenrodYellow
["papayawhip"] = 'FFEFD5', -- PapayaWhip
["moccasin"] = 'FFE4B5', -- Moccasin
["peachpuff"] = 'FFDAB9', -- PeachPuff
["palegoldenrod"] = 'EEE8AA', -- PaleGoldenrod
["khaki"] = 'F0E68C', -- Khaki
["darkkhaki"] = 'BDB76B', -- DarkKhaki
["gold"] = 'FFD700', -- Gold
-- Brown colors
["cornsilk"] = 'FFF8DC', -- Cornsilk
["blanchedalmond"] = 'FFEBCD', -- BlanchedAlmond
["bisque"] = 'FFE4C4', -- Bisque
["navajowhite"] = 'FFDEAD', -- NavajoWhite
["wheat"] = 'F5DEB3', -- Wheat
["burlywood"] = 'DEB887', -- Burlywood
["tan"] = 'D2B48C', -- Tan
["rosybrown"] = 'BC8F8F', -- RosyBrown
["sandybrown"] = 'F4A460', -- SandyBrown
["goldenrod"] = 'DAA520', -- Goldenrod
["darkgoldenrod"] = 'B8860B', -- DarkGoldenrod
["peru"] = 'CD853F', -- Peru
["chocolate"] = 'D2691E', -- Chocolate
["saddlebrown"] = '8B4513', -- SaddleBrown
["sienna"] = 'A0522D', -- Sienna
["brown"] = 'A52A2A', -- Brown
["maroon"] = '800000', -- Maroon
-- Green colors
["darkolivegreen"] = '556B2F', -- DarkOliveGreen
["olive"] = '808000', -- Olive
["olivedrab"] = '6B8E23', -- OliveDrab
["yellowgreen"] = '9ACD32', -- YellowGreen
["limegreen"] = '32CD32', -- LimeGreen
["lime"] = '00FF00', -- Lime
["lawngreen"] = '7CFC00', -- LawnGreen
["chartreuse"] = '7FFF00', -- Chartreuse
["greenyellow"] = 'ADFF2F', -- GreenYellow
["springgreen"] = '00FF7F', -- SpringGreen
["mediumspringgreen"] = '00FA9A', -- MediumSpringGreen
["lightgreen"] = '90EE90', -- LightGreen
["palegreen"] = '98FB98', -- PaleGreen
["darkseagreen"] = '8FBC8F', -- DarkSeaGreen
["mediumaquamarine"] = '66CDAA', -- MediumAquamarine
["mediumseagreen"] = '3CB371', -- MediumSeaGreen
["seagreen"] = '2E8B57', -- SeaGreen
["forestgreen"] = '228B22', -- ForestGreen
["green"] = '008000', -- Green
["darkgreen"] = '006400', -- DarkGreen
-- Cyan colors
["aqua"] = '00FFFF', -- Aqua
["cyan"] = '00FFFF', -- Cyan
["lightcyan"] = 'E0FFFF', -- LightCyan
["paleturquoise"] = 'AFEEEE', -- PaleTurquoise
["aquamarine"] = '7FFFD4', -- Aquamarine
["turquoise"] = '40E0D0', -- Turquoise
["mediumturquoise"] = '48D1CC', -- MediumTurquoise
["darkturquoise"] = '00CED1', -- DarkTurquoise
["lightseagreen"] = '20B2AA', -- LightSeaGreen
["cadetblue"] = '5F9EA0', -- CadetBlue
["darkcyan"] = '008B8B', -- DarkCyan
["teal"] = '008080', -- Teal
-- Blue colors
["lightsteelblue"] = 'B0C4DE', -- LightSteelBlue
["powderblue"] = 'B0E0E6', -- PowderBlue
["lightblue"] = 'ADD8E6', -- LightBlue
["skyblue"] = '87CEEB', -- SkyBlue
["lightskyblue"] = '87CEFA', -- LightSkyBlue
["deepskyblue"] = '00BFFF', -- DeepSkyBlue
["dodgerblue"] = '1E90FF', -- DodgerBlue
["cornflowerblue"] = '6495ED', -- CornflowerBlue
["steelblue"] = '4682B4', -- SteelBlue
["royalblue"] = '4169E1', -- RoyalBlue
["blue"] = '0000FF', -- Blue
["mediumblue"] = '0000CD', -- MediumBlue
["darkblue"] = '00008B', -- DarkBlue
["navy"] = '000080', -- Navy
["midnightblue"] = '191970', -- MidnightBlue
-- Purple, violet, and magenta colors
["lavender"] = 'E6E6FA', -- Lavender
["thistle"] = 'D8BFD8', -- Thistle
["plum"] = 'DDA0DD', -- Plum
["violet"] = 'EE82EE', -- Violet
["orchid"] = 'DA70D6', -- Orchid
["fuchsia"] = 'FF00FF', -- Fuchsia
["magenta"] = 'FF00FF', -- Magenta
["mediumorchid"] = 'BA55D3', -- MediumOrchid
["mediumpurple"] = '9370DB', -- MediumPurple
["blueviolet"] = '8A2BE2', -- BlueViolet
["darkviolet"] = '9400D3', -- DarkViolet
["darkorchid"] = '9932CC', -- DarkOrchid
["darkmagenta"] = '8B008B', -- DarkMagenta
["purple"] = '800080', -- Purple
["indigo"] = '4B0082', -- Indigo
["darkslateblue"] = '483D8B', -- DarkSlateBlue
["slateblue"] = '6A5ACD', -- SlateBlue
["mediumslateblue"] = '7B68EE', -- MediumSlateBlue
-- White colors
["white"] = 'FFFFFF', -- White
["snow"] = 'FFFAFA', -- Snow
["honeydew"] = 'F0FFF0', -- Honeydew
["mintcream"] = 'F5FFFA', -- MintCream
["azure"] = 'F0FFFF', -- Azure
["aliceblue"] = 'F0F8FF', -- AliceBlue
["ghostwhite"] = 'F8F8FF', -- GhostWhite
["whitesmoke"] = 'F5F5F5', -- WhiteSmoke
["seashell"] = 'FFF5EE', -- Seashell
["beige"] = 'F5F5DC', -- Beige
["oldlace"] = 'FDF5E6', -- OldLace
["floralwhite"] = 'FFFAF0', -- FloralWhite
["ivory"] = 'FFFFF0', -- Ivory
["antiquewhite"] = 'FAEBD7', -- AntiqueWhite
["linen"] = 'FAF0E6', -- Linen
["lavenderblush"] = 'FFF0F5', -- LavenderBlush
["mistyrose"] = 'FFE4E1', -- MistyRose
-- Gray and black colors
["gainsboro"] = 'DCDCDC', -- Gainsboro
["lightgray"] = 'D3D3D3', -- LightGray
["silver"] = 'C0C0C0', -- Silver
["darkgray"] = 'A9A9A9', -- DarkGray
["gray"] = '808080', -- Gray
["dimgray"] = '696969', -- DimGray
["lightslategray"] = '778899', -- LightSlateGray
["slategray"] = '708090', -- SlateGray
["darkslategray"] = '2F4F4F', -- DarkSlateGray
["black"] = '000000', -- Black
}
function p.ColorToHex (frame)
local args = p.GetArgs (frame)
return p.RColor_Par (args, 1)
end
local function GetRValue (rgb)
-- Red color
return tonumber (string.sub(rgb,1,2), 16)
end
local function GetGValue(rgb)
-- Green color
return tonumber (string.sub(rgb,3,4), 16)
end
local function GetBValue(rgb)
-- BLue color
return tonumber (string.sub(rgb,5,6), 16)
end
function p.CheckSIsColor (S, ParId, Default)
-- Returns if is valid and the color in format NNNNNN i.e.
-- for S == 'Green' returns true,'008000'
-- for S == '#008000' returns true,'008000'
function SixCharsFromCol (Col)
if Col == nil then
return nil
else
function NumColor (Col)
if string.len (Col) ~= 6 then
ParamError (ParId, RS.InvalColorLength, Col)
end
if tonumber ('0x'..Col) == nil then
ParamError (ParId, RS.InvalColorChar, Col)
end
end
if string.sub (Col, 1, 5) == '#' then
Col = string.sub (Col, 6)
NumColor (Col)
elseif string.sub (Col, 1, 1) == '#' then
Col = string.sub (Col, 2)
NumColor (Col)
else
local ColI = Col
local rgbn = string.lower (Col)
Col = p.Colors[rgbn]
if Col == nil then
ParamError (ParId, RS.InvalColorName, ColI)
end
end
if p.Error.yes then
return nil
else
return Col
end
end
end -- SixCharsFromCol
if p.Error.yes then return end
if S == nil then
S = Default
return SixCharsFromCol (S)
end
if S == nil then
return nil
else
return SixCharsFromCol (S)
end
end --CheckSIsColor
function p.Color_Par (Args, ParId, Default)
if p.Error.yes then return end
local rgb = p.Str_Par (Args, ParId)
if p.Error.yes then return end
return p.CheckSIsColor (rgb, ParId, Default)
end --Color_Par
function p.RColor_Par (Args, ParId, Default)
if p.Error.yes then return end
local rgb = p.RStr_Par (Args, ParId)
if p.Error.yes then return end
return p.CheckSIsColor (rgb, ParId)
end --Color_Par
---
function p.HAlign_Par (Args, ParId, Default)
local HAlign = {
RS.left,
RS.right,
RS.center,
}
if p.Error.yes then return end
local align = p.Str_Par (Args, ParId)
if p.Error.yes then return end
if (align == nil) or (align == '') then
return Default
else
local Idx = p.IdxFromWdTab (i18n, align, true, HAlign)
if Idx == 0 then
ParamErrorS (ParId, I18nStr (RS.InvalAlign,align)..'. '..PossibleValues(HAlign))
else
return HAlign[Idx]
end
end
end --HAlign_Par
function p.RHAlign_Par (Args, ParId)
if p.Error.yes then return end
local align = p.HAlign_Par (Args, ParId)
if p.Error.yes then return end
if align == nil then
p.NotAssignedValue (ParId)
else
return align
end
end --RHAlign_Par
---
function p.VAlign_Par (Args, ParId, Default)
local VAlign = {
RS.top,
RS.bottom,
RS.center,
}
if p.Error.yes then return end
local align = p.Str_Par (Args, ParId)
if p.Error.yes then return end
if (align == nil) or (align == '') then
return Default
else
local Idx = p.IdxFromWdTab (i18n, align, true, VAlign)
if Idx == 0 then
ParamErrorS (ParId, I18nStr (RS.InvalAlign,align)..'. '..PossibleValues(VAlign))
else
return VAlign[Idx]
end
end
end --VAlign_Par
function p.RVAlign_Par (Args, ParId)
if p.Error.yes then return end
local align = p.VAlign_Par (Args, ParId)
if p.Error.yes then return end
if align == nil then
p.NotAssignedValue (ParId)
else
return align
end
end --RVAlign_Par
---
function p.Bool_Par (Args, ParId, Default)
local yesno = {
RS.Yes,
RS.No,
}
if p.Error.yes then return end
local B = p.Str_Par (Args, ParId)
if IsNone(N) then return p.None end
if p.Error.yes then return end
if (B == nil) or (B == '') then
return Default
else
local Idx = p.IdxFromWdTab (i18n, B, true, yesno)
if Idx == 0 then
ParamErrorS (ParId, I18nStr (RS.InvalBool,B)..'. '..PossibleValues(yesno))
elseif Idx == 1 then
return true
elseif Idx == 2 then
return false
end
end
end --Bool_Par
function p.RBool_Par (Args, ParId)
if p.Error.yes then return end
local B = p.Bool_Par (Args, ParId)
if p.Error.yes then return end
if B == nil then
p.NotAssignedValue (ParId)
else
return B
end
end --RBool_Par
---
function SFoundInArr (val, CaseSens, ParId)
found = false
if type(ParId) == 'table' then
for _, W in ipairs(ParId) do
if val == PerhapsLow(CaseSens, W) then
found = true
break
end
end
else
if val == PerhapsLow(CaseSens, ParId) then
found = true
end
end
return found
end --SFoundInArr
local function StrIdxChkTab0 (val, CaseSens, Default, ...)
if p.Error.yes then return end
if arg == nil then
error('Not parameters trying to find "'..W..'"') --It doesn't require translation, only for degug
end
local Idx = 0
if not p.Error.yes then
if not CaseSens then
val = string.lower(val)
end
local tab = unpack(arg)
for I, W in ipairs(tab) do
if SFoundInArr (val, CaseSens, W) then
Idx = I
break
end
end
if (Idx == 0) and (Default ~= nil) then
Idx = Default
end
end
if p.Error.yes then
return p.MsgError()
else
return Idx
end
end --StrIdxChkTab0
function p.StrIdxChkTab (Args, ParId, CaseSens, Default, ...)
if p.Error.yes then return end
local W = p.Str_Par (Args, ParId, Default)
local Idx = StrIdxChkTab0 (W, CaseSens, Default, arg)
if p.Error.yes then
return p.MsgError()
else
return Idx
end
end--StrIdxChkTab
function p.RStrIdxChkTab (Args, ParId, CaseSens, ...)
if p.Error.yes then return end
local W = p.RStr_Par (Args, ParId)
local Idx = StrIdxChkTab0 (W, CaseSens, nil, arg)
if p.Error.yes then
return p.MsgError()
else
return Idx
end
end --RStrIdxChkTab
local function IdxOrNotFound (ParId, W, Idx, ...)
local Err = {}
if Idx == 0 then
local tab = unpack(arg)
for _, Wd in ipairs(tab) do
if type(Wd) == 'table' then
table.insert (Err, table.concat(Wd,p.ParaSep))
else
table.insert (Err, Wd)
end
end
ParamErrorS (ParId, I18nStr (RS.SNotFoundInTab, W, table.concat(Err,', ')))
else
return Idx
end
end --IdxOrNotFound
function p.StrIdxChkTabE (Args, ParId, CaseSens, Default, ...)
if p.Error.yes then return end
local W = p.Str_Par (Args, ParId, Default)
local Idx = StrIdxChkTab0 (W, CaseSens, Default, arg)
if p.Error.yes then
return p.MsgError()
else
return IdxOrNotFound (ParId, W, Idx, arg)
end
end--StrIdxChkTabE
function p.RStrIdxChkTabE (Args, ParId, CaseSens, ...)
if p.Error.yes then return end
local W = p.RStr_Par (Args, ParId)
local Idx = StrIdxChkTab0 (W, CaseSens, nil, arg)
if p.Error.yes then
return p.MsgError()
else
return IdxOrNotFound (ParId, W, Idx, arg)
end
end --RStrIdxChkTabE
-----
local function InRange (Num, ParId, MinItemNum, MaxItemNum)
out = ((MinItemNum ~= nil) and (Num < MinItemNum)) or ((MaxItemNum ~= nil) and (Num > MaxItemNum))
if out then
if MaxItemNum ~= nil then
ParamErrorS (ParId, I18nStr (RS.STabIsNotInRange, Num, tostring(MinItemNum), tostring(MaxItemNum)))
else
ParamErrorS (ParId, I18nStr (RS.STabFewItems, Num, tostring(MinItemNum)))
end
end
return not out
end--InRange
function p.StrTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
if Sep == nil then
error ('Undefined items separator') -- Don't translate, it ies only for debug
end
if OnEmpty == nil then
OnEmpty = 2 --set an empty value error
end
local tab = mw.text.split (p.Str_Par (Args, ParId), Sep)
if p.Error.yes then return end
if InRange (#tab, ParId, MinItemNum, MaxItemNum) then
for I, W in ipairs(tab) do
tab[I] = mw.text.trim (tab[I])
end
if OnEmpty == 0 then
return tab
elseif OnEmpty == 1 then
local tab2 = {}
for _, W in ipairs(tab) do
if W ~= '' then
table.insert (tab2, W)
end
end
return tab2
else
for _, W in ipairs(tab) do
if W == '' then
ParamError (ParId, RS.EmptyValue)
end
end
return tab
end
end
end --StrTab_1Par
function p.NumTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
tab = p.StrTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, OnEmpty)
if p.Error.yes then return end
for I, W in ipairs(tab) do
if W ~= nil then
local J = tonumber(W)
if not J then
ParamError (ParId, RS.SIsNotNumber, W)
return tab
else
p.CheckNum (J, Pos, LimInf, LimSup)
if p.Error.yes then return end
tab[I] = J
end
end
end
return tab
end --NumTab_1Par
function p.PosNumTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
tab = p.NumTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
for _, W in ipairs(tab) do
if W ~= nil then
p.CheckNumIsPos (W, ParId)
end
if p.Error.yes then return end
end
return tab
end --ZeroOrPosNumTab_1Par
function p.ZeroOrPosNumTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
tab = p.NumTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
for _, W in ipairs(tab) do
if W ~= nil then
p.CheckNumIsZeroOrPos (W, ParId)
end
if p.Error.yes then return end
end
return tab
end --ZeroOrPosNumTab_1Par
function p.IntTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
tab = p.NumTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
for _, W in ipairs(tab) do
if W ~= nil then
p.CheckNumIsInt (W, ParId)
end
if p.Error.yes then return end
end
return tab
end--IntTab_1Par
function p.PosIntTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
tab = p.IntTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
for _, W in ipairs(tab) do
if W ~= nil then
p.CheckNumIsPos (W, ParId)
end
if p.Error.yes then return end
end
return tab
end --PosIntTab_1Par
function p.ZeroOrPosIntTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
tab = p.IntTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
for _, W in ipairs(tab) do
if W ~= nil then
p.CheckNumIsZeroOrPos (W, ParId)
end
if p.Error.yes then return end
end
return tab
end --ZeroOrPosIntTab_1Par
--------
function p.StrTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, OnEmpty)
local tab = {}
if OnEmpty == nil then
OnEmpty = 2 --set an empty value error
end
function IncInTab (val)
val = mw.text.trim(val)
if OnEmpty == 0 then
if val ~= '' then
table.insert(tab,val)
end
elseif OnEmpty == 1 then
table.insert(tab,val)
else
if val == '' then
ParamError (ParId, RS.EmptyValue)
else
table.insert(tab,val)
end
end
end
if p.Error.yes then return end
if type(ParId) == 'number' then
if ParId == 1 then
for _, v in ipairs(Args) do
IncInTab (v)
if p.Error.yes then return end
end
else
for k = ParId, NArgs do
local S = Args[k]
IncInTab (S)
if p.Error.yes then return end
end
end
elseif type(ParId) == 'string' then
found = false
local Pos = 1
while not found do
local key = string.format (ParId, Pos)
for k, v in pairs(Args) do
if k == key then
IncInTab (v)
if p.Error.yes then return end
found = true
break
end
end
if not found then
break
end
found = false
Pos = Pos + 1
end
elseif type(ParId) == 'table' then
found = false
local Pos = 1
while not found do
for _, b in ipairs(ParId) do
local key = string.format (b, Pos)
for k, v in pairs(Args) do
if k == key then
IncInTab (v)
if p.Error.yes then return end
found = true
break
end
end
if found then
break
end
end
if not found then
break
end
found = false
Pos = Pos + 1
end
end
InRange (#tab, ParId, MinItemNum, MaxItemNum)
return tab, #tab
end --StrTab_NPar
function p.NumTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
local tab = p.StrTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, OnEmpty)
if p.Error.yes then return end
local Pos = ParId
for I, W in ipairs(tab) do
if W ~= nil then
local J = tonumber(W)
if not J then
ParamError (Pos, RS.SIsNotNumber, W)
else
p.CheckNum (J, Pos, LimInf, LimSup)
if p.Error.yes then return end
tab[I] = J
end
end
Pos = Pos + 1
end
return tab
end --NumTab_NPar
function p.PosNumTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
local tab = p.NumTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
local Pos = ParId
for _, W in ipairs(tab) do
if W ~= nil then
p.CheckNumIsPos (W, Pos)
end
if p.Error.yes then return end
Pos = Pos + 1
end
return tab
end --PosNumTab_NPar
function p.ZeroOrPosNumTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
local tab = p.NumTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
local Pos = ParId
for _, W in ipairs(tab) do
if W ~= nil then
p.CheckNumIsZeroOrPos (W, Pos)
end
if p.Error.yes then return end
Pos = Pos + 1
end
return tab
end --ZeroOrPosNumTab_NPar
function p.IntTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
local tab = p.NumTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
local Pos = ParId
for _, W in ipairs(tab) do
if W ~= nil then
p.CheckSIsInt (W, Pos)
end
if p.Error.yes then return end
Pos = Pos + 1
end
return tab
end --IntTab_NPar
function p.PosIntTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
local tab = p.IntTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
local Pos = ParId
for _, W in ipairs(tab) do
if W ~= nil then
p.CheckNumIsPos (W, Pos)
end
if p.Error.yes then return end
Pos = Pos + 1
end
return tab
end --PosIntTab_NPar
function p.ZeroOrPosIntTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
local tab = p.IntTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
if p.Error.yes then return end
local Pos = ParId
for _, W in ipairs(tab) do
if W ~= nil then
p.CheckNumIsZeroOrPos (W, Pos)
end
if p.Error.yes then return end
Pos = Pos + 1
end
return tab
end --ZeroOrPosIntTab_NPar
----------
function p.TemplateName(frame)
local S = frame:getParent():getTitle()
return string.sub(S, string.find(S,':')+1)
end
function p.MainTemplateName(frame)
local S = p.TemplateName(frame)
return string.sub (S, 1, #S - S:reverse():find("/"))
end
local function CheckIsStrNotEmpty (v, S)
if v == '' then
error ('"'..S..'" has not assigned value') -- Translation not required
else
return v
end
end --CheckIsStrNotEmpty
function p.CheckIsStr (v, S)
if type(v) == "string" then
return CheckIsStrNotEmpty (v, S)
elseif type(v) == nil then
error ('Not found item for "'..S..'"') -- Translation not required
else
SD.vtos (v)
error ('"'..SD.s..'" (for "'..S..'") is not a string') -- Translation not required
end
end --CheckIsStr
local function WhenNoStrOrTab (v, S)
SD.vtos (v)
error ('"'..SD.s..'" (for "'..S..'") is not a string/table') -- Translation not required
end
function p.CheckIsStrOrTab (v, S)
--It does not allow empty strings
if type(v) == "string" then
return CheckIsStrNotEmpty (v, S)
elseif type(v) == "table" then
for _, vv in ipairs(v) do
if type(vv) == "string" then
CheckIsStrNotEmpty (vv, S)
end
end
return v
else
WhenNoStrOrTab (v, S)
end
end --CheckIsStrOrTab
function p.CheckIsAnyStrOrTab (v, S)
--It allows empty strings
if (type(v) == "string") or (type(v) == "table") then
return v
else
WhenNoStrOrTab (v, S)
end
end --CheckIsAnyStrOrTab
----------------------------------------
function p.rgbToHex(rgb) --not used
local hexadecimal = '#'
for key, value in ipairs(rgb) do
local hex = ''
if (value < 0) or (value > 255) then
error ('Invalid color number: '..value)
end
while value > 0 do
local index = math.fmod(value, 16) + 1
value = math.floor (value/16)
hex = string.sub('0123456789ABCDEF', index, index) .. hex
end
if string.len(hex) == 0 then
hex = '00'
elseif string.len(hex) == 1 then
hex = '0' .. hex
end
hexadecimal = hexadecimal .. hex
end
return hexadecimal
end --p.rgbToHex
function p._ReverseColor0 (rgb) --not used
return p.rgbToHex ({255-GetRValue(rgb), 255-GetGValue(rgb), 255-GetBValue(rgb)});
end
function p._ReverseColor (rgb)
-- rgb is a string with 6 characters in format NNNNNN i.e. '008000'
-- (Better contrast than _ReverseColor0 for some colors: i.g. grey)
local BreakGrey = 150
local BreakColor = 180
local RValue = GetRValue (rgb)
local BValue = GetBValue (rgb)
local GValue = GetGValue (rgb)
if (RValue < BreakGrey) and (GValue < BreakGrey) and (BValue < BreakGrey) then
return 'White'
elseif (RValue >= BreakGrey) and (GValue >= BreakGrey) and (BValue >= BreakGrey) then
return 'Black'
elseif (RValue > BreakColor) and (GValue > BreakColor) then
return 'Blue'
elseif (RValue > BreakColor) and (BValue > BreakColor) then
return 'Green'
elseif (GValue > BreakColor) and (BValue > BreakColor) then
return 'Red'
elseif (RValue > BreakColor) then
return 'Aqua' --Blue + Green
elseif (GValue > BreakColor) then
return 'Fuchsia' --Red + Blue
elseif (BValue > BreakColor) then
return 'Yellow' --Red + Green
else
return 'White'
end
end --_ReverseColor
function p.ReverseColor (frame)
local args = p.GetArgs (frame)
local color = p.RColor_Par (args, 1)
return p._ReverseColor (color)
end --ReverseColor
function p._color_black_contrast (color)
local colors = {
GetRValue(color),
GetGValue(color),
GetBValue(color),
}
local dif = math.max (colors[1], colors[2], colors[3]) - math.min (colors[1], colors[2], colors[3])
local val = 0.28*colors[1] + 0.64*colors[2] + 0.08*colors[3]
local to_subtract = math.abs(dif-255)
local to_dif = 128-math.abs(val-128)
local to_subtract2 = to_subtract * to_dif * 0.002
local res = math.floor ((val - to_subtract2) + 0.5)
return res
end --_color_black_contrast
function p.color_black_contrast (frame)
-- Determine the luminosity of a color, with some corrections for grays,
-- for the background of an overlay text, in part from:
-- https://www.johndcook.com/blog/2009/08/24/algorithms-convert-color-grayscale/
local args = p.GetArgs (frame)
local color = p.RColor_Par (args, 1)
return p._color_black_contrast (color)
end --color_black_contrast
function p._txtcolor_for_bg (rgb)
if p._color_black_contrast (rgb) < 90 then
return 'white'
else
return 'black'
end
end --_txtcolor_for_bg
function p.txtcolor_for_bg (frame)
-- For better readability, determine whether the color of the letters
-- should be white or black
-- depending on the background color.
local args = p.GetArgs (frame)
local color = p.RColor_Par (args, 1)
return p._txtcolor_for_bg (color)
end --txtcolor_for_bg
----------------------------------------
return p