Zeile 1: |
Zeile 1: |
| local TemplateData = { suite = "TemplateData", | | local TemplateData = { suite = "TemplateData", |
− | serial = "2018-04-15", | + | serial = "2020-08-23", |
| item = 46997995 } | | item = 46997995 } |
| --[=[ | | --[=[ |
| improve template:TemplateData | | improve template:TemplateData |
| ]=] | | ]=] |
| + | local Failsafe = TemplateData |
| | | |
| | | |
Zeile 28: |
Zeile 29: |
| helpURL = "support4url", | | helpURL = "support4url", |
| helpUser = "support4wiki-user-name", | | helpUser = "support4wiki-user-name", |
− | msgDescMiss = "solo" }, | + | msgDescMiss = "solo", |
| + | tStylesTOCnum = "stylesTOCnum" }, |
| -- classParams = "classTable", | | -- classParams = "classTable", |
| -- classTable = false, -- class for params table | | -- classTable = false, -- class for params table |
Zeile 56: |
Zeile 58: |
| scream = false, -- error messages | | scream = false, -- error messages |
| sibling = false, -- TOC juxtaposed | | sibling = false, -- TOC juxtaposed |
− | slang = false, -- project language code | + | slang = nil, -- project/user language code |
| slim = false, -- JSON reduced to plain | | slim = false, -- JSON reduced to plain |
| source = false, -- JSON input | | source = false, -- JSON input |
Zeile 135: |
Zeile 137: |
| | | |
| | | |
− | local function Fetch( ask ) | + | local function Fetch( ask, allow ) |
| -- Fetch module | | -- Fetch module |
| -- Parameter: | | -- Parameter: |
− | -- ask -- string, with name | + | -- ask -- string, with name |
− | -- "/global" | + | -- "/global" |
− | -- "Multilingual" | + | -- "JSONutil" |
− | -- "Text" | + | -- "Multilingual" |
− | -- "WLink" | + | -- "Text" |
| + | -- "WLink" |
| + | -- allow -- true: no error if unavailable |
| -- Returns table of module | | -- Returns table of module |
| -- error: Module not available | | -- error: Module not available |
Zeile 167: |
Zeile 171: |
| end | | end |
| TemplateData.extern[ sign ] = r | | TemplateData.extern[ sign ] = r |
− | else | + | elseif not allow then |
− | error( string.format( "Fetch(%s) %s", sign, g ) ) | + | error( string.format( "Fetch(%s) %s", sign, g ), 0 ) |
| end | | end |
| end | | end |
| return r | | return r |
| end -- Fetch() | | end -- Fetch() |
| + | |
| + | |
| + | |
| + | local function Foreign() |
| + | -- Guess human language |
| + | -- Returns slang, or not |
| + | if type( Data.slang ) == "nil" then |
| + | local Multilingual = Fetch( "Multilingual", true ) |
| + | if Multilingual and |
| + | type( Multilingual.userLangCode ) == "function" then |
| + | Data.slang = Multilingual.userLangCode() |
| + | else |
| + | Data.slang = mw.language.getContentLanguage():getCode() |
| + | :lower() |
| + | end |
| + | end |
| + | if Data.slang and |
| + | mw.ustring.codepoint( Data.slang, 1, 1 ) > 122 then |
| + | Data.slang = false |
| + | end |
| + | return Data.slang |
| + | end -- Foreign() |
| | | |
| | | |
Zeile 212: |
Zeile 238: |
| -- Returns string, with localized text | | -- Returns string, with localized text |
| local o = mw.message.new( "templatedata-" .. adapt ) | | local o = mw.message.new( "templatedata-" .. adapt ) |
− | if not Data.slang then | + | if Foreign() 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 ) | | o:inLanguage( Data.slang ) |
| end | | end |
Zeile 359: |
Zeile 379: |
| local variants = { } | | local variants = { } |
| local r1, r2 | | local r1, r2 |
− | if Data.slang and
| |
− | mw.ustring.codepoint( Data.slang, 1, 1 ) > 122 then
| |
− | Data.slang = false
| |
− | end
| |
| for k, v in pairs( alternatives ) do | | for k, v in pairs( alternatives ) do |
| if type( v ) == "string" then | | if type( v ) == "string" then |
| v = mw.text.trim( v ) | | v = mw.text.trim( v ) |
− | if v ~= "" then | + | if v ~= "" and type( k ) == "string" then |
| k = k:lower() | | k = k:lower() |
| variants[ k ] = v | | variants[ k ] = v |
Zeile 374: |
Zeile 390: |
| end -- for k, v | | end -- for k, v |
| if n > 0 then | | if n > 0 then |
− | local choices, Multilingual | + | local Multilingual = Fetch( "Multilingual", true ) |
− | if n > 1 then | + | if Multilingual and |
− | choices = { } | + | type( Multilingual.i18n ) == "function" then |
− | end
| + | local show, slang = Multilingual.i18n( variants ) |
− | for k, v in pairs( variants ) do
| + | if show then |
− | if n == 1 then | + | r1 = show |
− | r1 = v | + | variants[ slang ] = nil |
− | elseif Data.slang == k then
| |
− | variants[ k ] = nil | |
− | r1 = v
| |
| r2 = variants | | r2 = variants |
− | else
| |
− | table.insert( choices, k )
| |
| end | | end |
− | end -- for k, v | + | end |
| if not r1 then | | if not r1 then |
− | Multilingual = Fetch( "Multilingual" ) | + | Foreign() |
− | if type( Multilingual.userLang ) == "function" then | + | for k, v in pairs( variants ) do |
− | local sel = Multilingual.userLang( choices,
| + | if n == 1 then |
− | TemplateData.frame )
| + | r1 = v |
− | r1 = variants[ sel ]
| + | elseif Data.slang == k then |
− | variants[ sel ] = nil
| + | variants[ k ] = nil |
− | r2 = variants
| + | r1 = v |
− | end | + | r2 = variants |
| + | end |
| + | end -- for k, v |
| end | | end |
− | if r2 then | + | if r2 and Multilingual 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, true ) then | | if v and not Multilingual.isLang( k, true ) then |
− | Fault( string.format( "Invalid <code>lang=%s</code>", | + | Fault( string.format( "%s <code>lang=%s</code>", |
| + | "Invalid", |
| k ) ) | | k ) ) |
| end | | end |
Zeile 429: |
Zeile 442: |
| para:wikitext( about.description[ 1 ] ) | | para:wikitext( about.description[ 1 ] ) |
| plus = mw.html.create( "ul" ) | | plus = mw.html.create( "ul" ) |
| + | plus:css( "text-align", "left" ) |
| for k, v in pairs( about.description[ 2 ] ) do | | for k, v in pairs( about.description[ 2 ] ) do |
| plus:node( mw.html.create( "li" ) | | plus:node( mw.html.create( "li" ) |
Zeile 654: |
Zeile 668: |
| local pointers = { } | | local pointers = { } |
| local points = { } | | local points = { } |
| + | local given = { } |
| for k, v in pairs( Data.tree.params ) do | | for k, v in pairs( Data.tree.params ) do |
| i = facet( k, 1 ) | | i = facet( k, 1 ) |
| + | if type( v ) == "table" then |
| + | if type( v.label ) == "string" then |
| + | s = mw.text.trim( v.label ) |
| + | if s == "" then |
| + | s = k |
| + | end |
| + | else |
| + | s = k |
| + | end |
| + | if given[ s ] then |
| + | if given[ s ] == 1 then |
| + | local scream = "Parameter label '%s' detected multiple times" |
| + | Fault( string.format( scream, s ) ) |
| + | given[ s ] = 2 |
| + | end |
| + | else |
| + | given[ s ] = 1 |
| + | end |
| + | end |
| if i then | | if i then |
| table.insert( points, i ) | | table.insert( points, i ) |
Zeile 794: |
Zeile 828: |
| if type( boole.show ) == "string" then | | if type( boole.show ) == "string" then |
| local v = mw.html.create( "span" ) | | local v = mw.html.create( "span" ) |
| + | :attr( "aria-hidden", "true" ) |
| :wikitext( boole.show ) | | :wikitext( boole.show ) |
| if boole.css then | | if boole.css then |
Zeile 820: |
Zeile 855: |
| | | |
| -- type | | -- type |
| + | if type( param.type ) == "string" then |
| + | param.type = mw.text.trim( param.type ) |
| + | if param.type == "" then |
| + | param.type = false |
| + | end |
| + | end |
| if param.type then | | if param.type then |
| s = Permit.types[ param.type ] | | s = Permit.types[ param.type ] |
Zeile 856: |
Zeile 897: |
| if param.required then | | if param.required then |
| mode = 1 | | mode = 1 |
| + | if param.autovalue then |
| + | Fault( string.format( "autovalued <code>%s</code> required", |
| + | access ) ) |
| + | legal = false |
| + | end |
| + | if param.default then |
| + | Fault( string.format( "Defaulted <code>%s</code> required", |
| + | access ) ) |
| + | legal = false |
| + | end |
| if param.deprecated then | | if param.deprecated then |
| Fault( string.format( "Required deprecated <code>%s</code>", | | Fault( string.format( "Required deprecated <code>%s</code>", |
Zeile 986: |
Zeile 1.037: |
| | | |
| | | |
− | local function finalize( advance ) | + | local function fellow( any, assigned, at ) |
− | -- Wrap presentation into frame | + | -- Check sets[] parameter and issue error message, if necessary |
| -- Parameter: | | -- Parameter: |
− | -- advance -- true, for nice | + | -- any -- should be number |
− | -- Returns string | + | -- assigned -- parameter name |
− | local r, lapsus | + | -- at -- number, of set |
− | if Data.div then | + | local s |
− | r = tostring( Data.div ) | + | if type( any ) ~= "number" then |
− | elseif Data.strip then | + | s = "<code>sets[%d].params[%s]</code>??" |
− | r = Data.strip
| + | Fault( string.format( s, |
| + | at, |
| + | mw.text.nowiki( tostring( any ) ) ) ) |
| + | elseif type( assigned ) == "string" then |
| + | if not Data.got.params[ assigned ] then |
| + | s = "<code>sets[%d].params %s</code> is undefined" |
| + | Fault( string.format( s, at, assigned ) ) |
| + | end |
| else | | else |
− | lapsus = true | + | s = "<code>sets[%d].params[%d] = %s</code>??" |
− | r = "" | + | Fault( string.format( s, k, type( assigned ) ) ) |
| end | | end |
− | r = r .. failures() | + | end -- fellow() |
− | if Data.source then | + | |
− | local live = ( advance or lapsus ) | + | |
− | if not live then | + | |
− | live = TemplateData.frame:preprocess( "{{REVISIONID}}" ) | + | local function fellows() |
− | live = ( live == "" ) | + | -- Check sets[] and issue error message, if necessary |
| + | local s |
| + | if type( Data.got.sets ) == "table" then |
| + | if type( Data.got.params ) == "table" then |
| + | for k, v in pairs( Data.got.sets ) do |
| + | if type( k ) == "number" then |
| + | if type( v ) == "table" then |
| + | for ek, ev in pairs( v ) do |
| + | if ek == "label" then |
| + | s = type( ev ) |
| + | if s ~= "string" and |
| + | s ~= "table" then |
| + | s = "<code>sets[%d].label</code>??" |
| + | Fault( string.format( s, k ) ) |
| + | end |
| + | elseif ek == "params" and |
| + | type( ev ) == "table" then |
| + | for pk, pv in pairs( ev ) do |
| + | fellow( pk, pv, k ) |
| + | end -- for pk, pv |
| + | else |
| + | ek = mw.text.nowiki( tostring( ek ) ) |
| + | s = "<code>sets[%d][%s]</code>??" |
| + | Fault( string.format( s, k, ek ) ) |
| + | end |
| + | end -- for ek, ev |
| + | else |
| + | k = mw.text.nowiki( tostring( k ) ) |
| + | v = mw.text.nowiki( tostring( v ) ) |
| + | s = string.format( "<code>sets[%s][%s]</code>??", |
| + | k, v ) |
| + | Fault( s ) |
| + | end |
| + | else |
| + | k = mw.text.nowiki( tostring( k ) ) |
| + | s = string.format( "<code>sets[%s]</code> ?????", k ) |
| + | Fault( s ) |
| + | end |
| + | end -- for k, v |
| + | else |
| + | s = "<code>params</code> required for <code>sets</code>" |
| + | Fault( s ) |
| + | end |
| + | else |
| + | s = "<code>sets</code> needs to be of <code>object</code> type" |
| + | Fault( s ) |
| + | end |
| + | end -- fellows() |
| + | |
| + | |
| + | |
| + | local function finalize( advance ) |
| + | -- Wrap presentation into frame |
| + | -- Parameter: |
| + | -- advance -- true, for nice |
| + | -- Returns string |
| + | local r, lapsus |
| + | if Data.div then |
| + | r = tostring( Data.div ) |
| + | elseif Data.strip then |
| + | r = Data.strip |
| + | else |
| + | 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 |
| + | return r |
| + | end -- finalize() |
| + | |
| + | |
| + | |
| + | local function find() |
| + | -- Find JSON data within page source (title) |
| + | -- Returns string, or nil |
| + | local s = Data.title:getContent() |
| + | local i, j = s:find( "<templatedata>", 1, true ) |
| + | local r |
| + | if i then |
| + | local k = s:find( "</templatedata>", j, true ) |
| + | if k then |
| + | r = mw.text.trim( s:sub( j + 1, k - 1 ) ) |
| + | end |
| + | end |
| + | return r |
| + | end -- find() |
| + | |
| + | |
| + | |
| + | local function flat( adjust ) |
| + | -- Remove formatting from text string |
| + | -- Parameter: |
| + | -- arglist -- string, to be stripped, or nil |
| + | -- Returns string, or nil |
| + | local r |
| + | if adjust then |
| + | r = adjust:gsub( "\n", " " ) |
| + | if r:find( "<noexport>", 1, true ) then |
| + | r = r:gsub( "<noexport>(.*)</noexport>", "" ) |
| + | end |
| + | if r:find( "''", 1, true ) then |
| + | r = r:gsub( "'''", "" ):gsub( "''", "" ) |
| + | end |
| + | if r:find( "<", 1, true ) then |
| + | local Text = Fetch( "Text" ) |
| + | r = Text.getPlain( r:gsub( "<br */?>", "\r\n" ) ) |
| + | end |
| + | if r:find( "[", 1, true ) then |
| + | local WLink = Fetch( "WLink" ) |
| + | if WLink.isBracketedURL( r ) then |
| + | r = r:gsub( "%[([hf]tt?ps?://%S+) [^%]]+%]", "%1" ) |
| + | end |
| + | r = WLink.getPlain( r ) |
| end | | end |
− | if live then | + | if r:find( "&", 1, true ) then |
− | r = r .. fancy( advance, lapsus ) | + | r = mw.text.decode( r ) |
| end | | end |
| end | | end |
| return r | | return r |
− | end -- finalize() | + | end -- flat() |
| | | |
| | | |
| | | |
− | local function find() | + | local function flush() |
− | -- Find JSON data within page source (title) | + | -- JSON encode narrowed input; obey unnamed (numerical) parameters |
− | -- Returns string, or nil | + | -- Returns <templatedata> JSON string |
− | local s = Data.title:getContent() | + | local r |
− | local i, j = s:find( "<templatedata>", 1, true ) | + | if Data.tag then |
− | local r | + | r = mw.text.jsonEncode( Data.tag ):gsub( "%}$", "," ) |
− | if i then | + | else |
− | local k = s:find( "</templatedata>", j, true ) | + | r = "{" |
− | if k then
| + | end |
− | r = mw.text.trim( s:sub( j + 1, k - 1 ) )
| + | r = r .. "\n\"params\":{" |
− | end | + | if Data.order then |
| + | local sep = "" |
| + | local s |
| + | for i = 1, #Data.order do |
| + | s = Data.order[ i ] |
| + | r = string.format( "%s%s\n%s:%s", |
| + | r, |
| + | sep, |
| + | mw.text.jsonEncode( s ), |
| + | mw.text.jsonEncode( Data.params[ s ] ) ) |
| + | sep = ",\n" |
| + | end -- for i = 1, #Data.order |
| end | | end |
| + | r = r .. "\n}\n}" |
| return r | | return r |
− | end -- find() | + | end -- flush() |
| | | |
| | | |
| | | |
− | local function flat( adjust ) | + | local function focus( access ) |
− | -- Remove formatting from text string | + | -- Check components; focus multilingual description, build trees |
| -- Parameter: | | -- Parameter: |
− | -- arglist -- string, to be stripped, or nil | + | -- access -- string, name of parameter, nil for root |
− | -- Returns string, or nil
| + | local f = function ( a, at ) |
− | local r | + | local r |
− | if adjust then
| + | if at then |
− | r = adjust:gsub( "\n", " " )
| + | r = string.format( "<code>params.%s</code>", at ) |
− | if r:find( "<noexport>", 1, true ) then
| + | else |
− | r = r:gsub( "<noexport>(.*)</noexport>", "" )
| + | r = "''root''" |
− | end
| + | end |
− | if r:find( "''", 1, true ) then
| + | if a then |
− | r = r:gsub( "'''", "" ):gsub( "''", "" )
| + | r = string.format( "%s<code>.%s</code>", r, a ) |
− | end
| + | end |
− | if r:find( "<", 1, true ) then
| + | return r |
− | local Text = Fetch( "Text" )
| + | end |
− | r = Text.getPlain( r )
| + | local parent |
− | end
| + | if access then |
− | if r:find( "[", 1, true ) then
| + | parent = Data.got.params[ access ] |
− | local WLink = Fetch( "WLink" ) | + | else |
− | if WLink.isBracketedURL( r ) then | + | parent = Data.got |
− | r = r:gsub( "%[([hf]tt?ps?://%S+) [^%]]+%]", "%1" ) | + | end |
| + | if type( parent ) == "table" then |
| + | local elem, got, permit, s, scope, slot, tag, target |
| + | if access then |
| + | permit = Permit.params |
| + | if type( access ) == "number" then |
| + | slot = tostring( access ) |
| + | else |
| + | slot = access |
| end | | end |
− | r = WLink.getPlain( r ) | + | else |
| + | permit = Permit.root |
| end | | end |
− | if r:find( "&", 1, true ) then | + | for k, v in pairs( parent ) do |
− | r = mw.text.decode( r )
| + | scope = permit[ k ] |
− | end
| + | if scope then |
− | end
| + | s = type( v ) |
− | return r
| + | if s == "string" and k ~= "format" then |
− | end -- flat()
| + | v = mw.text.trim( v ) |
− | | + | end |
− | | + | if scope:find( s, 1, true ) then |
− | | + | if scope:find( "I18N", 1, true ) then |
− | local function flush() | + | if s == "string" then |
− | -- JSON encode narrowed input; obey unnamed (numerical) parameters
| + | elem = fair( v ) |
− | -- Returns <templatedata> JSON string
| + | elseif s == "table" then |
− | local r
| + | local translated |
− | if Data.tag then
| + | v, translated = faraway( v ) |
− | r = mw.text.jsonEncode( Data.tag ):gsub( "%}$", "," )
| + | if v then |
− | else
| + | if translated and |
− | r = "{"
| + | k == "description" then |
− | end
| + | elem = { [ 1 ] = fair( v ), |
− | r = r .. "\n\"params\":{"
| + | [ 2 ] = translated } |
− | if Data.order then
| + | else |
− | local sep = ""
| + | elem = fair( v ) |
− | local s
| + | end |
− | for i = 1, #Data.order do
| + | else |
− | s = Data.order[ i ]
| + | elem = false |
− | r = string.format( "%s%s\n%s:%s",
| + | end |
− | r,
| + | end |
− | sep,
| + | if type( v ) == "string" then |
− | mw.text.jsonEncode( s ),
| + | if k == "deprecated" then |
− | mw.text.jsonEncode( Data.params[ s ] ) )
| + | if v == "1" then |
− | sep = ",\n"
| + | v = true |
− | end -- for i = 1, #Data.order
| + | elseif v == "0" then |
− | end
| + | v = false |
− | r = r .. "\n}\n}"
| + | end |
− | return r
| + | elem = v |
− | end -- flush()
| + | elseif scope:find( "nowiki", 1, true ) then |
− | | + | elem = mw.text.nowiki( v ) |
− | | + | elem = elem:gsub( " \n", "<br>" ) |
− | | + | v = v:gsub( string.char( 13 ), "" ) |
− | local function focus( access )
| + | else |
− | -- Check components; focus multilingual description, build trees
| + | v = flat( v ) |
− | -- Parameter:
| + | end |
− | -- access -- string, name of parameter, nil for root
| + | elseif s == "boolean" then |
− | local f = function ( a, at )
| + | if scope:find( "boolean", 1, true ) then |
− | local r
| + | elem = v |
− | if at then
| + | else |
− | r = string.format( "<code>params.%s</code>", at ) | + | s = "Type <code>boolean</code> bad for " |
− | else
| + | .. f( k, slot ) |
− | r = "''root''" | + | Fault( s ) |
| + | end |
| + | end |
| + | else |
| + | if k == "params" and not access then |
| + | v = nil |
| + | elem = nil |
| + | elseif k == "format" and not access then |
| + | elem = mw.text.decode( v ) |
| + | v = nil |
| + | elseif k == "inherits" then |
| + | elem = v |
| + | if not Data.heirs then |
| + | Data.heirs = { } |
| + | end |
| + | Data.heirs[ slot ] = v |
| + | v = nil |
| + | elseif k == "style" then |
| + | elem = v |
| + | v = nil |
| + | elseif s == "string" then |
| + | v = mw.text.nowiki( v ) |
| + | elem = v |
| + | else |
| + | elem = v |
| + | end |
| end | | end |
− | if a then | + | if type( elem ) ~= "nil" then |
− | r = string.format( "%s<code>.%s</code>", r, a ) | + | if not target then |
| + | if access then |
| + | if not Data.tree.params then |
| + | Data.tree.params = { } |
| + | end |
| + | Data.tree.params[ slot ] = { } |
| + | target = Data.tree.params[ slot ] |
| + | else |
| + | Data.tree = { } |
| + | target = Data.tree |
| + | end |
| + | end |
| + | target[ k ] = elem |
| + | elem = false |
| end | | end |
− | return r | + | if type( v ) ~= "nil" then |
− | end
| + | if not tag then |
− | local parent
| + | if access then |
− | if access then
| + | if type( v ) == "string" and |
− | parent = Data.got.params[ access ]
| + | v.sub( 1, 1 ) == "=" then |
− | else
| + | v = nil |
− | parent = Data.got
| + | else |
− | end
| + | if not Data.params then |
− | if type( parent ) == "table" then
| + | Data.params = { } |
− | local elem, got, permit, s, scope, slot, tag, target
| + | end |
− | if access then
| + | Data.params[ slot ] = { } |
− | permit = Permit.params
| + | tag = Data.params[ slot ] |
− | if type( access ) == "number" then
| + | end |
− | slot = tostring( access )
| + | else |
− | else
| + | Data.tag = { } |
− | slot = access
| + | tag = Data.tag |
− | end
| + | end |
− | else
| + | end |
− | permit = Permit.root
| + | if type( v ) ~= "nil" then |
− | end
| + | tag[ k ] = v |
− | for k, v in pairs( parent ) do
| + | end |
− | scope = permit[ k ]
| + | end |
− | if scope then
| + | else |
− | s = type( v ) | + | s = string.format( "Type <code>%s</code> bad for %s", |
− | if s == "string" and k ~= "format" then
| + | scope, f( k, slot ) ) |
− | v = mw.text.trim( v ) | + | Fault( s ) |
| end | | end |
− | if scope:find( s, 1, true ) then | + | else |
− | if scope:find( "I18N", 1, true ) then
| + | Fault( "Unknown component " .. f( k, slot ) ) |
− | if s == "string" then
| + | end |
− | elem = fair( v )
| + | end -- for k, v |
− | elseif s == "table" then
| + | if not access and Data.got.sets then |
− | local translated
| + | fellows() |
− | v, translated = faraway( v )
| + | end |
− | if v then
| + | else |
− | if translated and
| + | Fault( f() .. " needs to be of <code>object</code> type" ) |
− | k == "description" then
| + | end |
− | elem = { [ 1 ] = fair( v ),
| + | end -- focus() |
− | [ 2 ] = translated }
| + | |
− | else
| + | |
− | elem = fair( v )
| + | |
− | end
| + | local function format() |
− | else
| + | -- Build formatted element |
− | elem = false
| + | -- Returns <inline> |
− | end
| + | local source = Data.tree.format:lower() |
− | end
| + | local r, s |
− | if type( v ) == "string" then
| + | if source == "inline" or source == "block" then |
− | if k == "deprecated" then
| + | r = mw.html.create( "i" ) |
− | if v == "1" then
| + | :wikitext( source ) |
− | v = true
| + | else |
− | elseif v == "0" then
| + | local code |
− | v = false
| + | if source:find( "|", 1, true ) then |
− | end
| + | local scan = "^[\n ]*%{%{[\n _]*|[\n _]*=[\n _]*%}%}[\n ]*$" |
− | elem = v
| + | if source:match( scan ) then |
− | elseif scope:find( "nowiki", 1, true ) then
| + | code = source:gsub( "\n", "N" ) |
− | elem = mw.text.nowiki( v )
| + | else |
− | else
| + | s = mw.text.nowiki( source ):gsub( "\n", "\n" ) |
− | v = flat( v )
| + | s = tostring( mw.html.create( "code" ) |
− | end
| + | :wikitext( s ) ) |
− | end
| + | Fault( "Invalid format " .. s ) |
− | else
| + | source = false |
− | if k == "params" and not access then
| + | end |
− | v = nil
| + | else |
− | elem = nil
| + | local words = mw.text.split( source, "%s+" ) |
− | elseif k == "format" and not access then
| + | local show, start, support, unknown |
− | elem = mw.text.decode( v )
| + | for i = 1, #words do |
− | v = nil
| + | s = words[ i ] |
− | elseif k == "inherits" then
| + | if i == 1 then |
− | elem = v
| + | start = s |
− | if not Data.heirs then
| + | end |
− | Data.heirs = { }
| + | support = Permit.builder[ s ] |
− | end
| + | if support == start or |
− | Data.heirs[ slot ] = v
| + | support == "*" then |
− | v = nil
| + | Permit.builder[ s ] = true |
− | elseif k == "style" then
| + | elseif s:match( "^[1-9]%d?" ) and |
− | elem = v
| + | Permit.builder.align then |
− | v = nil
| + | Permit.builder.align = tonumber( s ) |
− | elseif s == "string" then
| + | else |
− | v = mw.text.nowiki( v )
| + | if unknown then |
− | elem = v
| + | unknown = string.format( "%s %s", unknown, s ) |
− | else
| + | else |
− | elem = v
| + | unknown = s |
− | end
| |
| end | | end |
− | if type( elem ) ~= "nil" then
| |
− | if not target then
| |
− | if access then
| |
− | if not Data.tree.params then
| |
− | Data.tree.params = { }
| |
− | end
| |
− | Data.tree.params[ slot ] = { }
| |
− | target = Data.tree.params[ slot ]
| |
− | else
| |
− | Data.tree = { }
| |
− | target = Data.tree
| |
− | end
| |
− | end
| |
− | target[ k ] = elem
| |
− | elem = false
| |
− | end
| |
− | if type( v ) ~= "nil" then
| |
− | if not tag then
| |
− | if access then
| |
− | if type( v ) == "string" and
| |
− | v.sub( 1, 1 ) == "=" then
| |
− | v = nil
| |
− | else
| |
− | if not Data.params then
| |
− | Data.params = { }
| |
− | end
| |
− | Data.params[ slot ] = { }
| |
− | tag = Data.params[ slot ]
| |
− | end
| |
− | else
| |
− | Data.tag = { }
| |
− | tag = Data.tag
| |
− | end
| |
− | end
| |
− | if type( v ) ~= "nil" then
| |
− | tag[ k ] = v
| |
− | end
| |
− | end
| |
− | else
| |
− | s = string.format( "Type <code>%s</code> bad for %s",
| |
− | scope, f( k, slot ) )
| |
− | Fault( s )
| |
| end | | end |
− | else
| + | end -- i = 1, #words |
− | Fault( "Unknown component " .. f( k, slot ) )
| + | if unknown then |
− | end | + | s = tostring( mw.html.create( "code" ) |
− | end -- for k, v
| + | :css( "white-space", "nowrap" ) |
− | else
| + | :wikitext( s ) ) |
− | Fault( f() .. " needs to be of <code>object</code> type" )
| + | Fault( "Unknown/misplaced format keyword " .. s ) |
− | end
| + | source = false |
− | end -- focus()
| + | start = false |
− | | + | end |
− | | + | if start == "inline" then |
− | | + | if Permit.builder.half == true then |
− | local function format()
| + | show = "inline half" |
− | -- Build formatted element
| + | code = "{{_ |_=_}}" |
− | -- Returns <inline>
| + | elseif Permit.builder.grouped == true then |
− | local source = Data.tree.format:lower()
| + | show = "inline grouped" |
− | local r, s
| + | code = "{{_ | _=_}}" |
− | if source == "inline" or source == "block" then
| + | elseif Permit.builder.spaced == true then |
− | r = mw.html.create( "i" )
| + | show = "inline spaced" |
− | :wikitext( source )
| + | code = "{{_ | _ = _ }}" |
− | else
| + | end |
− | local code
| + | if Permit.builder.newlines == true then |
− | if source:find( "|", 1, true ) then
| + | show = show or "inline" |
− | local scan = "^[\n ]*%{%{[\n _]*|[\n _]*=[\n _]*%}%}[\n ]*$"
| + | code = code or "{{_|_=_}}" |
− | if source:match( scan ) then
| + | show = show .. " newlines" |
− | code = source:gsub( "\n", "N" )
| + | code = string.format( "N%sN", code ) |
− | else
| + | end |
− | s = mw.text.nowiki( source ):gsub( "\n", "\n" ) | + | elseif start == "block" then |
− | s = tostring( mw.html.create( "code" )
| + | local space = "" -- amid "|" and name |
− | :wikitext( s ) )
| + | local spaced = " " -- preceding "=" |
− | Fault( "Invalid format " .. s ) | + | local spacer = " " -- following "=" |
− | source = false | + | local suffix = "N" -- closing "}}" on new line |
− | end
| + | show = "block" |
− | else
| + | if Permit.builder.indent == true then |
− | local words = mw.text.split( source, "%s+" )
| + | start = " " |
− | local show, start, support, unknown
| + | show = "block indent" |
− | for i = 1, #words do
| + | else |
− | s = words[ i ] | + | start = "" |
− | if i == 1 then | + | end |
− | start = s | + | if Permit.builder.compressed == true then |
− | end | + | spaced = "" |
− | support = Permit.builder[ s ] | + | spacer = "" |
− | if support == start or
| + | show = show .. " compressed" |
− | support == "*" then
| + | if Permit.builder.last == true then |
− | Permit.builder[ s ] = true | + | show = show .. " last" |
− | elseif s:match( "^[1-9]%d?" ) and
| + | else |
− | Permit.builder.align then
| + | suffix = "" |
− | Permit.builder.align = tonumber( s )
| + | end |
− | else
| + | else |
− | if unknown then
| + | if Permit.builder.lead == true then |
− | unknown = string.format( "%s %s", unknown, s )
| + | show = show .. " lead" |
− | else
| + | space = " " |
− | unknown = s | + | end |
| + | if type( Permit.builder.align ) ~= "string" 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 |
| end | | end |
− | end -- i = 1, #words
| + | code = string.format( "N{{_N%s|%s_%s=%s_%s}}N", |
− | if unknown then
| + | start, |
− | s = tostring( mw.html.create( "code" )
| + | space, |
− | :css( "white-space", "nowrap" )
| + | spaced, |
− | :wikitext( s ) )
| + | spacer, |
− | Fault( "Unknown/misplaced format keyword " .. s )
| + | suffix ) |
− | source = false
| + | if show == "block" then |
− | start = false
| + | show = "block newlines" |
− | end
| + | end |
− | if start == "inline" then
| + | end |
− | if Permit.builder.half == true then
| + | if show then |
− | show = "inline half"
| + | r = mw.html.create( "span" ) |
− | code = "{{_ |_=_}}"
| + | :wikitext( show ) |
− | 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 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 |
| + | -- Returns <div> |
| + | local r = mw.html.create( "div" ) |
| + | local x = fashioned( Data.tree, true, r ) |
| + | local s |
| + | if x then |
| + | r = x |
| + | end |
| + | if Data.leading then |
| + | local toc = mw.html.create( "div" ) |
| + | local shift |
| + | if Config.suppressTOCnum then |
| + | toc:addClass( Config.suppressTOCnum ) |
| + | if type( Config.stylesTOCnum ) == "string" then |
| + | local src = Config.stylesTOCnum .. "/styles.css" |
| + | s = TemplateData.frame:extensionTag( "templatestyles", |
| + | nil, |
| + | { src = src } ) |
| + | r:newline() |
| + | :node( s ) |
| + | end |
| + | 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() |
| + | :node( toc ) |
| + | :newline() |
| + | if shift then |
| + | r:node( mw.html.create( "div" ) |
| + | :css( "clear", shift ) ) |
| + | :newline() |
| + | end |
| + | end |
| + | s = features() |
| + | if s then |
| + | if Data.leading then |
| + | r:node( mw.html.create( "h" .. Config.nested ) |
| + | :wikitext( factory( "doc-params" ) ) ) |
| + | :newline() |
| + | end |
| + | 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 |
| + | if Data.tree and Data.tree.format then |
| + | local e = format() |
| + | if e then |
| + | 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 |
− | if source then
| |
− | Data.tag.format = source
| |
− | end
| |
| return r | | return r |
− | end -- format() | + | end -- formatter() |
| | | |
| | | |
| | | |
− | local function formatter() | + | local function free() |
− | -- Build presented documentation | + | -- Remove JSON comment lines |
− | -- Returns <div> | + | if Data.source:find( "//", 1, true ) then |
− | local r = mw.html.create( "div" )
| + | Data.source:gsub( "([{,\"'])(%s*\n%s*//.*\n%s*)([{},\"'])", |
− | local x = fashioned( Data.tree, true, r )
| + | "%1%3" ) |
− | local s
| |
− | if x then
| |
− | r = x
| |
| end | | end |
− | if Data.leading then | + | end -- free() |
− | local toc = mw.html.create( "div" )
| + | |
− | local shift
| + | |
− | if Config.suppressTOCnum then
| + | |
− | toc:addClass( Config.suppressTOCnum )
| + | local function full() |
− | end
| + | -- Build survey table from JSON data, append invisible <templatedata> |
− | toc:css( "margin-top", "0.5em" )
| + | Data.div = mw.html.create( "div" ) |
− | :wikitext( "__TOC__" )
| + | :addClass( "mw-templatedata-doc-wrap" ) |
− | if Data.sibling then | + | focus() |
− | local block = mw.html.create( "div" ) | + | if Data.tag then |
− | if TemplateData.ltr then | + | if type( Data.got.params ) == "table" then |
− | shift = "right" | + | for k, v in pairs( Data.got.params ) do |
− | else
| + | focus( k ) |
− | shift = "left"
| + | end -- for k, v |
| + | if Data.heirs then |
| + | fathers() |
| end | | end |
− | block:css( "float", shift )
| |
− | :wikitext( Data.sibling )
| |
− | r:newline()
| |
− | :node( block )
| |
− | :newline()
| |
| end | | end |
− | r:newline() | + | end |
− | :node( toc )
| + | Data.div:node( formatter() ) |
− | :newline()
| + | if not Data.lazy then |
− | if shift then
| + | Data.slim = flush() |
− | r:node( mw.html.create( "div" )
| + | if TemplateData.frame then |
− | :css( "clear", shift ) )
| + | local div = mw.html.create( "div" ) |
− | :newline()
| + | local tdata = { [ 1 ] = "templatedata", |
| + | [ 2 ] = Data.slim } |
| + | Data.strip = TemplateData.frame:callParserFunction( "#tag", |
| + | tdata ) |
| + | div:wikitext( Data.strip ) |
| + | if Config.loudly then |
| + | Data.div:node( mw.html.create( "hr" ) |
| + | :css( { height = "7ex" } ) ) |
| + | else |
| + | div:css( "display", "none" ) |
| + | end |
| + | Data.div:node( div ) |
| end | | end |
| end | | end |
− | s = features() | + | if Data.lasting then |
− | if s then | + | Fault( "deprecated type syntax" ) |
− | if Data.leading then
| + | end |
− | r:node( mw.html.create( "h2" )
| + | if Data.less then |
− | :wikitext( factory( "doc-params" ) ) )
| + | Fault( Config.solo ) |
− | :newline()
| + | end |
| + | end -- full() |
| + | |
| + | |
| + | |
| + | local function furnish( adapt, arglist ) |
| + | -- Analyze transclusion |
| + | -- Parameter: |
| + | -- adapt -- table, #invoke parameters |
| + | -- arglist -- table, template parameters |
| + | -- Returns string |
| + | local source |
| + | favorize() |
| + | -- deprecated: |
| + | for k, v in pairs( Config.basicCnf ) do |
| + | if adapt[ k ] and adapt[ k ] ~= "" then |
| + | Config[ v ] = adapt[ k ] |
| end | | end |
− | r:node( s )
| + | end -- for k, v |
| + | if arglist.heading and arglist.heading:match( "^[3-6]$" ) then |
| + | Config.nested = arglist.heading |
| + | else |
| + | Config.nested = "2" |
| end | | end |
− | if Data.shared then | + | Config.loudly = faculty( arglist.debug or adapt.debug ) |
− | local global = mw.html.create( "div" ) | + | Data.lazy = faculty( arglist.lazy ) and not Config.loudly |
− | :attr( "id", "templatedata-global" )
| + | Data.leading = faculty( arglist.TOC ) |
− | local shift
| + | if Data.leading and arglist.TOCsibling then |
− | if TemplateData.ltr then
| + | Data.sibling = mw.text.trim( arglist.TOCsibling ) |
− | shift = "right"
| + | end |
− | else | + | if arglist.lang then |
− | shift = "left"
| + | Data.slang = arglist.lang:lower() |
− | end
| + | elseif adapt.lang then |
− | global:css( "float", shift )
| + | Data.slang = adapt.lang:lower() |
− | :wikitext( string.format( "[[%s|%s]]",
| |
− | Data.shared, "Global" ) )
| |
− | r:newline()
| |
− | :node( global )
| |
| end | | end |
− | if Data.tree and Data.tree.format then | + | if arglist.JSON then |
− | local e = format() | + | source = arglist.JSON |
− | if e then | + | elseif arglist.Global then |
− | local show = "Format" | + | source = TemplateData.getGlobalJSON( arglist.Global, |
− | if Config.supportFormat then | + | arglist.Local ) |
− | show = string.format( "[[%s|%s]]",
| + | elseif arglist[ 1 ] then |
− | Config.supportFormat, show )
| + | local s = mw.text.trim( arglist[ 1 ] ) |
− | end
| + | local start = s:sub( 1, 1 ) |
− | r:node( mw.html.create( "p" )
| + | if start == "<" then |
− | :wikitext( show .. ": " )
| + | Data.strip = s |
− | :node( e ) )
| + | elseif start == "{" then |
| + | source = s |
| + | elseif mw.ustring.sub( s, 1, 8 ) == |
| + | mw.ustring.char( 127, 39, 34, 96, 85, 78, 73, 81 ) then |
| + | Data.strip = s |
| end | | end |
| end | | end |
− | return r | + | if type( arglist.vertical ) == "string" and |
− | end -- formatter()
| + | arglist.vertical:match( "^%d*%.?%d+[emprx]+$" ) then |
− | | + | Data.scroll = arglist.vertical |
− | | + | end |
− | | + | if not source then |
− | local function free()
| + | Data.title = mw.title.getCurrentTitle() |
− | -- Remove JSON comment lines
| + | source = find() |
− | Data.source:gsub( "([{,\"'])(%s*\n%s*//.*\n%s*)([},\"'])",
| + | if not source and |
− | "%1%3" )
| + | not Data.title.text:match( Config.subpage ) then |
− | end -- free() | + | local s = string.format( Config.suffix, |
− | | + | Data.title.prefixedText ) |
− | | + | Data.title = mw.title.new( s ) |
− | | + | if Data.title.exists then |
− | local function full()
| + | source = find() |
− | -- Build survey table from JSON data, append invisible <templatedata> | |
− | Data.div = mw.html.create( "div" )
| |
− | :addClass( "mw-templatedata-doc-wrap" )
| |
− | focus()
| |
− | if Data.tag then
| |
− | if type( Data.got.params ) == "table" then
| |
− | for k, v in pairs( Data.got.params ) do | |
− | focus( k )
| |
− | end -- for k, v
| |
− | if Data.heirs then | |
− | fathers() | |
| end | | end |
| end | | end |
| end | | end |
− | Data.div:node( formatter() )
| |
| if not Data.lazy then | | if not Data.lazy then |
− | Data.slim = flush() | + | if not Data.title then |
− | if TemplateData.frame then
| + | Data.title = mw.title.getCurrentTitle() |
− | local div = mw.html.create( "div" )
| |
− | local tdata = { [ 1 ] = "templatedata",
| |
− | [ 2 ] = Data.slim }
| |
− | Data.strip = TemplateData.frame:callParserFunction( "#tag", | |
− | tdata )
| |
− | div:wikitext( Data.strip )
| |
− | if Config.loudly then
| |
− | Data.div:node( mw.html.create( "hr" ) )
| |
− | else
| |
− | div:css( "display", "none" )
| |
− | end
| |
− | Data.div:node( div )
| |
| end | | end |
| + | Data.lazy = Data.title.text:match( Config.subpage ) |
| end | | end |
− | if Data.lasting then | + | if type( source ) == "string" then |
− | Fault( "deprecated type syntax" ) | + | TemplateData.getPlainJSON( source ) |
| end | | end |
− | if Data.less then | + | return finalize( faculty( arglist.source ) ) |
− | Fault( Config.solo )
| + | end -- furnish() |
− | end
| |
− | end -- full() | |
| | | |
| | | |
| | | |
− | local function furnish( adapt, arglist )
| + | Failsafe.failsafe = function ( atleast ) |
− | -- Analyze transclusion | + | -- Retrieve versioning and check for compliance |
− | -- Parameter: | + | -- Precondition: |
− | -- adapt -- table, #invoke parameters | + | -- atleast -- string, with required version |
− | -- arglist -- table, template parameters | + | -- or wikidata|item|~|@ or false |
− | -- Returns string | + | -- Postcondition: |
− | local source | + | -- Returns string -- with queried version/item, also if problem |
− | favorize() | + | -- false -- if appropriate |
− | -- deprecated: | + | -- 2020-08-17 |
− | for k, v in pairs( Config.basicCnf ) do | + | local since = atleast |
− | if adapt[ k ] and adapt[ k ] ~= "" then
| + | local last = ( since == "~" ) |
− | Config[ v ] = adapt[ k ] | + | local linked = ( since == "@" ) |
| + | local link = ( since == "item" ) |
| + | local r |
| + | if last or link or linked or since == "wikidata" then |
| + | local item = Failsafe.item |
| + | since = false |
| + | if type( item ) == "number" and item > 0 then |
| + | local suited = string.format( "Q%d", item ) |
| + | if link then |
| + | r = suited |
| + | else |
| + | local entity = mw.wikibase.getEntity( suited ) |
| + | if type( entity ) == "table" then |
| + | local seek = Failsafe.serialProperty or "P348" |
| + | local vsn = entity:formatPropertyValues( seek ) |
| + | if type( vsn ) == "table" and |
| + | type( vsn.value ) == "string" and |
| + | vsn.value ~= "" then |
| + | if last and vsn.value == Failsafe.serial then |
| + | r = false |
| + | elseif linked then |
| + | if mw.title.getCurrentTitle().prefixedText |
| + | == mw.wikibase.getSitelink( suited ) then |
| + | r = false |
| + | else |
| + | r = suited |
| + | end |
| + | else |
| + | r = vsn.value |
| + | end |
| + | end |
| + | end |
| + | end |
| end | | end |
− | end -- for k, v | + | end |
− | Config.loudly = faculty( arglist.debug or adapt.debug )
| + | if type( r ) == "nil" then |
− | Data.lazy = faculty( arglist.lazy ) and not Config.loudly
| + | if not since or since <= Failsafe.serial then |
− | Data.leading = faculty( arglist.TOC )
| + | r = Failsafe.serial |
− | if Data.leading and arglist.TOCsibling then | + | else |
− | Data.sibling = mw.text.trim( arglist.TOCsibling )
| + | r = false |
− | end
| |
− | if arglist.lang then
| |
− | Data.slang = arglist.lang:lower()
| |
− | elseif adapt.lang then
| |
− | Data.slang = adapt.lang:lower()
| |
− | end
| |
− | if arglist.JSON then
| |
− | source = arglist.JSON
| |
− | elseif arglist.Global then
| |
− | source = TemplateData.getGlobalJSON( arglist.Global,
| |
− | arglist.Local )
| |
− | elseif arglist[ 1 ] then
| |
− | local s = mw.text.trim( arglist[ 1 ] )
| |
− | local start = s:sub( 1, 1 )
| |
− | if start == "<" then | |
− | Data.strip = s
| |
− | elseif start == "{" then
| |
− | source = s | |
− | elseif mw.ustring.sub( s, 1, 8 ) == | |
− | mw.ustring.char( 127, 39, 34, 96, 85, 78, 73, 81 ) then
| |
− | Data.strip = s | |
| end | | end |
| end | | end |
− | if type( arglist.vertical ) == "string" and
| + | return r |
− | arglist.vertical:match( "^%d*%.?%d+[emprx]+$" ) then
| + | end -- Failsafe.failsafe() |
− | Data.scroll = arglist.vertical
| |
− | end
| |
− | if not source then
| |
− | Data.title = mw.title.getCurrentTitle()
| |
− | source = find()
| |
− | if not source and
| |
− | not Data.title.text:match( Config.subpage ) then
| |
− | local s = string.format( Config.suffix,
| |
− | Data.title.prefixedText )
| |
− | Data.title = mw.title.new( s )
| |
− | if Data.title.exists then
| |
− | source = find()
| |
− | end
| |
− | end
| |
− | end
| |
− | if not Data.lazy then
| |
− | if not Data.title then
| |
− | Data.title = mw.title.getCurrentTitle()
| |
− | end
| |
− | Data.lazy = Data.title.text:match( Config.subpage )
| |
− | end
| |
− | if type( source ) == "string" then
| |
− | TemplateData.getPlainJSON( source )
| |
− | end
| |
− | return finalize( faculty( arglist.source ) ) | |
− | end -- furnish() | |
| | | |
− |
| |
− |
| |
− | 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
| |
− | 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
| |
− | return r
| |
− | end -- TemplateData.failsafe()
| |
| | | |
| | | |
Zeile 1.697: |
Zeile 1.878: |
| -- Returns string, or not | | -- Returns string, or not |
| if type( adapt ) == "string" then | | if type( adapt ) == "string" then |
− | local lucky | + | local JSONutil = Fetch( "JSONutil", true ) |
| Data.source = adapt | | Data.source = adapt |
| free() | | free() |
− | lucky, Data.got = pcall( mw.text.jsonDecode, Data.source ) | + | if JSONutil then |
− | if lucky then | + | local Multilingual = Fetch( "Multilingual", true ) |
| + | local f |
| + | if Multilingual then |
| + | f = Multilingual.i18n |
| + | end |
| + | Data.got = JSONutil.fetch( Data.source, true, f ) |
| + | else |
| + | local lucky |
| + | lucky, Data.got = pcall( mw.text.jsonDecode, Data.source ) |
| + | end |
| + | if type( Data.got ) == "table" then |
| full() | | full() |
| elseif not Data.strip then | | elseif not Data.strip then |
− | Fault( "fatal JSON error: " .. Data.got ) | + | local scream = type( Data.got ) |
| + | if scream == "string" then |
| + | scream = Data.got |
| + | else |
| + | scream = "Data.got: " .. scream |
| + | end |
| + | Fault( "fatal JSON error: " .. scream ) |
| end | | end |
| end | | end |
Zeile 1.732: |
Zeile 1.929: |
| end | | end |
| return r | | return r |
− | end -- p.f() | + | end -- p.f |
| | | |
| p.failsafe = function ( frame ) | | p.failsafe = function ( frame ) |
Zeile 1.749: |
Zeile 1.946: |
| end | | end |
| end | | end |
− | return TemplateData.failsafe( since ) or "" | + | return Failsafe.failsafe( since ) or "" |
− | end -- p.failsafe() | + | end -- p.failsafe |
| | | |
| p.TemplateData = function () | | p.TemplateData = function () |