395
Bearbeitungen
wp>PerfektesChaos (2017-05-27) |
K (52 Versionen importiert: Lua) |
||
(34 dazwischenliegende Versionen von 3 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
local TemplateData = { serial = " | local TemplateData = { suite = "TemplateData", | ||
serial = "2018-04-21", | |||
item = 46997995 } | |||
--[=[ | --[=[ | ||
improve template:TemplateData | improve template:TemplateData | ||
Zeile 8: | Zeile 9: | ||
local Config = { | local Config = { | ||
-- multiple | -- multiple option names mapped into unique internal fields | ||
basicCnf = { catProblem = "strange", | |||
-- | classNoNumTOC = "suppressTOCnum", | ||
cssParWrap = "cssTabWrap", | |||
cssParams = "cssTable", | |||
docpageCreate = "suffix", | |||
docpageDetect = "subpage", | |||
helpBoolean = "support4boolean", | |||
helpContent = "support4content", | |||
-- classTable | helpDate = "support4date", | ||
loudly | helpFile = "support4wiki-file-name", | ||
solo | helpFormat = "supportFormat", | ||
strange | helpLine = "support4line", | ||
helpNumber = "support4number", | |||
helpPage = "support4wiki-page-name", | |||
subpage | helpString = "support4string", | ||
suffix | helpTemplate = "support4wiki-template-name", | ||
helpURL = "support4url", | |||
helpUser = "support4wiki-user-name", | |||
msgDescMiss = "solo" }, | |||
-- classParams = "classTable", | |||
-- classTable = false, -- class for params table | |||
debugmultilang = "C0C0C0", | |||
loudly = false, -- show exported element, etc. | |||
solo = false, -- complaint on missing description | |||
strange = false, -- title of maintenance category | |||
cssTable = false, -- styles for params table | |||
cssTabWrap = false, -- styles for params table wrapper | |||
debug = false, | |||
subpage = false, -- pattern to identify subpage | |||
suffix = false, -- subpage creation scheme | |||
suppressTOCnum = false, -- class for TOC number suppression | |||
jsonDebug = "json-code-lint" -- class for jsonDebug tool | |||
} | } | ||
local Data = { | local Data = { | ||
Zeile 38: | Zeile 55: | ||
params = false, -- table, exported parameters | params = false, -- table, exported parameters | ||
scream = false, -- error messages | scream = false, -- error messages | ||
sibling = false, -- TOC juxtaposed | |||
slang = false, -- project language code | slang = false, -- project language code | ||
slim = false, -- JSON reduced to plain | slim = false, -- JSON reduced to plain | ||
Zeile 47: | Zeile 65: | ||
} | } | ||
local Permit = { | local Permit = { | ||
colors = { required = "EAF3FF", | builder = { after = "block", | ||
align = "block", | |||
block = "block", | |||
compressed = "block", | |||
dense = "block", | |||
grouped = "inline", | |||
half = "inline", | |||
indent = "block", | |||
inline = "inline", | |||
last = "block", | |||
lead = "block", | |||
newlines = "*", | |||
spaced = "inline" }, | |||
colors = { tableheadbg = "B3B7FF", | |||
required = "EAF3FF", | |||
suggested = "FFFFFF", | suggested = "FFFFFF", | ||
optional = "EAECF0", | optional = "EAECF0", | ||
deprecated = "FFCBCB | 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 61: | Zeile 92: | ||
inherits = "string", | inherits = "string", | ||
required = "boolean", | required = "boolean", | ||
style = "string table", | |||
suggested = "boolean", | suggested = "boolean", | ||
type = "string" }, | type = "string" }, | ||
Zeile 95: | Zeile 127: | ||
-- alert -- string, error message | -- alert -- string, error message | ||
if Data.scream then | if Data.scream then | ||
string.format( "%s *** %s", Data.scream, alert ) | Data.scream = string.format( "%s *** %s", Data.scream, alert ) | ||
else | else | ||
Data.scream = alert | Data.scream = alert | ||
Zeile 107: | Zeile 139: | ||
-- Parameter: | -- Parameter: | ||
-- ask -- string, with name | -- ask -- string, with name | ||
-- "/global" | |||
-- "Multilingual" | -- "Multilingual" | ||
-- "Text" | -- "Text" | ||
Zeile 112: | Zeile 145: | ||
-- 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 167: | Zeile 211: | ||
-- adapt -- string, message ID after "templatedata-" | -- adapt -- string, message ID after "templatedata-" | ||
-- Returns string, with localized text | -- Returns string, with localized text | ||
local o = mw.message.new( "templatedata-" .. adapt ) | |||
if not Data.slang then | |||
local Multilingual = Fetch( "Multilingual" ) | |||
if type( Multilingual.userLangCode ) == "function" then | |||
Data.slang = Multilingual.userLangCode() | |||
end | |||
end | |||
if Data.slang then | |||
o:inLanguage( Data.slang ) | |||
end | |||
return o:plain() | |||
end -- factory() | end -- factory() | ||
Zeile 247: | Zeile 301: | ||
return r | return r | ||
end -- fair() | end -- fair() | ||
local function fancy( advance, alert ) | |||
-- Present JSON source | |||
-- Parameter: | |||
-- advance -- true, for nice | |||
-- alert -- true, for visible | |||
-- Returns string | |||
local r | |||
if Data.source then | |||
local support = Config.jsonDebug | |||
local css | |||
if advance then | |||
css = { height = "6em", | |||
resize = "vertical" } | |||
r = { [ 1 ] = "syntaxhighlight", | |||
[ 2 ] = Data.source, | |||
lang = "json", | |||
style = table.concat( css, ";" ) } | |||
if alert then | |||
r.class( support ) | |||
end | |||
r = TemplateData.frame:callParserFunction( "#tag", r ) | |||
else | |||
css = { [ "font-size" ] = "77%", | |||
[ "line-height" ] = "1.35" } | |||
if alert then | |||
css.resize = "vertical" | |||
else | |||
css.display = "none" | |||
end | |||
r = mw.html.create( "pre" ) | |||
:addClass( support ) | |||
:css( css ) | |||
:wikitext( mw.text.encode( Data.source ) ) | |||
r = tostring( r ) | |||
end | |||
r = "\n".. r | |||
else | |||
r = "" | |||
end | |||
return r | |||
end -- fancy() | |||
local function faraway( alternatives ) | local function faraway( alternatives ) | ||
-- Retrieve | -- Retrieve best language version from multilingual text | ||
-- Parameter: | -- Parameter: | ||
-- alternatives -- table, to be evaluated | -- alternatives -- table, to be evaluated | ||
Zeile 260: | Zeile 359: | ||
local variants = { } | local variants = { } | ||
local r1, r2 | local r1, r2 | ||
if | if Data.slang and | ||
Data.slang = | mw.ustring.codepoint( Data.slang, 1, 1 ) > 122 then | ||
Data.slang = false | |||
end | end | ||
for k, v in pairs( alternatives ) do | for k, v in pairs( alternatives ) do | ||
Zeile 267: | Zeile 367: | ||
v = mw.text.trim( v ) | v = mw.text.trim( v ) | ||
if v ~= "" then | if v ~= "" then | ||
k = k:lower() | |||
variants[ k ] = v | variants[ k ] = v | ||
n = n + 1 | n = n + 1 | ||
Zeile 273: | Zeile 374: | ||
end -- for k, v | end -- for k, v | ||
if n > 0 then | if n > 0 then | ||
local choices, Multilingual | |||
if n > 1 then | |||
choices = { } | |||
end | |||
for k, v in pairs( variants ) do | for k, v in pairs( variants ) do | ||
if n == 1 then | |||
r1 = v | |||
elseif Data.slang == k then | |||
variants[ k ] = nil | |||
r1 = v | |||
r2 = variants | |||
else | |||
table.insert( choices, k ) | |||
end | end | ||
end -- for k, v | end -- for k, v | ||
if not r1 then | if not r1 then | ||
Multilingual = Fetch( "Multilingual" ) | |||
if type( Multilingual.userLang ) == "function" then | |||
local sel = Multilingual.userLang( choices, | |||
TemplateData.frame ) | |||
r1 = variants[ sel ] | |||
variants[ sel ] = nil | |||
r2 = variants | |||
local | |||
end | end | ||
end | end | ||
if r2 then | if r2 then | ||
Multilingual = Multilingual or 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, true ) then | ||
Fault( string.format( "Invalid <code>lang=%s</code>", | Fault( string.format( "Invalid <code>lang=%s</code>", | ||
k ) ) | k ) ) | ||
Zeile 331: | Zeile 411: | ||
return r1, r2 | return r1, r2 | ||
end -- faraway() | end -- faraway() | ||
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 | |||
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 ) | |||
:node( plus ) | |||
else | |||
r = para | |||
end | |||
end | |||
return r | |||
end -- fashioned() | |||
local function fatten( access ) | |||
-- Create table row for sub-headline | |||
-- Parameter: | |||
-- access -- string, with name | |||
-- Returns <tr> | |||
local param = Data.tree.params[ access ] | |||
local sub, sort = access:match( "(=+)%s*(%S.*)$" ) | |||
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 | |||
headline:wikitext( sort ) | |||
end | |||
td:node( headline ) | |||
r:node( td ) | |||
return r | |||
end -- fatten() | |||
Zeile 344: | Zeile 511: | ||
end -- for k, v | end -- for k, v | ||
for i = 1, n do | for i = 1, n do | ||
for k, v in pairs( Data.heirs ) do | if Data.heirs then | ||
for k, v in pairs( Data.heirs ) do | |||
if v and not Data.heirs[ v ] then | |||
n = n - 1 | |||
t[ k ].inherits = nil | |||
Data.heirs[ k ] = nil | |||
p2 = { } | |||
t2 = { } | |||
if p[ v ] then | |||
for k2, v2 in pairs( p[ v ] ) do | |||
p2[ k2 ] = v2 | 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 | |||
t2[ k2 ] = v2 | |||
end -- for k2, v2 | |||
for k2, v2 in pairs( t[ k ] ) do | |||
if type( v2 ) ~= "nil" then | |||
t2[ k2 ] = v2 | |||
end | |||
end -- for k2, v2 | |||
t[ k ] = t2 | |||
else | |||
Fault( "No params[] inherits " .. v ) | |||
end | |||
end | end | ||
end -- for k, v | |||
end | |||
end | |||
end -- i = 1, n | end -- i = 1, n | ||
if n > 0 then | if n > 0 then | ||
Zeile 391: | Zeile 564: | ||
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() | |||
if TemplateData.ltr then | |||
if | scripting = "left" | ||
if type( | else | ||
scripting = "right" | |||
end | |||
boole[ "margin-" .. scripting ] = "3em" | |||
Permit.boole = { [false] = { css = boole, | |||
if | 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 | |||
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 | ||
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 564: | Zeile 762: | ||
-- 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 577: | Zeile 783: | ||
if show then | if show then | ||
dd = mw.html.create( "dd" ) | dd = mw.html.create( "dd" ) | ||
section = factory( "doc-param-" .. s ) | section = factory( "doc-param-" .. s ) | ||
if param.type == "boolean" and | if param.type == "boolean" and | ||
( show == "0" or show == "1" ) then | ( show == "0" or show == "1" ) then | ||
local | local boole = Permit.boole[ ( show == "1" ) ] | ||
if boole.lead == true then | |||
dd:node( mw.html.create( "code" ) | |||
:wikitext( show ) ) | |||
if | :wikitext( " " ) | ||
end | |||
if type( boole.show ) == "string" then | |||
local v = mw.html.create( "span" ) | |||
:wikitext( boole.show ) | |||
if boole.css then | |||
v:css( boole.css ) | |||
end | |||
dd:node( v ) | |||
end | |||
if type( boole.suffix ) == "string" then | |||
dd:wikitext( boole.suffix ) | |||
end | |||
if boole.lead == false then | |||
dd:wikitext( " " ) | |||
:node( mw.html.create( "code" ) | |||
:wikitext( show ) ) | |||
end | end | ||
dd: | else | ||
dd:wikitext( show ) | |||
end | end | ||
dl:node( mw.html.create( "dt" ) | dl:node( mw.html.create( "dt" ) | ||
Zeile 614: | Zeile 833: | ||
Data.lasting = true | Data.lasting = true | ||
else | else | ||
local support = Config[ "support4" .. param.type ] | |||
s = factory( "doc-param-type-" .. param.type ) | s = factory( "doc-param-type-" .. param.type ) | ||
if support then | |||
s = string.format( "[[%s|%s]]", support, s ) | |||
end | |||
typed:wikitext( s ) | typed:wikitext( s ) | ||
end | end | ||
Zeile 659: | Zeile 882: | ||
-- <tr> | -- <tr> | ||
r:attr( "id", "templatedata:" .. mw.uri.anchorEncode( access ) ) | r:attr( "id", "templatedata:" .. mw.uri.anchorEncode( access ) ) | ||
:css( | :css( Permit.css[ status ] ) | ||
:node( begin ) | :node( begin ) | ||
:node( code ) | :node( code ) | ||
Zeile 681: | Zeile 904: | ||
local r | local r | ||
if Data.tree and Data.tree.params then | if Data.tree and Data.tree.params then | ||
local tbl = mw.html.create( "table" ) | |||
local tbl | :addClass( "wikitable" ) | ||
local tr = mw.html.create( "tr" ) | |||
local tr | |||
feat() | feat() | ||
if Data.order and #Data.order > 1 then | if Data.order and #Data.order > 1 then | ||
Zeile 692: | Zeile 914: | ||
-- tbl:addClass( Config.classTable ) | -- tbl:addClass( Config.classTable ) | ||
-- end | -- end | ||
if Config. | if Config.cssTable then | ||
tbl:cssText( Config. | if type( Config.cssTable ) == "table" then | ||
tbl:css( Config.cssTable ) | |||
elseif type( Config.cssTable ) == "string" then | |||
-- deprecated | |||
tbl:cssText( Config.cssTable ) | |||
end | |||
end | end | ||
tr:node( mw.html.create( "th" ) | tr:node( mw.html.create( "th" ) | ||
:attr( "colspan", "2" ) | :attr( "colspan", "2" ) | ||
:css( | :css( Permit.css.tablehead ) | ||
:wikitext( factory( "doc-param-name" ) ) ) | :wikitext( factory( "doc-param-name" ) ) ) | ||
:node( mw.html.create( "th" ) | :node( mw.html.create( "th" ) | ||
:css( | :css( Permit.css.tablehead ) | ||
:wikitext( factory( "doc-param-desc" ) ) ) | :wikitext( factory( "doc-param-desc" ) ) ) | ||
:node( mw.html.create( "th" ) | :node( mw.html.create( "th" ) | ||
:css( | :css( Permit.css.tablehead ) | ||
:wikitext( factory( "doc-param-type" ) ) ) | :wikitext( factory( "doc-param-type" ) ) ) | ||
:node( mw.html.create( "th" ) | :node( mw.html.create( "th" ) | ||
:css( | :css( Permit.css.tablehead ) | ||
:wikitext( factory( "doc-param-status" ) ) ) | :wikitext( factory( "doc-param-status" ) ) ) | ||
tbl:newline() | tbl:newline() | ||
-- :node( mw.html.create( "thead" ) | -- :node( mw.html.create( "thead" ) | ||
:node( tr ) | :node( tr ) | ||
-- | -- ) | ||
: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 | |||
elseif s:match( "[=|]" ) then | |||
Fault( string.format( "Bad param <code>%s</code>", | |||
s ) ) | |||
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. | if Config.cssTabWrap or Data.scroll then | ||
r = mw.html.create( "div" ) | r = mw.html.create( "div" ) | ||
if type( Config.cssTabWrap ) == "table" then | |||
r:css( Config.cssTabWrap ) | |||
elseif type( Config.cssTabWrap ) == "string" then | |||
-- deprecated | |||
r:cssText( Config.cssTabWrap ) | |||
end | |||
if Data.scroll then | |||
r:css( "height", Data.scroll ) | |||
:css( "overflow", "auto" ) | |||
end | |||
r:node( tbl ) | |||
else | else | ||
r = tbl | r = tbl | ||
Zeile 731: | Zeile 986: | ||
local function finalize() | local function finalize( advance ) | ||
-- Wrap presentation into frame | -- Wrap presentation into frame | ||
-- Parameter: | |||
-- advance -- true, for nice | |||
-- Returns string | -- Returns string | ||
local r | local r, lapsus | ||
if Data.div then | if Data.div then | ||
r = tostring( Data.div ) | r = tostring( Data.div ) | ||
Zeile 740: | Zeile 997: | ||
r = Data.strip | r = Data.strip | ||
else | else | ||
r = "" | lapsus = true | ||
r = "" | |||
end | |||
r = r .. failures() | |||
if Data.source then | |||
local live = ( advance or lapsus ) | |||
if not live then | |||
live = TemplateData.frame:preprocess( "{{REVISIONID}}" ) | |||
live = ( live == "" ) | |||
end | |||
if live then | |||
r = r .. fancy( advance, lapsus ) | |||
end | |||
end | end | ||
return r | return r | ||
end -- finalize() | end -- finalize() | ||
Zeile 865: | Zeile 1.134: | ||
if scope then | if scope then | ||
s = type( v ) | s = type( v ) | ||
if s == "string" then | if s == "string" and k ~= "format" then | ||
v = mw.text.trim( v ) | v = mw.text.trim( v ) | ||
end | end | ||
Zeile 872: | Zeile 1.141: | ||
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 887: | Zeile 1.156: | ||
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 ) | ||
elem = elem:gsub( " \n", "<br>" ) | |||
v = v:gsub( string.char( 13 ), "" ) | |||
else | else | ||
v = flat( v ) | v = flat( v ) | ||
end | |||
elseif s == "boolean" then | |||
if scope:find( "boolean", 1, true ) then | |||
elem = v | |||
else | |||
s = "Type <code>boolean</code> bad for " | |||
.. f( k, slot ) | |||
Fault( s ) | |||
end | end | ||
end | end | ||
Zeile 899: | Zeile 1.185: | ||
elem = nil | elem = nil | ||
elseif k == "format" and not access then | elseif k == "format" and not access then | ||
elem = mw.text.decode( v ) | |||
v = nil | |||
elseif k == "inherits" then | elseif k == "inherits" then | ||
elem = v | elem = v | ||
Zeile 908: | Zeile 1.194: | ||
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 934: | Zeile 1.223: | ||
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 944: | Zeile 1.238: | ||
end | end | ||
end | end | ||
tag[ k ] = v | if type( v ) ~= "nil" then | ||
tag[ k ] = v | |||
end | |||
end | end | ||
else | else | ||
Zeile 963: | Zeile 1.259: | ||
local function format() | local function format() | ||
-- Build formatted element | |||
-- Returns <inline> | |||
local source = Data.tree.format:lower() | |||
local r, s | |||
if source == "inline" or source == "block" then | |||
r = mw.html.create( "i" ) | |||
:wikitext( source ) | |||
else | |||
local code | |||
if source:find( "|", 1, true ) then | |||
local scan = "^[\n ]*%{%{[\n _]*|[\n _]*=[\n _]*%}%}[\n ]*$" | |||
if source:match( scan ) then | |||
code = source:gsub( "\n", "N" ) | |||
else | |||
s = mw.text.nowiki( source ):gsub( "\n", "\n" ) | |||
s = tostring( mw.html.create( "code" ) | |||
:wikitext( s ) ) | |||
Fault( "Invalid format " .. s ) | |||
source = false | |||
end | |||
else | |||
local words = mw.text.split( source, "%s+" ) | |||
local show, start, support, unknown | |||
for i = 1, #words do | |||
s = words[ i ] | |||
if i == 1 then | |||
start = s | |||
end | |||
support = Permit.builder[ s ] | |||
if support == start or | |||
support == "*" then | |||
Permit.builder[ s ] = true | |||
elseif s:match( "^[1-9]%d?" ) and | |||
Permit.builder.align then | |||
Permit.builder.align = tonumber( s ) | |||
else | |||
if unknown then | |||
unknown = string.format( "%s %s", unknown, s ) | |||
else | |||
unknown = s | |||
end | |||
end | |||
end -- i = 1, #words | |||
if unknown then | |||
s = tostring( mw.html.create( "code" ) | |||
:css( "white-space", "nowrap" ) | |||
:wikitext( s ) ) | |||
Fault( "Unknown/misplaced format keyword " .. s ) | |||
source = false | |||
start = false | |||
end | |||
if start == "inline" then | |||
if Permit.builder.half == true then | |||
show = "inline half" | |||
code = "{{_ |_=_}}" | |||
elseif Permit.builder.grouped == true then | |||
show = "inline grouped" | |||
code = "{{_ | _=_}}" | |||
elseif Permit.builder.spaced == true then | |||
show = "inline spaced" | |||
code = "{{_ | _ = _ }}" | |||
end | |||
if Permit.builder.newlines == true then | |||
show = show .. " newlines" | |||
code = string.format( "N%sN", code ) | |||
end | |||
elseif start == "block" then | |||
local space = "" -- amid "|" and name | |||
local spaced = " " -- preceding "=" | |||
local spacer = " " -- following "=" | |||
local suffix = "N" -- closing "}}" on new line | |||
show = "block" | |||
if Permit.builder.indent == true then | |||
start = " " | |||
show = "block indent" | |||
else | |||
start = "" | |||
end | |||
if Permit.builder.compressed == true then | |||
spaced = "" | |||
spacer = "" | |||
show = show .. " compressed" | |||
if Permit.builder.last == true then | |||
show = show .. " last" | |||
else | |||
suffix = "" | |||
end | |||
else | |||
if Permit.builder.lead == true then | |||
show = show .. " lead" | |||
space = " " | |||
end | |||
if Permit.builder.align then | |||
local n | |||
s = " align" | |||
if Permit.builder.align == true then | |||
n = 0 | |||
if type( Data.got ) == "table" and | |||
type( Data.got.params ) == "table" then | |||
for k, v in pairs( Data.got.params ) do | |||
if type( v ) == "table" and | |||
not v.deprecated and | |||
type( k ) == "string" then | |||
k = mw.ustring.len( k ) | |||
if k > n then | |||
n = k | |||
end | |||
end | |||
end -- for k, v | |||
end | |||
else | |||
n = Permit.builder.align | |||
if type( n ) == "number" and n > 1 then | |||
s = string.format( "%s %d", s, n ) | |||
else | |||
n = 0 -- How comes? | |||
end | |||
end | |||
if n > 1 then | |||
spaced = string.rep( "_", n ) .. " " | |||
end | |||
show = show .. s | |||
elseif Permit.builder.after == true then | |||
spaced = "" | |||
show = show .. " after" | |||
elseif Permit.builder.dense == true then | |||
spaced = "" | |||
spacer = "" | |||
show = show .. " dense" | |||
end | |||
if Permit.builder.last == true then | |||
suffix = spacer | |||
show = show .. " last" | |||
end | |||
end | |||
code = string.format( "N{{_N%s|%s_%s=%s_%s}}N", | |||
start, | |||
space, | |||
spaced, | |||
spacer, | |||
suffix ) | |||
if show == "block" then | |||
show = "block newlines" | |||
end | |||
end | |||
if show then | |||
r = mw.html.create( "span" ) | |||
:wikitext( show ) | |||
end | |||
end | |||
if code then | |||
source = code:gsub( "N", "\n" ) | |||
code = mw.text.nowiki( code ):gsub( "N", "\n" ) | |||
code = mw.html.create( "code" ) | |||
:css( "margin-left", "1em" ) | |||
:css( "margin-right", "1em" ) | |||
:wikitext( code ) | |||
if r then | |||
r = mw.html.create( "span" ) | |||
:node( r ) | |||
:node( code ) | |||
else | |||
r = code | |||
end | |||
end | |||
end | |||
if source then | |||
Data.tag.format = source | |||
end | |||
return r | |||
end -- format() | |||
local function formatter() | |||
-- Build presented documentation | -- Build presented documentation | ||
-- 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 | ||
local toc = mw.html.create( "div" ) | |||
local shift | |||
if Config.suppressTOCnum then | |||
toc:addClass( Config.suppressTOCnum ) | |||
end | |||
toc:css( "margin-top", "0.5em" ) | |||
:wikitext( "__TOC__" ) | |||
if Data.sibling then | |||
local block = mw.html.create( "div" ) | |||
if TemplateData.ltr then | |||
shift = "right" | |||
else | |||
shift = "left" | |||
end | |||
block:css( "float", shift ) | |||
:wikitext( Data.sibling ) | |||
r:newline() | |||
:node( block ) | |||
:newline() | |||
end | |||
r:newline() | r:newline() | ||
: | :node( toc ) | ||
:newline() | :newline() | ||
if shift then | |||
r:node( mw.html.create( "div" ) | |||
:css( "clear", shift ) ) | |||
:newline() | |||
end | |||
end | end | ||
s = features() | s = features() | ||
Zeile 979: | Zeile 1.476: | ||
if Data.leading then | if Data.leading then | ||
r:node( mw.html.create( "h2" ) | r:node( mw.html.create( "h2" ) | ||
:wikitext( factory( "doc-params" ) ) ) | |||
:newline() | :newline() | ||
end | end | ||
r:node( s ) | r:node( s ) | ||
end | |||
if Data.shared then | |||
local global = mw.html.create( "div" ) | |||
:attr( "id", "templatedata-global" ) | |||
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 | ||
local e | local e = format() | ||
if e then | |||
if | local show = "Format" | ||
if Config.supportFormat then | |||
show = string.format( "[[%s|%s]]", | |||
Config.supportFormat, show ) | |||
end | |||
r:node( mw.html.create( "p" ) | |||
:wikitext( show .. ": " ) | |||
:node( e ) ) | |||
end | end | ||
end | end | ||
return r | return r | ||
end -- | end -- formatter() | ||
Zeile 1.025: | Zeile 1.537: | ||
end | end | ||
end | end | ||
Data.div:node( | Data.div:node( formatter() ) | ||
if not Data.lazy then | if not Data.lazy then | ||
Data.slim = flush() | Data.slim = flush() | ||
Zeile 1.042: | Zeile 1.554: | ||
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.053: | Zeile 1.571: | ||
-- arglist -- table, template parameters | -- arglist -- table, template parameters | ||
-- Returns string | -- Returns string | ||
local source | local source | ||
for k, v in pairs( Config ) do | favorize() | ||
-- deprecated: | |||
for k, v in pairs( Config.basicCnf ) do | |||
if adapt[ k ] and adapt[ k ] ~= "" then | if adapt[ k ] and adapt[ k ] ~= "" then | ||
Config[ v ] = adapt[ k ] | Config[ v ] = adapt[ k ] | ||
Zeile 1.061: | Zeile 1.580: | ||
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.lang then | |||
Data.slang = arglist.lang:lower() | |||
elseif adapt.lang then | |||
Data.slang = adapt.lang:lower() | |||
end | |||
if arglist.JSON then | if arglist.JSON then | ||
source = arglist.JSON | source = arglist.JSON | ||
elseif arglist.Global then | |||
source = TemplateData.getGlobalJSON( arglist.Global, | |||
arglist.Local ) | |||
elseif arglist[ 1 ] then | elseif arglist[ 1 ] then | ||
local s = mw.text.trim( arglist[ 1 ] ) | local s = mw.text.trim( arglist[ 1 ] ) | ||
Zeile 1.079: | Zeile 1.606: | ||
Data.strip = s | Data.strip = s | ||
end | end | ||
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.084: | Zeile 1.615: | ||
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.093: | Zeile 1.623: | ||
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.106: | Zeile 1.630: | ||
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 | ||
return finalize() | TemplateData.getPlainJSON( source ) | ||
end | |||
return finalize( faculty( arglist.source ) ) | |||
end -- furnish() | end -- furnish() | ||
Zeile 1.114: | Zeile 1.639: | ||
TemplateData.failsafe = function ( assert ) | TemplateData.failsafe = function ( assert ) | ||
-- Retrieve versioning and check for compliance | |||
-- Precondition: | |||
-- assert -- string, with required version or "wikidata", | |||
-- or false | |||
-- Postcondition: | |||
-- Returns string with appropriate version, or false | |||
local since = assert | |||
local r | local r | ||
if not | if since == "wikidata" then | ||
local item = TemplateData.item | |||
since = false | |||
if type( item ) == "number" and item > 0 then | |||
local entity = mw.wikibase.getEntity( string.format( "Q%d", | |||
item ) ) | |||
if type( entity ) == "table" then | |||
local vsn = entity:formatPropertyValues( "P348" ) | |||
if type( vsn ) == "table" and | |||
type( vsn.value) == "string" and | |||
vsn.value ~= "" then | |||
r = vsn.value | |||
end | |||
end | |||
end | |||
end | |||
if not r then | |||
if not since or since <= TemplateData.serial then | |||
r = TemplateData.serial | |||
else | |||
r = false | |||
end | |||
end | end | ||
return r | return r | ||
end -- TemplateData.failsafe() | end -- TemplateData.failsafe() | ||
TemplateData.getGlobalJSON = function ( access, adapt ) | |||
-- Retrieve TemplateData from a global repository (JSON) | |||
-- Parameter: | |||
-- access -- string, with page specifier (on WikiMedia Commons) | |||
-- adapt -- JSON string or table with local overrides | |||
-- 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, adapt ) | |||
if got then | |||
Data.got = got | |||
Data.order = got.paramOrder | |||
Data.shared = s | |||
r = true | |||
full() | |||
else | |||
Fault( s ) | |||
end | |||
end | |||
return r | |||
end -- TemplateData.getGlobalJSON() | |||
Zeile 1.131: | Zeile 1.707: | ||
-- Returns string, or not | -- Returns string, or not | ||
if type( adapt ) == "string" then | if type( adapt ) == "string" then | ||
local lucky | |||
Data.source = adapt | Data.source = adapt | ||
free() | free() | ||
Data.got = mw.text.jsonDecode | lucky, Data.got = pcall( mw.text.jsonDecode, Data.source ) | ||
if | if lucky then | ||
full() | full() | ||
elseif not Data.strip then | elseif not Data.strip then | ||
Fault( "fatal JSON error" ) | Fault( "fatal JSON error: " .. Data.got ) | ||
end | end | ||
end | end |