Módulo:SimpleArgs
Uso
Utilizado por otros módulos para comprobación de parámetros pasados.
Plantilla:ForMultilingualTrans
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).
- Plantilla:Tlc -> StrTab_NPar (args, 4, 1} -> {a,b,c}
- Plantilla:Tlc -> StrTab_NPar (args, 4, 1} -> {a,b,c}
- Plantilla:Tlc -> 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).
- Plantilla:Tlc -> StrTab_NPar (args, 4, 2} -> {a,b,c}
- Plantilla:Tlc -> 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