Modul:TemplatePar: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
update
wp>Leyo K (Schützte „Modul:TemplatePar“: Häufig eingebundenes Modul ([Bearbeiten=Nur angemeldete, nicht neue Benutzer] (unbeschränkt) [Verschieben=Nur Administratoren] (unbeschränkt))) |
wp>PerfektesChaos (update) |
||
Zeile 1: | Zeile 1: | ||
--[=[ TemplatePar 2013- | --[=[ TemplatePar 2013-05-03 | ||
Template parameter utility | Template parameter utility | ||
* check | * check | ||
* count | * count | ||
* valid | |||
* TemplatePar() | |||
]=] | ]=] | ||
Zeile 8: | Zeile 10: | ||
-- Module globals | -- Module globals | ||
local | local TemplatePar = { } | ||
local messagePrefix = "lua-module-TemplatePar-" | |||
local l10nDef = {} | local l10nDef = {} | ||
l10nDef[ "en" ] = { | l10nDef[ "en" ] = { | ||
dupOpt | dupOpt = "TemplatePar#invoke: repeated optional parameter", | ||
empty | empty = "Error in template: undefined value for mandatory", | ||
undefined = "Error in template: mandatory parameter missing", | invalid = "Error in template: invalid parameter", | ||
unknown | invalidPar = "TemplatePar#invoke: invalid parameter", | ||
noname = "TemplatePar#invoke: missing parameter name", | |||
tooLong = "Error in template: parameter too long", | |||
tooShort = "Error in template: parameter too short", | |||
undefined = "Error in template: mandatory parameter missing", | |||
unknown = "Error in template: unknown parameter name", | |||
unknownRule = "TemplatePar#invoke: unknown rule" | |||
} | } | ||
l10nDef[ "de" ] = { | l10nDef[ "de" ] = { | ||
dupOpt | dupOpt = "TemplatePar#invoke: Optionsparameter wiederholt", | ||
empty | empty = "Fehler bei Vorlage: Pflichtparameter ohne Wert", | ||
undefined = "Fehler bei Vorlage: | invalid = "Fehler bei Vorlage: Parameter ungültig", | ||
unknown | invalidPar = "TemplatePar#invoke: Ungültiger Parameter", | ||
noname = "TemplatePar#invoke: Parametername nicht angegeben", | |||
tooLong = "Fehler bei Vorlage: Parameter zu lang", | |||
tooShort = "Fehler bei Vorlage: Parameter zu kurz", | |||
undefined = "Fehler bei Vorlage: Pflichtparameter fehlt", | |||
unknown = "Fehler bei Vorlage: Parametername unbekannt", | |||
unknownRule = "TemplatePar#invoke: Unbekannte Regel" | |||
} | } | ||
local Patterns = { | |||
[ "ASCII" ] = "^[ -~]*$", | |||
[ "ASCII+" ] = "^[ -~]+$", | |||
[ "ASCII+1" ] = "^[!-~]+$", | |||
[ "n" ] = "^%-?[0-9]*$", -- einzelnes Minus ausschließen | |||
[ "n>0" ] = "^[0-9]*[1-9][0-9]*$", | |||
[ "N+" ] = "^%-?[1-9][0-9]*$", | |||
[ "N>0" ] = "^[1-9][0-9]*$", | |||
[ "x" ] = "^[0-9A-Fa-f]*$", | |||
[ "x+" ] = "^[0-9A-Fa-f]+$", | |||
[ "X" ] = "^[0-9A-F]*$", | |||
[ "X+" ] = "^[0-9A-F]+$", | |||
[ "+" ] = "%S" | |||
} | |||
function trim( s ) | |||
-- Trim string | |||
-- Precondition: | |||
-- s -- string or nil; to be trimmed | |||
-- Postcondition: | |||
-- Return trimmed string or nil | |||
local r = s | |||
if type( s ) == "string" then | |||
if s:match( "^%s*$" ) then | |||
r = "" | |||
else | |||
r = s:match( "^%s*(%S.*)$" ) | |||
r = r:match( "^(.*%S)%s*$" ) | |||
end | |||
end | |||
return r | |||
end -- trim() | |||
local function factory( say ) | |||
-- Retrieve localized message string in content language | |||
-- Precondition: | |||
-- say -- string; message ID | |||
-- Postcondition: | |||
-- Return some message string | |||
-- Uses: | |||
-- > messagePrefix | |||
-- > l10nDef | |||
local c = mw.language.getContentLanguage():getCode() | |||
local m = mw.message.new( messagePrefix .. say ) | |||
local r = false | |||
if m:isBlank() then | |||
local l10n = l10nDef[ c ] | |||
if not l10n then | |||
l10n = l10nDef[ "en" ] | |||
end | |||
r = l10n[ say ] | |||
else | |||
m:inLanguage( c ) | |||
r = m:plain() | |||
end | |||
if not r then | |||
r = "(((".. say .. ")))" | |||
end | |||
return r | |||
end -- factory() | |||
local function | local function failure( spec, suspect, options ) | ||
-- Submit error message | -- Submit localized error message | ||
-- Precondition: | -- Precondition: | ||
-- spec -- string; message ID | -- spec -- string; message ID | ||
-- suspect -- string or nil; additional information | -- suspect -- string or nil; additional information | ||
-- options -- table or nil; optional details | |||
-- options.template | |||
-- Postcondition: | -- Postcondition: | ||
-- Return string | -- Return string | ||
-- Uses: | -- Uses: | ||
-- | -- factory() | ||
local r = factory( spec ) | |||
local r | if type( options ) == "table" then | ||
if type( options.template ) == "string" then | |||
if #options.template > 0 then | |||
r = r .. " (" .. options.template .. ")" | |||
end | |||
end | |||
end | end | ||
if suspect then | if suspect then | ||
Zeile 50: | Zeile 127: | ||
end | end | ||
return r | return r | ||
end -- | end -- failure() | ||
Zeile 97: | Zeile 174: | ||
local function fetch() | local function fetch() | ||
-- Return regular table with template parameters | -- Return regular table with all template transclusion parameters | ||
-- Postcondition: | -- Postcondition: | ||
-- Return table; whitespace-only values as false | -- Return table; whitespace-only values as false | ||
-- Uses: | -- Uses: | ||
-- | -- mw.getCurrentFrame() | ||
-- frame:getParent() | -- frame:getParent() | ||
local k, v | local k, v | ||
local r = { } | local r = { } | ||
local t = | local t = mw.getCurrentFrame():getParent() | ||
local o = t.args | local o = t.args | ||
for k, v in pairs( o ) do | for k, v in pairs( o ) do | ||
Zeile 122: | Zeile 199: | ||
return r | return r | ||
end -- fetch() | end -- fetch() | ||
Zeile 165: | Zeile 223: | ||
return r | return r | ||
end -- fill() | end -- fill() | ||
local function finalize( submit, options ) | |||
-- Finalize message | |||
-- Precondition: | |||
-- submit -- string or false or nil; non-empty error message | |||
-- options -- table or nil; optional details | |||
-- options.noError | |||
-- options.cat | |||
-- options.template | |||
-- Postcondition: | |||
-- Return string or false | |||
local r = false | |||
if submit then | |||
local opt, s | |||
if type( options ) == "table" then | |||
opt = options | |||
else | |||
opt = { } | |||
end | |||
if opt.noError then | |||
r = false | |||
else | |||
r = "<span class='error'>" .. submit .. "</span>" | |||
end | |||
s = opt.cat | |||
if type( s ) == "string" then | |||
if not r then | |||
r = "" | |||
end | |||
if s:find( "@@@" ) then | |||
if type( opt.template ) == "string" then | |||
s = s:gsub( "@@@", opt.template ) | |||
end | |||
end | |||
r = r .. "[[Category:" .. s .. "]]" | |||
end | |||
end | |||
return r | |||
end -- finalize() | |||
Zeile 231: | Zeile 330: | ||
local function fix( valid, duty ) | local function fix( valid, duty, options ) | ||
-- Perform parameter analysis | -- Perform transclusion parameter analysis | ||
-- Precondition: | -- Precondition: | ||
-- valid | -- valid -- table; unique sequence of known parameters | ||
-- duty | -- duty -- table; sequence of mandatory parameters | ||
-- options -- table or nil; optional details | |||
-- Postcondition: | -- Postcondition: | ||
-- Return string as configured; empty if valid | -- Return string as configured; empty if valid | ||
-- Uses: | -- Uses: | ||
-- fetch() | -- fetch() | ||
-- finder() | -- finder() | ||
-- fault() | -- fault() | ||
-- | -- failure() | ||
-- fed() | -- fed() | ||
local k, v | local k, v | ||
Zeile 254: | Zeile 353: | ||
end -- for k, v | end -- for k, v | ||
if r then | if r then | ||
r = | r = failure( "unknown", r, options ) | ||
else -- all names valid | else -- all names valid | ||
local i, s | local i, s | ||
for i = 1, #duty do | for i = 1, #duty do | ||
Zeile 265: | Zeile 363: | ||
end -- for i | end -- for i | ||
if r then | if r then | ||
r = | r = failure( "undefined", r, options ) | ||
else | else -- all mandatory present | ||
for i = 1, #duty do | for i = 1, #duty do | ||
s = duty[ i ] | s = duty[ i ] | ||
Zeile 274: | Zeile 372: | ||
end -- for i | end -- for i | ||
if r then | if r then | ||
r = | r = failure( "empty", r, options ) | ||
end | end | ||
end | end | ||
end | end | ||
if r | return r | ||
end -- fix() | |||
r = "" | |||
local function format( seek, options ) | |||
-- Check validity of one particular template parameter | |||
-- Precondition: | |||
-- seek -- string non-empty; name of template parameter | |||
-- options -- table or nil; optional details | |||
-- options.pattern | |||
-- options.key | |||
-- options.min | |||
-- options.max | |||
-- Postcondition: | |||
-- Return string with error message as configured; | |||
-- false if valid or no answer permitted | |||
-- Uses: | |||
-- > Patterns | |||
-- failure() | |||
-- mw.ustring.match() | |||
-- frame:getParent() | |||
local r = false | |||
local s | |||
local scan = false | |||
local story = mw.getCurrentFrame():getParent() | |||
story = ( story.args[ seek ] or "" ) | |||
if type( options.pattern ) == "string" then | |||
if options.key then | |||
r = failure( "duplicatedRule", false, options ) | |||
else | |||
scan = options.pattern | |||
end | |||
else | |||
if type( options.key ) == "string" then | |||
s = trim( options.key ) | |||
else | else | ||
s = "+" | |||
end | end | ||
scan = Patterns[ s ] | |||
if | if type( scan ) == "string" then | ||
if | if s == "n" then | ||
if trim( story ) == "-" then | |||
scan = false | |||
r = failure( "invalid", | |||
"'" .. seek .. "'", | |||
options ) | |||
end | end | ||
end | end | ||
r = r .. " | else | ||
r = failure( "unknownRule", s, options ) | |||
end | |||
end | |||
if scan then | |||
if not mw.ustring.match( story, scan ) then | |||
r = failure( "invalid", "'" .. seek .. "'", options ) | |||
end | |||
end | |||
if options.min and not r then | |||
if type( options.min ) == "number" then | |||
if #story < options.min then | |||
r = failure( "tooShort", | |||
" <" .. options.min .. " '" .. seek .. "'", | |||
options ) | |||
end | |||
else | |||
r = failure( "invalidPar", "min", options ) | |||
end | |||
end | |||
if options.max and not r then | |||
if type( options.max ) == "number" then | |||
if #story > options.max then | |||
r = failure( "tooLong", | |||
" >" .. options.max .. " '" .. seek .. "'", | |||
options ) | |||
end | |||
else | |||
r = failure( "invalidPar", "max", options ) | |||
end | end | ||
end | end | ||
return r | return r | ||
end -- | end -- format() | ||
TemplatePar.check = function ( options ) | |||
-- | -- Run parameter analysis | ||
-- Precondition: | |||
-- options -- table or nil; optional details | |||
-- options.mandatory | |||
-- options.optional | |||
-- Postcondition: | -- Postcondition: | ||
-- Return string as configured; | -- Return string with error message as configured; | ||
-- false if valid or no answer permitted | |||
-- Uses: | -- Uses: | ||
-- fit() | -- fit() | ||
-- | -- failure() | ||
-- fix() | -- fix() | ||
local duty | -- finalize() | ||
local duty, r | |||
if type( options ) == "table" then | |||
if type( options.mandatory ) == "table" then | |||
duty = options.mandatory | |||
else | |||
duty = { } | |||
end | |||
if type( options.optional ) ~= "table" then | |||
options.optional = { } | |||
end | |||
r = fit( duty, options.optional ) | |||
else | |||
duty = { } | |||
r = { } | |||
end | |||
if type( r ) == "string" then | if type( r ) == "string" then | ||
r = | r = failure( "dupOpt", r, options ) | ||
else | else | ||
r = fix( r, duty ) | r = fix( r, duty, options ) | ||
end | end | ||
return finalize( r, options ) | |||
end -- TemplatePar.check() | |||
TemplatePar.count = function () | |||
-- Return number of template parameters | |||
-- Postcondition: | |||
-- Return number, starting at 0 | |||
-- Uses: | |||
-- mw.getCurrentFrame() | |||
-- frame:getParent() | |||
local k, v | |||
local r = 0 | |||
local t = mw.getCurrentFrame():getParent() | |||
local o = t.args | |||
for k, v in pairs( o ) do | |||
r = r + 1 | |||
end -- for k, v | |||
return r | return r | ||
end -- | end -- TemplatePar.count() | ||
TemplatePar.valid = function ( seek, options ) | |||
-- Check validity of one particular template parameter | |||
-- Precondition: | |||
-- seek -- string; name of template parameter | |||
-- options -- table or nil; optional details | |||
-- Postcondition: | |||
-- Return string with error message as configured; | |||
-- false if valid or no answer permitted | |||
-- Uses: | |||
-- trim() | |||
-- format() | |||
-- failure() | |||
-- finalize() | |||
local r | |||
if type( seek ) == "string" then | |||
r = trim( seek ) | |||
if #r == 0 then | |||
r = false | |||
end | |||
end | |||
if r then | |||
r = format( seek, options ) | |||
else | |||
r = failure( "noname", false, options ) | |||
end | |||
return finalize( r, options ) | |||
end -- TemplatePar.valid() | |||
-- Provide external access | |||
local p = {} | local p = {} | ||
function p.check( frame ) | function p.check( frame ) | ||
Zeile 336: | Zeile 561: | ||
-- Return string with error message or "" | -- Return string with error message or "" | ||
-- Uses: | -- Uses: | ||
-- | -- fill() | ||
-- | -- TemplatePar.check() | ||
local options = { mandatory = fill( frame.args[ 1 ] ), | |||
return | optional = fill( frame.args[ 2 ] ), | ||
cat = frame.args.cat, | |||
noError = frame.args.noError, | |||
template = frame.args.template | |||
} | |||
return TemplatePar.check( options ) or "" | |||
end -- .check() | end -- .check() | ||
function p.count( frame ) | function p.count( frame ) | ||
-- Count number of template parameters | -- Count number of template parameters | ||
-- Postcondition: | -- Postcondition: | ||
-- Return string with digits including "0" | -- Return string with digits including "0" | ||
-- Uses: | -- Uses: | ||
-- | -- TemplatePar.count() | ||
return tostring( TemplatePar.count() ) | |||
return tostring( | |||
end -- .count() | end -- .count() | ||
function p.valid( frame ) | function p.valid( frame ) | ||
-- Check validity of one template parameter | -- Check validity of one particular template parameter | ||
-- Precondition: | -- Precondition: | ||
-- frame -- object; #invoke environment | -- frame -- object; #invoke environment | ||
Zeile 362: | Zeile 592: | ||
-- Return string with error message or "" | -- Return string with error message or "" | ||
-- Uses: | -- Uses: | ||
-- | -- trim() | ||
-- TemplatePar.valid() | |||
local r = false | |||
local s | |||
local options = { cat = frame.args.cat, | |||
noError = frame.args.noError, | |||
template = frame.args.template | |||
} | |||
s = trim( frame.args[ 2 ] ) | |||
if type( s ) == "string" then | |||
local sub = s:match( "^/(.*%S)/$" ) | |||
if type( sub ) == "string" then | |||
options.pattern = sub | |||
else | |||
options.key = s | |||
end | |||
end | |||
if type( frame.args.min ) == "string" then | |||
s = frame.args.min:match( "^%s*([0-9]+)%s*$" ) | |||
if s then | |||
options.min = tonumber( s ) | |||
else | |||
r = failure( "invalidPar", | |||
"min=" .. frame.args.min, | |||
options ) | |||
end | |||
end | |||
if type( frame.args.max ) == "string" then | |||
s = frame.args.max:match( "^%s*([1-9][0-9]*)%s*$" ) | |||
if s then | |||
options.max = tonumber( s ) | |||
else | |||
r = failure( "invalidPar", | |||
"max=" .. frame.args.max, | |||
options ) | |||
end | |||
end | |||
if r then | |||
r = finalize( r, options ) | |||
else | |||
s = frame.args[ 1 ] or "" | |||
r = TemplatePar.valid( s, options ) or "" | |||
end | |||
return r | |||
end -- .valid() | end -- .valid() | ||
function p.TemplatePar() | |||
-- Retrieve function access for modules | |||
-- Postcondition: | |||
-- Return table with functions | |||
return TemplatePar | |||
end -- .TemplatePar() | |||
return p | return p |