Modul:TemplateData: Unterschied zwischen den Versionen
2018-03-30
wp>PerfektesChaos (2018-03-12) |
wp>PerfektesChaos (2018-03-30) |
||
Zeile 1: | Zeile 1: | ||
local TemplateData = { suite = "TemplateData", | local TemplateData = { suite = "TemplateData", | ||
serial = "2018-03- | serial = "2018-03-30", | ||
item = 46997995 } | item = 46997995 } | ||
--[=[ | --[=[ | ||
Zeile 77: | Zeile 77: | ||
newlines = "*", | newlines = "*", | ||
spaced = "inline" }, | spaced = "inline" }, | ||
colors = { tableheadbg | colors = { tableheadbg = "B3B7FF", | ||
required | required = "EAF3FF", | ||
suggested | suggested = "FFFFFF", | ||
optional | optional = "EAECF0", | ||
deprecated | deprecated = "FFCBCB" }, | ||
params = { aliases = "table", | params = { aliases = "table", | ||
autovalue = "string", | autovalue = "string", | ||
default = "string table I18N nowiki", | default = "string table I18N nowiki", | ||
deprecated = "boolean string", | deprecated = "boolean string I18N", | ||
description = "string table I18N", | description = "string table I18N", | ||
example = "string table I18N nowiki", | example = "string table I18N nowiki", | ||
Zeile 91: | Zeile 91: | ||
inherits = "string", | inherits = "string", | ||
required = "boolean", | required = "boolean", | ||
style = "string table", | |||
suggested = "boolean", | suggested = "boolean", | ||
type = "string" }, | type = "string" }, | ||
Zeile 137: | Zeile 138: | ||
-- Parameter: | -- Parameter: | ||
-- ask -- string, with name | -- ask -- string, with name | ||
-- "/global" | |||
-- "Multilingual" | -- "Multilingual" | ||
-- "Text" | -- "Text" | ||
Zeile 142: | Zeile 144: | ||
-- Returns table of module | -- Returns table of module | ||
-- error: Module not available | -- error: Module not available | ||
local r | local sign = ask | ||
local r, stem | |||
if sign:sub( 1, 1 ) == "/" then | |||
sign = TemplateData.frame:getTitle() .. sign | |||
else | |||
stem = sign | |||
sign = "Module:" .. stem | |||
end | |||
if TemplateData.extern then | if TemplateData.extern then | ||
r = TemplateData.extern[ | r = TemplateData.extern[ sign ] | ||
else | else | ||
TemplateData.extern = { } | TemplateData.extern = { } | ||
end | end | ||
if not r then | if not r then | ||
local lucky, g = pcall( require, | local lucky, g = pcall( require, sign ) | ||
if type( g ) == "table" then | if type( g ) == "table" then | ||
r = g[ | if stem and type( g[ stem ] ) == "function" then | ||
TemplateData.extern[ | r = g[ stem ]() | ||
else | |||
r = g | |||
end | |||
TemplateData.extern[ sign ] = r | |||
else | else | ||
error( string.format( "Fetch(%s) %s", | error( string.format( "Fetch(%s) %s", sign, g ) ) | ||
end | end | ||
end | end | ||
Zeile 375: | Zeile 388: | ||
end -- for k, v | end -- for k, v | ||
if not r1 then | if not r1 then | ||
local others = mw.language.getFallbacksFor( slang ) | local others = mw.language.getFallbacksFor( Data.slang ) | ||
table.insert( others, "en" ) | table.insert( others, "en" ) | ||
for i = 1, #others do | for i = 1, #others do | ||
Zeile 401: | Zeile 414: | ||
local Multilingual = Fetch( "Multilingual" ) | local Multilingual = Fetch( "Multilingual" ) | ||
for k, v in pairs( r2 ) do | for k, v in pairs( r2 ) do | ||
if v and not Multilingual.isLang( k ) then | if v and not Multilingual.isLang( k ) | ||
and k ~= "simple" then | |||
Fault( string.format( "Invalid <code>lang=%s</code>", | Fault( string.format( "Invalid <code>lang=%s</code>", | ||
k ) ) | k ) ) | ||
Zeile 413: | Zeile 427: | ||
local function | local function fashioned( about, asked, assign ) | ||
-- | -- Create description head | ||
-- Parameter: | |||
-- about -- table, supposed to contain description | |||
-- asked -- true, if mandatory description | |||
-- assign -- <block>, if to be equipped | |||
-- Returns <block>, with head, or nil | |||
local para = assign or mw.html.create( "div" ) | |||
local plus, r | |||
if about and about.description then | |||
if type( about.description ) == "string" then | |||
para:wikitext( about.description ) | |||
else | |||
para:wikitext( about.description[ 1 ] ) | |||
plus = mw.html.create( "ul" ) | |||
for k, v in pairs( about.description[ 2 ] ) do | |||
plus:node( mw.html.create( "li" ) | |||
:node( mw.html.create( "code" ) | |||
:wikitext( k ) ) | |||
:node( mw.html.create( "br" ) ) | |||
:wikitext( fair( v ) ) ) | |||
end -- for k, v | |||
if Config.loudly then | |||
plus = mw.html.create( "div" ) | |||
:css( "background-color", | |||
"#" .. Config.debugmultilang ) | |||
:node( plus ) | |||
else | |||
plus:addClass( "templatedata-maintain" ) | |||
:css( "display", "none" ) | |||
end | end | ||
end | end | ||
elseif Config.solo and asked then | |||
para:addClass( "error" ) | |||
:wikitext( Config.solo ) | |||
Data.less = true | |||
else | |||
para = false | |||
end | |||
if para then | |||
if plus then | |||
r = mw.html.create( "div" ) | |||
:node( para ) | |||
end | :node( plus ) | ||
else | |||
r = para | |||
end | |||
end | end | ||
end -- | return r | ||
end -- fashioned() | |||
local function | local function fatten( access ) | ||
-- | -- Create table row for sub-headline | ||
local | -- Parameter: | ||
local | -- access -- string, with name | ||
-- Returns <tr> | |||
local | local param = Data.tree.params[ access ] | ||
local sub, sort = access:match( "(=+)%s*(%S.*)$" ) | |||
if | local headline = mw.html.create( string.format( "h%d", #sub ) ) | ||
local r = mw.html.create( "tr" ) | |||
local td = mw.html.create( "td" ) | |||
:attr( "colspan", "5" ) | |||
:attr( "data-sort-value", "!" .. sort ) | |||
local s | |||
if param.style then | |||
s = type( param.style ) | |||
if s == "table" then | |||
td:css( param.style ) | |||
elseif s == "string" then | |||
td:cssText( param.style ) | |||
end | |||
end | |||
s = fashioned( param, false, headline ) | |||
if s then | |||
headline = s | |||
else | else | ||
headline:wikitext( sort ) | |||
end | end | ||
td:node( headline ) | |||
r:node( td ) | |||
return r | |||
end -- fatten() | |||
local function fathers() | |||
for k, v in pairs( | -- Merge params with inherited values | ||
local n = 0 | |||
local p = Data.params | |||
local t = Data.tree.params | |||
local p2, t2 | |||
for k, v in pairs( Data.heirs ) do | |||
n = n + 1 | |||
end -- for k, v | end -- for k, v | ||
for i = 1, n do | |||
for k, v in pairs( Data.heirs ) do | |||
if v and not Data.heirs[ v ] then | |||
if | n = n - 1 | ||
t[ k ].inherits = nil | |||
Data.heirs[ k ] = nil | |||
end | p2 = { } | ||
if | t2 = { } | ||
for k2, v2 in pairs( p[ v ] ) do | |||
p2[ k2 ] = v2 | |||
end -- for k2, v2 | |||
if p[ k ] then | |||
for k2, v2 in pairs( p[ k ] ) do | |||
if type( v2 ) ~= "nil" then | |||
p2[ k2 ] = v2 | |||
end | |||
end -- for k2, v2 | |||
end | end | ||
p[ k ] = p2 | |||
for k2, v2 in pairs( t[ v ] ) do | |||
for | t2[ k2 ] = v2 | ||
if type( | end -- for k2, v2 | ||
for k2, v2 in pairs( t[ k ] ) do | |||
if type( v2 ) ~= "nil" then | |||
t2[ k2 ] = v2 | |||
end | end | ||
end -- for k | end -- for k2, v2 | ||
t[ k ] = t2 | |||
end | end | ||
end | end -- for k, v | ||
for k, v in pairs( | end -- i = 1, n | ||
s = | if n > 0 then | ||
local s | |||
for k, v in pairs( Data.heirs ) do | |||
if v then | |||
if s then | |||
s = string.format( "%s | %s", s, k ) | |||
else | |||
s = "Circular inherits: " .. k | |||
end | |||
end | end | ||
end -- for k, v | end -- for k, v | ||
Fault( s ) | |||
end | end | ||
end -- | end -- fathers() | ||
local function | local function favorize() | ||
-- | -- Local customization issues | ||
local boole = { ["font-size"] = "125%" } | |||
local l, cx = pcall( mw.loadData, | |||
TemplateData.frame:getTitle() .. "/config" ) | |||
local scripting | |||
TemplateData.ltr = not mw.language.getContentLanguage():isRTL() | |||
local | if TemplateData.ltr then | ||
if | scripting = "left" | ||
else | |||
scripting = "right" | |||
end | |||
boole[ "margin-" .. scripting ] = "3em" | |||
Permit.boole = { [false] = { css = boole, | |||
lead = true, | |||
show = "☐" }, | |||
[true] = { css = boole, | |||
lead = true, | |||
show = "☑" } } | |||
Permit.css = { } | |||
for k, v in pairs( Permit.colors ) do | |||
if k == "tableheadbg" then | |||
k = "tablehead" | |||
end | end | ||
Permit.css[ k ] = { ["background-color"] = "#" .. v } | |||
end -- for k, v | |||
if type( cx ) == "table" then | |||
local c, s | |||
if type( cx.permit ) == "table" then | |||
if type( cx.permit.boole ) == "table" then | |||
if type( cx.permit.boole[ true ] ) == "table" then | |||
Permit.boole[ false ] = cx.permit.boole[ false ] | |||
end | |||
if type( cx.permit.boole[ true ] ) == "table" then | |||
Permit.boole[ true ] = cx.permit.boole[ true ] | |||
end | |||
end | |||
if type( cx.permit.css ) == "table" then | |||
for k, v in pairs( cx.permit.css ) do | |||
if type( v ) == "table" then | |||
Permit.css[ k ] = v | |||
end | |||
end -- for k, v | |||
end | |||
end | |||
for k, v in pairs( Config.basicCnf ) do | |||
s = type( cx[ k ] ) | |||
if s == "string" or s == "table" then | |||
Config[ v ] = cx[ k ] | |||
end | |||
end -- for k, v | |||
end | end | ||
if | if type( Config.subpage ) ~= "string" or | ||
type( Config.suffix ) ~= "string" then | |||
local got = mw.message.new( "templatedata-doc-subpage" ) | |||
local suffix | |||
if got:isDisabled() then | |||
suffix = "doc" | |||
else | else | ||
suffix = got:plain() | |||
end | |||
if type( Config.subpage ) ~= "string" then | |||
Config.subpage = string.format( "/%s$", suffix ) | |||
end | |||
if type( Config.suffix ) ~= "string" then | |||
Config.suffix = string.format( "%%s/%s", suffix ) | |||
end | end | ||
end | end | ||
end -- favorize() | |||
end -- | |||
Zeile 704: | Zeile 769: | ||
-- description etc. | -- description etc. | ||
s = | s = fashioned( param ) | ||
if s then | if s then | ||
desc:node( s ) | desc:node( s ) | ||
end | |||
if param.style then | |||
s = type( param.style ) | |||
if s == "table" then | |||
desc:css( param.style ) | |||
elseif s == "string" then | |||
desc:cssText( param.style ) | |||
end | |||
end | end | ||
if param.default or param.example or param.autovalue then | if param.default or param.example or param.autovalue then | ||
Zeile 838: | Zeile 911: | ||
local r | local r | ||
if Data.tree and Data.tree.params then | if Data.tree and Data.tree.params then | ||
local tbl | local tbl = mw.html.create( "table" ) | ||
:addClass( "wikitable" ) | |||
local tr | local tr = mw.html.create( "tr" ) | ||
feat() | feat() | ||
if Data.order and #Data.order > 1 then | if Data.order and #Data.order > 1 then | ||
Zeile 875: | Zeile 948: | ||
:newline() | :newline() | ||
if Data.order then | if Data.order then | ||
local leave, s | |||
for i = 1, #Data.order do | for i = 1, #Data.order do | ||
tbl:node( | s = Data.order[ i ] | ||
if s:sub( 1, 1 ) == "=" then | |||
leave = true | |||
tbl:node( fatten( s ) ) | |||
Data.order[ i ] = false | |||
else | |||
tbl:node( feature( s ) ) | |||
end | |||
end -- for i = 1, #Data.order | end -- for i = 1, #Data.order | ||
if leave then | |||
for i = #Data.order, 1, -1 do | |||
if not Data.order[ i ] then | |||
table.remove( Data.order, i ) | |||
end | |||
end -- for i = #Data.order, 1, -1 | |||
end | |||
Data.tag.paramOrder = Data.order | |||
end | end | ||
if Config.cssTabWrap then | if Config.cssTabWrap or Data.scroll then | ||
r = mw.html.create( "div" ) | r = mw.html.create( "div" ) | ||
if type( Config.cssTabWrap ) == "table" then | if type( Config.cssTabWrap ) == "table" then | ||
Zeile 886: | Zeile 975: | ||
-- deprecated | -- deprecated | ||
r:cssText( Config.cssTabWrap ) | r:cssText( Config.cssTabWrap ) | ||
end | |||
if Data.scroll then | |||
r:css( "height", Data.scroll ) | |||
:css( "overflow", "auto" ) | |||
end | end | ||
r:node( tbl ) | r:node( tbl ) | ||
Zeile 1.052: | Zeile 1.145: | ||
if s == "string" then | if s == "string" then | ||
elem = fair( v ) | elem = fair( v ) | ||
elseif s == "table" then | |||
local translated | local translated | ||
v, translated = faraway( v ) | v, translated = faraway( v ) | ||
Zeile 1.067: | Zeile 1.160: | ||
end | end | ||
end | end | ||
if v then | if type( v ) == "string" then | ||
if scope:find( "nowiki", 1, true ) then | if k == "deprecated" then | ||
if v == "1" then | |||
v = true | |||
elseif v == "0" then | |||
v = false | |||
end | |||
elem = v | |||
elseif scope:find( "nowiki", 1, true ) then | |||
elem = mw.text.nowiki( v ) | elem = mw.text.nowiki( v ) | ||
else | else | ||
Zeile 1.088: | Zeile 1.188: | ||
Data.heirs[ slot ] = v | Data.heirs[ slot ] = v | ||
v = nil | v = nil | ||
elseif k == "style" then | |||
elem = v | |||
v = nil | |||
elseif s == "string" then | elseif s == "string" then | ||
v = mw.text.nowiki( v ) | v = mw.text.nowiki( v ) | ||
Zeile 1.114: | Zeile 1.217: | ||
if not tag then | if not tag then | ||
if access then | if access then | ||
if not Data.params then | if type( v ) == "string" and | ||
Data.params = { } | v.sub( 1, 1 ) == "=" then | ||
v = nil | |||
else | |||
if not Data.params then | |||
Data.params = { } | |||
end | |||
Data.params[ slot ] = { } | |||
tag = Data.params[ slot ] | |||
end | end | ||
else | else | ||
Data.tag = { } | Data.tag = { } | ||
Zeile 1.124: | Zeile 1.232: | ||
end | end | ||
end | end | ||
tag[ k ] = v | if type( v ) ~= "nil" then | ||
tag[ k ] = v | |||
end | |||
end | end | ||
else | else | ||
Zeile 1.307: | Zeile 1.417: | ||
-- Returns <div> | -- Returns <div> | ||
local r = mw.html.create( "div" ) | local r = mw.html.create( "div" ) | ||
local | local x = fashioned( Data.tree, true, r ) | ||
if | local s | ||
r | if x then | ||
r = x | |||
end | end | ||
if Data.leading then | if Data.leading then | ||
Zeile 1.318: | Zeile 1.429: | ||
toc:css( "margin-top", "0.5em" ) | toc:css( "margin-top", "0.5em" ) | ||
:wikitext( "__TOC__" ) | :wikitext( "__TOC__" ) | ||
if Data.sibling then | |||
local block = mw.html.create( "div" ) | |||
local shift | |||
if TemplateData.ltr then | |||
shift = "right" | |||
else | |||
shift = "left" | |||
end | |||
block:css( "float", shift ) | |||
:wikitext( Data.sibling ) | |||
r:newline() | |||
:node( block ) | |||
end | |||
r:newline() | r:newline() | ||
:node( toc ) | :node( toc ) | ||
Zeile 1.330: | Zeile 1.454: | ||
end | end | ||
r:node( s ) | r:node( s ) | ||
end | |||
if Data.shared then | |||
local global = mw.html.create( "div" ) | |||
local shift | |||
if TemplateData.ltr then | |||
shift = "right" | |||
else | |||
shift = "left" | |||
end | |||
global:css( "float", shift ) | |||
:wikitext( string.format( "[[%s|%s]]", | |||
Data.shared, "Global" ) ) | |||
r:newline() | |||
:node( global ) | |||
end | end | ||
if Data.tree and Data.tree.format then | if Data.tree and Data.tree.format then | ||
Zeile 1.389: | Zeile 1.527: | ||
Data.div:node( div ) | Data.div:node( div ) | ||
end | end | ||
end | |||
if Data.lasting then | |||
Fault( "deprecated type syntax" ) | |||
end | |||
if Data.less then | |||
Fault( Config.solo ) | |||
end | end | ||
end -- full() | end -- full() | ||
Zeile 1.400: | Zeile 1.544: | ||
-- arglist -- table, template parameters | -- arglist -- table, template parameters | ||
-- Returns string | -- Returns string | ||
local source | local source | ||
favorize() | favorize() | ||
Zeile 1.410: | Zeile 1.553: | ||
end -- for k, v | end -- for k, v | ||
Config.loudly = faculty( arglist.debug or adapt.debug ) | Config.loudly = faculty( arglist.debug or adapt.debug ) | ||
Data.lazy = faculty( arglist.lazy ) and not Config.loudly | Data.lazy = faculty( arglist.lazy ) and not Config.loudly | ||
Data.leading = faculty( arglist.TOC ) | Data.leading = faculty( arglist.TOC ) | ||
if Data.leading and arglist.TOCsibling then | |||
Data.sibling = mw.text.trim( arglist.TOCsibling ) | |||
end | |||
if arglist.JSON then | if arglist.JSON then | ||
source = arglist.JSON | source = arglist.JSON | ||
elseif arglist.Global then | |||
source = TemplateData.getGlobalJSON( arglist.Global ) | |||
elseif arglist[ 1 ] then | elseif arglist[ 1 ] then | ||
local s = mw.text.trim( arglist[ 1 ] ) | local s = mw.text.trim( arglist[ 1 ] ) | ||
Zeile 1.433: | Zeile 1.578: | ||
elseif adapt.lang then | elseif adapt.lang then | ||
Data.slang = adapt.lang:lower() | Data.slang = adapt.lang:lower() | ||
end | |||
if type( arglist.vertical ) == "string" and | |||
arglist.vertical:match( "^%d*%.?%d+[emprx]+$" ) then | |||
Data.scroll = arglist.vertical | |||
end | end | ||
if not source then | if not source then | ||
Zeile 1.438: | Zeile 1.587: | ||
source = find() | source = find() | ||
if not source and | if not source and | ||
not Data.title.text:match( Config.subpage ) then | not Data.title.text:match( Config.subpage ) then | ||
local s = string.format( Config.suffix, | local s = string.format( Config.suffix, | ||
Zeile 1.447: | Zeile 1.595: | ||
end | end | ||
end | end | ||
end | end | ||
if not Data.lazy | if not Data.lazy then | ||
if not Data.title then | if not Data.title then | ||
Data.title = mw.title.getCurrentTitle() | Data.title = mw.title.getCurrentTitle() | ||
Zeile 1.460: | Zeile 1.602: | ||
Data.lazy = Data.title.text:match( Config.subpage ) | Data.lazy = Data.title.text:match( Config.subpage ) | ||
end | end | ||
TemplateData.getPlainJSON( source ) | if type( source ) == "string" then | ||
TemplateData.getPlainJSON( source ) | |||
end | |||
return finalize( faculty( arglist.source ) ) | return finalize( faculty( arglist.source ) ) | ||
end -- furnish() | end -- furnish() | ||
Zeile 1.473: | Zeile 1.616: | ||
-- or false | -- or false | ||
-- Postcondition: | -- Postcondition: | ||
-- Returns string with appropriate version, or false | -- Returns string with appropriate version, or false | ||
local since = assert | local since = assert | ||
local r | local r | ||
if since == "wikidata" then | if since == "wikidata" then | ||
local item = TemplateData.item | local item = TemplateData.item | ||
since = false | since = false | ||
if type( item ) == "number" and item > 0 then | if type( item ) == "number" and item > 0 then | ||
local entity = mw.wikibase.getEntity( string.format( "Q%d", | local entity = mw.wikibase.getEntity( string.format( "Q%d", | ||
item ) ) | item ) ) | ||
if type( entity ) == "table" then | if type( entity ) == "table" then | ||
local vsn = entity:formatPropertyValues( "P348" ) | local vsn = entity:formatPropertyValues( "P348" ) | ||
if type( vsn ) == "table" and | if type( vsn ) == "table" and | ||
type( vsn.value) == "string" and | type( vsn.value) == "string" and | ||
vsn.value ~= "" then | vsn.value ~= "" then | ||
r = vsn.value | r = vsn.value | ||
end | end | ||
end | end | ||
end | end | ||
end | end | ||
if not r then | if not r then | ||
if not since or since <= TemplateData.serial then | if not since or since <= TemplateData.serial then | ||
r = TemplateData.serial | r = TemplateData.serial | ||
else | |||
r = false | |||
end | |||
end | |||
return r | |||
end -- TemplateData.failsafe() | |||
TemplateData.getGlobalJSON = function ( access ) | |||
-- Retrieve JSON from a global repository | |||
-- Parameter: | |||
-- access -- string, with page specifier (on WikiMedia Commons) | |||
-- Returns true, if succeeded | |||
local plugin = Fetch( "/global" ) | |||
local r | |||
if type( plugin ) == "table" and | |||
type( plugin.fetch ) == "function" then | |||
local s, got = plugin.fetch( access ) | |||
if got then | |||
Data.got = got | |||
Data.order = got.paramOrder | |||
Data.shared = s | |||
r = true | |||
full() | |||
else | else | ||
Fault( s ) | |||
end | end | ||
end | end | ||
return r | return r | ||
end -- TemplateData. | end -- TemplateData.getGlobalJSON() | ||
Zeile 1.516: | Zeile 1.684: | ||
if lucky then | if lucky then | ||
full() | full() | ||
elseif not Data.strip then | elseif not Data.strip then | ||
Fault( "fatal JSON error: " .. Data.got ) | Fault( "fatal JSON error: " .. Data.got ) |