w>PerfektesChaos |
|
Zeile 1: |
Zeile 1: |
| local TemplateData = { suite = "TemplateData",
| | Die '''Töpfertradition auf Gotland''' wurde erst im 18. Jahrhundert auf Initiative des Landeshauptmanns gegründet, um die Einfuhr von [[Keramik]] auf die Insel zu drosseln. Er beschloss, einen Töpfer auf die [[Schweden|schwedischen]] Insel [[Gotland]] zu rufen, der "Kacheln, gemeine Steingefäße, Töpfe, und Ziegel" herstellen konnte. In den 1740er Jahren gab es zwei deutsche Töpfer und Kachelofenbauer in [[Visby]]. In ihren Werkstätten wurden Lehrlinge ausgebildet, die später Unternehmer und Lehrmeister wurden. Die bekannteste Töpferfamilie auf Gotland hieß im 19. Jahrhundert Berg und besaß Werkstätten in Visby, Boge und [[Klintehamn]]. Viele der Kachelöfen auf Gotland stammen von der Werkstatt Vesters in Boge. Eine andere berühmte Töpferfamilie hieß Korsman und war in Hemse tätig. Adergrens produzierte in Visby, Peterssons in Katthammarsvik. Nilssons in Etelhem waren auch bekannte Kachelofenbauer. |
| serial = "2019-07-01",
| |
| item = 46997995 }
| |
| --[=[
| |
| improve template:TemplateData
| |
| ]=] | |
|
| |
|
| | == Etelhem == |
| | Die Werkstätten der Töpferei des 19. Jahrhunderts gibt es noch in Etelhem. Daneben wurden neue Gebäude errichtet. Zu den Anlagen gehört ein Schlammwerk, wo der Ton vorbereitet wird. Hier lernen während des Sommers die Töpferlehrlinge der Insel und Kinder können an der Drehscheibe arbeiten. |
|
| |
|
| | Die 1889 gegründete [[Töpferei]] stellte Gebrauchsgegenstände und [[Kachelofen|Kachelöfen]] unter der Leitung des Töpfers Axel Nilsson her. Der Betrieb ging auf den Sohn Axel Olof über, der die Produktion umstellte. Er nahm Abstand von den Kachelöfen und betrieb die Töpferei bis 1960. Egil Solberg übernahm den Betrieb, der heute unter der Regie des Sohnes Torleif produziert. Die Solbergs führten neue Herstellungsmethoden ein. Nach wie vor waren Krüge, Schüsseln und Vasen, die Hauptausrichtung der Töpferei. Die traditionelle Brennerei wurde indes durch einen großen Reisigofen ergänzt, worin das Töpfergut bei 1025 °C gebrannt wird. Es dauert einen Tag, den Ofen mit Reisig zu feuern. |
|
| |
|
| local Config = {
| | == Literatur == |
| -- multiple option names mapped into unique internal fields
| | * Marita Jonsson, Sven-Olof Lindquist: ''Kulturführer Gotland''. Almqvist und Wiksell, Uppsala 1993, ISBN 91-88036-09-X. |
| basicCnf = { catProblem = "strange",
| |
| classNoNumTOC = "suppressTOCnum",
| |
| cssParWrap = "cssTabWrap",
| |
| cssParams = "cssTable",
| |
| docpageCreate = "suffix",
| |
| docpageDetect = "subpage",
| |
| helpBoolean = "support4boolean",
| |
| helpContent = "support4content",
| |
| helpDate = "support4date",
| |
| helpFile = "support4wiki-file-name",
| |
| helpFormat = "supportFormat",
| |
| helpLine = "support4line",
| |
| helpNumber = "support4number",
| |
| helpPage = "support4wiki-page-name",
| |
| helpString = "support4string",
| |
| helpTemplate = "support4wiki-template-name",
| |
| helpURL = "support4url",
| |
| helpUser = "support4wiki-user-name",
| |
| msgDescMiss = "solo",
| |
| tStylesTOCnum = "stylesTOCnum" },
| |
| -- 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 = {
| |
| div = false, -- <div class="mw-templatedata-doc-wrap">
| |
| got = false, -- table, initial templatedata object
| |
| heirs = false, -- table, params that are inherited
| |
| less = false, -- main description missing
| |
| lasting = false, -- old syntax encountered
| |
| lazy = false, -- doc mode; do not generate effective <templatedata>
| |
| leading = false, -- show TOC
| |
| -- low = false, -- 1= mode
| |
| order = false, -- parameter sequence
| |
| params = false, -- table, exported parameters
| |
| scream = false, -- error messages
| |
| sibling = false, -- TOC juxtaposed
| |
| slang = nil, -- project/user language code
| |
| slim = false, -- JSON reduced to plain
| |
| source = false, -- JSON input
| |
| strip = false, -- <templatedata> evaluation
| |
| tag = false, -- table, exported root element
| |
| title = false, -- page
| |
| tree = false -- table, rewritten templatedata object
| |
| }
| |
| local Permit = {
| |
| 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",
| |
| optional = "EAECF0",
| |
| deprecated = "FFCBCB" },
| |
| params = { aliases = "table",
| |
| autovalue = "string",
| |
| default = "string table I18N nowiki",
| |
| deprecated = "boolean string I18N",
| |
| description = "string table I18N",
| |
| example = "string table I18N nowiki",
| |
| label = "string table I18N",
| |
| inherits = "string",
| |
| required = "boolean",
| |
| style = "string table",
| |
| suggested = "boolean",
| |
| type = "string" },
| |
| root = { description = "string table I18N",
| |
| format = "string",
| |
| maps = "table",
| |
| params = "table",
| |
| paramOrder = "table",
| |
| sets = "table" },
| |
| search = "[{,]%%s*(['\"])%s%%1%%s*:%%s*%%{",
| |
| types = { boolean = true,
| |
| content = true,
| |
| date = true,
| |
| line = true,
| |
| number = true,
| |
| string = true,
| |
| unknown = true,
| |
| url = true,
| |
| ["wiki-file-name"] = true,
| |
| ["wiki-page-name"] = true,
| |
| ["wiki-template-name"] = true,
| |
| ["wiki-user-name"] = true,
| |
| ["unbalanced-wikitext"] = true,
| |
| ["string/line"] = "line",
| |
| ["string/wiki-page-name"] = "wiki-page-name",
| |
| ["string/wiki-user-name"] = "wiki-user-name" }
| |
| }
| |
|
| |
|
| | {{DEFAULTSORT:Topfertradition auf Gotland}} |
|
| |
|
| | | [[Kategorie:Handwerkstechnik]] |
| local function Fault( alert )
| | [[Kategorie:Werkstatt]] |
| -- Memorize error message
| | [[Kategorie:Töpferei|Etelhem]] |
| -- Parameter:
| | [[Kategorie:Künstlerische Technik]] |
| -- alert -- string, error message
| |
| if Data.scream then
| |
| Data.scream = string.format( "%s *** %s", Data.scream, alert )
| |
| else
| |
| Data.scream = alert
| |
| end
| |
| end -- Fault()
| |
| | |
| | |
| | |
| local function Fetch( ask, allow )
| |
| -- Fetch module
| |
| -- Parameter:
| |
| -- ask -- string, with name
| |
| -- "/global"
| |
| -- "JSONutil"
| |
| -- "Multilingual"
| |
| -- "Text"
| |
| -- "WLink"
| |
| -- allow -- true: no error if unavailable
| |
| -- Returns table of module
| |
| -- error: Module not available
| |
| 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
| |
| r = TemplateData.extern[ sign ]
| |
| else
| |
| TemplateData.extern = { }
| |
| end
| |
| if not r then
| |
| local lucky, g = pcall( require, sign )
| |
| if type( g ) == "table" then
| |
| if stem and type( g[ stem ] ) == "function" then
| |
| r = g[ stem ]()
| |
| else
| |
| r = g
| |
| end
| |
| TemplateData.extern[ sign ] = r
| |
| elseif not allow then
| |
| error( string.format( "Fetch(%s) %s", sign, g ) )
| |
| end
| |
| end
| |
| return r
| |
| 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()
| |
| | |
| | |
| | |
| local function facet( ask, at )
| |
| -- Find physical position of parameter definition in JSON
| |
| -- Parameter:
| |
| -- ask -- string, parameter name
| |
| -- at -- number, physical position within definition
| |
| -- Returns number, or nil
| |
| local seek = string.format( Permit.search,
| |
| ask:gsub( "%%", "%%%%" )
| |
| :gsub( "([%-.()+*?^$%[%]])",
| |
| "%%%1" ) )
| |
| local i, k = Data.source:find( seek, at )
| |
| local r, slice, source
| |
| while i and not r do
| |
| source = Data.source:sub( k + 1 )
| |
| slice = source:match( "^%s*\"([^\"]+)\"s*:" )
| |
| if not slice then
| |
| slice = source:match( "^%s*'([^']+)'%s*:" )
| |
| end
| |
| if ( slice and Permit.params[ slice ] ) or
| |
| source:match( "^%s*%}" ) then
| |
| r = k
| |
| else
| |
| i, k = Data.source:find( seek, k )
| |
| end
| |
| end -- while i
| |
| return r
| |
| end -- facet()
| |
| | |
| | |
| | |
| local function factory( adapt )
| |
| -- Retrieve localized text from system message
| |
| -- Parameter:
| |
| -- adapt -- string, message ID after "templatedata-"
| |
| -- Returns string, with localized text
| |
| local o = mw.message.new( "templatedata-" .. adapt )
| |
| if Foreign() then
| |
| o:inLanguage( Data.slang )
| |
| end
| |
| return o:plain()
| |
| end -- factory()
| |
| | |
| | |
| | |
| local function faculty( adjust )
| |
| -- Test template arg for boolean
| |
| -- adjust -- string or nil
| |
| -- Returns boolean
| |
| local s = type( adjust )
| |
| local r
| |
| if s == "string" then
| |
| r = mw.text.trim( adjust )
| |
| r = ( r ~= "" and r ~= "0" )
| |
| elseif s == "boolean" then
| |
| r = adjust
| |
| else
| |
| r = false
| |
| end
| |
| return r
| |
| end -- faculty()
| |
| | |
| | |
| | |
| local function failures()
| |
| -- Retrieve error collection and category
| |
| -- Returns string
| |
| local r
| |
| if Data.scream then
| |
| local e = mw.html.create( "span" )
| |
| :addClass( "error" )
| |
| :wikitext( Data.scream )
| |
| r = tostring( e )
| |
| mw.addWarning( "'''TemplateData'''<br />" .. Data.scream )
| |
| if Config.strange then
| |
| r = string.format( "%s[[category:%s]]",
| |
| r,
| |
| Config.strange )
| |
| end
| |
| else
| |
| r = ""
| |
| end
| |
| return r
| |
| end -- failures()
| |
| | |
| | |
| | |
| local function fair( adjust )
| |
| -- Reduce text to one line of plain text, or noexport wikitext blocks
| |
| -- adjust -- string
| |
| -- Returns string, with adjusted text
| |
| local f = function ( a )
| |
| return a:gsub( "%s*\n%s*", " " )
| |
| :gsub( "%s%s+", " " )
| |
| end
| |
| local r
| |
| if adjust:find( "<noexport>", 1, true ) then
| |
| local i = 1
| |
| local j, k = adjust:find( "<noexport>", i, true )
| |
| r = ""
| |
| while j do
| |
| if j > 1 then
| |
| r = r .. f( adjust:sub( i, j - 1 ) )
| |
| end
| |
| i = k + 1
| |
| j, k = adjust:find( "</noexport>", i, true )
| |
| if j then
| |
| r = r .. adjust:sub( i, j - 1 )
| |
| i = k + 1
| |
| j, k = adjust:find( "<noexport>", i, true )
| |
| else
| |
| Fault( "missing </noexport>" )
| |
| end
| |
| end -- while j
| |
| r = r .. adjust:sub( i )
| |
| else
| |
| r = f( adjust )
| |
| end
| |
| return r
| |
| 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 )
| |
| -- Retrieve best language version from multilingual text
| |
| -- Parameter:
| |
| -- alternatives -- table, to be evaluated
| |
| -- Returns
| |
| -- 1 -- string, with best match
| |
| -- 2 -- table of other versions, if any
| |
| local n = 0
| |
| local variants = { }
| |
| local r1, r2
| |
| for k, v in pairs( alternatives ) do
| |
| if type( v ) == "string" then
| |
| v = mw.text.trim( v )
| |
| if v ~= "" then
| |
| k = k:lower()
| |
| variants[ k ] = v
| |
| n = n + 1
| |
| end
| |
| end
| |
| end -- for k, v
| |
| if n > 0 then
| |
| local Multilingual = Fetch( "Multilingual", true )
| |
| if Multilingual and
| |
| type( Multilingual.i18n ) == "function" then
| |
| local show, slang = Multilingual.i18n( variants )
| |
| if show then
| |
| r1 = show
| |
| variants[ slang ] = nil
| |
| r2 = variants
| |
| end
| |
| end
| |
| if not r1 then
| |
| Foreign()
| |
| 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
| |
| end
| |
| end -- for k, v
| |
| end
| |
| if r2 and Multilingual then
| |
| for k, v in pairs( r2 ) do
| |
| if v and not Multilingual.isLang( k, true ) then
| |
| Fault( string.format( "%s <code>lang=%s</code>",
| |
| "Invalid",
| |
| k ) )
| |
| end
| |
| end -- for k, v
| |
| end
| |
| end
| |
| return r1, r2
| |
| 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" )
| |
| plus:css( "text-align", "left" )
| |
| 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()
| |
| | |
| | |
| | |
| local function fathers()
| |
| -- 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
| |
| for i = 1, n 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
| |
| 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
| |
| 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 -- for k, v
| |
| end
| |
| end -- i = 1, n
| |
| 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 -- for k, v
| |
| Fault( s )
| |
| end
| |
| end -- fathers()
| |
| | |
| | |
| | |
| 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
| |
| 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
| |
| 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
| |
| 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
| |
| 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 -- favorize()
| |
| | |
| | |
| | |
| local function feat()
| |
| -- Check and store parameter sequence
| |
| if Data.source then
| |
| local i = 0
| |
| local s
| |
| for k, v in pairs( Data.tree.params ) do
| |
| if i == 0 then
| |
| Data.order = { }
| |
| i = 1
| |
| s = k
| |
| else
| |
| i = 2
| |
| break -- for k, v
| |
| end
| |
| end -- for k, v
| |
| if i > 1 then
| |
| local pointers = { }
| |
| local points = { }
| |
| local given = { }
| |
| for k, v in pairs( Data.tree.params ) do
| |
| i = facet( k, 1 )
| |
| if type( v ) == "table" then
| |
| if v.label 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
| |
| table.insert( points, i )
| |
| pointers[ i ] = k
| |
| i = facet( k, i )
| |
| if i then
| |
| s = "Parameter '%s' detected twice"
| |
| Fault( string.format( s, k ) )
| |
| end
| |
| else
| |
| s = "Parameter '%s' not detected"
| |
| Fault( string.format( s, k ) )
| |
| end
| |
| end -- for k, v
| |
| table.sort( points )
| |
| for i = 1, #points do
| |
| table.insert( Data.order, pointers[ points[ i ] ] )
| |
| end -- i = 1, #points
| |
| elseif s then
| |
| table.insert( Data.order, s )
| |
| end
| |
| end
| |
| end -- feat()
| |
| | |
| | |
| | |
| local function feature( access )
| |
| -- Create table row for parameter, check and display violations
| |
| -- Parameter:
| |
| -- access -- string, with name
| |
| -- Returns <tr>
| |
| local mode, s, status
| |
| local fine = function ( a )
| |
| s = mw.text.trim( a )
| |
| return a == s and
| |
| a ~= "" and
| |
| not a:find( "%|=\n" ) and
| |
| not a:find( "%s%s" )
| |
| end
| |
| local begin = mw.html.create( "td" )
| |
| local code = mw.html.create( "code" )
| |
| local desc = mw.html.create( "td" )
| |
| local legal = true
| |
| local param = Data.tree.params[ access ]
| |
| local ranking = { "required", "suggested", "optional", "deprecated" }
| |
| local r = mw.html.create( "tr" )
| |
| local sort, typed
| |
| | |
| for k, v in pairs( param ) do
| |
| if v == "" then
| |
| param[ k ] = false
| |
| end
| |
| end -- for k, v
| |
| | |
| -- label
| |
| sort = param.label or access
| |
| if sort:match( "^%d+$" ) then
| |
| begin:attr( "data-sort-value",
| |
| string.format( "%05d", tonumber( sort ) ) )
| |
| end
| |
| begin:css( "font-weight", "bold" )
| |
| :wikitext( sort )
| |
| | |
| -- name and aliases
| |
| code:css( "font-size", "92%" )
| |
| :css( "white-space", "nowrap" )
| |
| :wikitext( access )
| |
| if not fine( access ) then
| |
| code:addClass( "error" )
| |
| Fault( string.format( "Bad ID params.<code>%s</code>", access ) )
| |
| legal = false
| |
| begin:attr( "data-sort-value", " " .. sort )
| |
| end
| |
| code = mw.html.create( "td" )
| |
| :node( code )
| |
| if access:match( "^%d+$" ) then
| |
| code:attr( "data-sort-value",
| |
| string.format( "%05d", tonumber( access ) ) )
| |
| end
| |
| if type( param.aliases ) == "table" then
| |
| local lapsus
| |
| for k, v in pairs( param.aliases ) do
| |
| code:tag( "br" )
| |
| if type( v ) == "string" then
| |
| if not fine( v ) then
| |
| lapsus = true
| |
| code:node( mw.html.create( "span" )
| |
| :addClass( "error" )
| |
| :css( "font-style", "italic" )
| |
| :wikitext( "string" ) )
| |
| end
| |
| code:wikitext( s )
| |
| else
| |
| lapsus = true
| |
| code:node( mw.html.create( "code" )
| |
| :addClass( "error" )
| |
| :wikitext( type( v ) ) )
| |
| end
| |
| end -- for k, v
| |
| if lapsus then
| |
| s = string.format( "params.<code>%s</code>.aliases", access )
| |
| Fault( factory( "invalid-value" ):gsub( "$1", s ) )
| |
| legal = false
| |
| end
| |
| end
| |
| | |
| -- description etc.
| |
| s = fashioned( param )
| |
| if s then
| |
| 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
| |
| if param.default or param.example or param.autovalue then
| |
| local details = { "default", "example", "autovalue" }
| |
| local dl = mw.html.create( "dl" )
| |
| local dd, section, show
| |
| for i = 1, #details do
| |
| s = details[ i ]
| |
| show = param[ s ]
| |
| if show then
| |
| dd = mw.html.create( "dd" )
| |
| section = factory( "doc-param-" .. s )
| |
| if param.type == "boolean" and
| |
| ( show == "0" or show == "1" ) then
| |
| local boole = Permit.boole[ ( show == "1" ) ]
| |
| if boole.lead == true then
| |
| dd:node( mw.html.create( "code" )
| |
| :wikitext( show ) )
| |
| :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
| |
| else
| |
| dd:wikitext( show )
| |
| end
| |
| dl:node( mw.html.create( "dt" )
| |
| :wikitext( section ) )
| |
| :node( dd )
| |
| end
| |
| end -- i = 1, #details
| |
| desc:node( dl )
| |
| end
| |
| | |
| -- type
| |
| if param.type then
| |
| s = Permit.types[ param.type ]
| |
| typed = mw.html.create( "td" )
| |
| if s then
| |
| if s == "string" then
| |
| Data.params[ access ].type = s
| |
| typed:wikitext( factory( "doc-param-type-" .. s ) )
| |
| :tag( "br" )
| |
| typed:node( mw.html.create( "span" )
| |
| :addClass( "error" )
| |
| :wikitext( param.type ) )
| |
| Data.lasting = true
| |
| else
| |
| local support = Config[ "support4" .. param.type ]
| |
| s = factory( "doc-param-type-" .. param.type )
| |
| if support then
| |
| s = string.format( "[[%s|%s]]", support, s )
| |
| end
| |
| typed:wikitext( s )
| |
| end
| |
| else
| |
| Data.params[ access ].type = "unknown"
| |
| typed:addClass( "error" )
| |
| :wikitext( "INVALID" )
| |
| s = string.format( "params.<code>%s</code>.type", access )
| |
| Fault( factory( "invalid-value" ):gsub( "$1", s ) )
| |
| legal = false
| |
| end
| |
| else
| |
| typed = mw.html.create( "td" )
| |
| :wikitext( factory( "doc-param-type-unknown" ) )
| |
| end
| |
| | |
| -- status
| |
| if param.required then
| |
| 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
| |
| Fault( string.format( "Required deprecated <code>%s</code>",
| |
| access ) )
| |
| legal = false
| |
| end
| |
| elseif param.deprecated then
| |
| mode = 4
| |
| elseif param.suggested then
| |
| mode = 2
| |
| else
| |
| mode = 3
| |
| end
| |
| status = ranking[ mode ]
| |
| ranking = factory( "doc-param-status-" .. status )
| |
| if mode == 1 or mode == 4 then
| |
| ranking = mw.html.create( "span" )
| |
| :css( "font-weight", "bold" )
| |
| :wikitext( ranking )
| |
| if type( param.deprecated ) == "string" then
| |
| ranking:tag( "br" )
| |
| ranking:wikitext( param.deprecated )
| |
| end
| |
| end
| |
| | |
| -- <tr>
| |
| r:attr( "id", "templatedata:" .. mw.uri.anchorEncode( access ) )
| |
| :css( Permit.css[ status ] )
| |
| :node( begin )
| |
| :node( code )
| |
| :node( desc )
| |
| :node( typed )
| |
| :node( mw.html.create( "td" )
| |
| :attr( "data-sort-value", tostring( mode ) )
| |
| :node( ranking ) )
| |
| :newline()
| |
| if not legal then
| |
| r:css( "border", "#FF0000 3px solid" )
| |
| end
| |
| return r
| |
| end -- feature()
| |
| | |
| | |
| | |
| local function features()
| |
| -- Create <table> for parameters
| |
| -- Returns <table>, or nil
| |
| local r
| |
| if Data.tree and Data.tree.params then
| |
| local tbl = mw.html.create( "table" )
| |
| :addClass( "wikitable" )
| |
| local tr = mw.html.create( "tr" )
| |
| feat()
| |
| if Data.order and #Data.order > 1 then
| |
| tbl:addClass( "sortable" )
| |
| end
| |
| -- if Config.classTable then
| |
| -- tbl:addClass( Config.classTable )
| |
| -- end
| |
| if Config.cssTable then
| |
| if type( Config.cssTable ) == "table" then
| |
| tbl:css( Config.cssTable )
| |
| elseif type( Config.cssTable ) == "string" then
| |
| -- deprecated
| |
| tbl:cssText( Config.cssTable )
| |
| end
| |
| end
| |
| tr:node( mw.html.create( "th" )
| |
| :attr( "colspan", "2" )
| |
| :css( Permit.css.tablehead )
| |
| :wikitext( factory( "doc-param-name" ) ) )
| |
| :node( mw.html.create( "th" )
| |
| :css( Permit.css.tablehead )
| |
| :wikitext( factory( "doc-param-desc" ) ) )
| |
| :node( mw.html.create( "th" )
| |
| :css( Permit.css.tablehead )
| |
| :wikitext( factory( "doc-param-type" ) ) )
| |
| :node( mw.html.create( "th" )
| |
| :css( Permit.css.tablehead )
| |
| :wikitext( factory( "doc-param-status" ) ) )
| |
| tbl:newline()
| |
| -- :node( mw.html.create( "thead" )
| |
| :node( tr )
| |
| -- )
| |
| :newline()
| |
| if Data.order then
| |
| local leave, s
| |
| for i = 1, #Data.order do
| |
| 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
| |
| 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
| |
| if Config.cssTabWrap or Data.scroll then
| |
| 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
| |
| r = tbl
| |
| end
| |
| end
| |
| return r
| |
| end -- features()
| |
| | |
| | |
| | |
| 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
| |
| if r:find( "&", 1, true ) then
| |
| r = mw.text.decode( r )
| |
| end
| |
| end
| |
| return r
| |
| end -- flat()
| |
| | |
| | |
| | |
| local function flush()
| |
| -- JSON encode narrowed input; obey unnamed (numerical) parameters
| |
| -- Returns <templatedata> JSON string
| |
| local r
| |
| if Data.tag then
| |
| r = mw.text.jsonEncode( Data.tag ):gsub( "%}$", "," )
| |
| else
| |
| r = "{"
| |
| end
| |
| r = r .. "\n\"params\":{"
| |
| 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
| |
| r = r .. "\n}\n}"
| |
| return r
| |
| end -- flush()
| |
| | |
| | |
| | |
| local function focus( access )
| |
| -- Check components; focus multilingual description, build trees
| |
| -- Parameter:
| |
| -- access -- string, name of parameter, nil for root
| |
| local f = function ( a, at )
| |
| local r
| |
| if at then
| |
| r = string.format( "<code>params.%s</code>", at )
| |
| else
| |
| r = "''root''"
| |
| end
| |
| if a then
| |
| r = string.format( "%s<code>.%s</code>", r, a )
| |
| end
| |
| return r
| |
| end
| |
| local parent
| |
| if access then
| |
| parent = Data.got.params[ access ]
| |
| else
| |
| parent = Data.got
| |
| 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
| |
| else
| |
| permit = Permit.root
| |
| end
| |
| for k, v in pairs( parent ) do
| |
| scope = permit[ k ]
| |
| if scope then
| |
| s = type( v )
| |
| if s == "string" and k ~= "format" then
| |
| v = mw.text.trim( v )
| |
| end
| |
| if scope:find( s, 1, true ) then
| |
| if scope:find( "I18N", 1, true ) then
| |
| if s == "string" then
| |
| elem = fair( v )
| |
| elseif s == "table" then
| |
| local translated
| |
| v, translated = faraway( v )
| |
| if v then
| |
| if translated and
| |
| k == "description" then
| |
| elem = { [ 1 ] = fair( v ),
| |
| [ 2 ] = translated }
| |
| else
| |
| elem = fair( v )
| |
| end
| |
| else
| |
| elem = false
| |
| end
| |
| end
| |
| if type( v ) == "string" 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 = elem:gsub( " \n", "<br>" )
| |
| v = v:gsub( string.char( 13 ), "" )
| |
| else
| |
| 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
| |
| 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
| |
| 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
| |
| else
| |
| Fault( "Unknown component " .. f( k, slot ) )
| |
| end
| |
| end -- for k, v
| |
| else
| |
| Fault( f() .. " needs to be of <code>object</code> type" )
| |
| end
| |
| end -- focus()
| |
| | |
| | |
| | |
| 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 or "inline"
| |
| code = code or "{{_|_=_}}"
| |
| 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 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
| |
| 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
| |
| -- 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( "h2" )
| |
| :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
| |
| return r
| |
| end -- formatter()
| |
| | |
| | |
| | |
| local function free()
| |
| -- Remove JSON comment lines
| |
| Data.source:gsub( "([{,\"'])(%s*\n%s*//.*\n%s*)([},\"'])",
| |
| "%1%3" )
| |
| end -- free()
| |
| | |
| | |
| | |
| local function full()
| |
| -- 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
| |
| Data.div:node( formatter() )
| |
| if not Data.lazy then
| |
| Data.slim = flush()
| |
| if TemplateData.frame then
| |
| 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" )
| |
| :css( { height = "7ex" } ) )
| |
| else
| |
| div:css( "display", "none" )
| |
| end
| |
| Data.div:node( div )
| |
| end
| |
| end
| |
| if Data.lasting then
| |
| Fault( "deprecated type syntax" )
| |
| end
| |
| if Data.less then
| |
| Fault( Config.solo )
| |
| 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 -- for k, v
| |
| Config.loudly = faculty( arglist.debug or adapt.debug )
| |
| Data.lazy = faculty( arglist.lazy ) and not Config.loudly
| |
| 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
| |
| 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
| |
| if type( arglist.vertical ) == "string" and
| |
| arglist.vertical:match( "^%d*%.?%d+[emprx]+$" ) then
| |
| 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 ( atleast )
| |
| -- Retrieve versioning and check for compliance
| |
| -- Precondition:
| |
| -- atleast -- string, with required version or "wikidata"
| |
| -- or false
| |
| -- Postcondition:
| |
| -- Returns string with appropriate version, or false
| |
| local since = atleast
| |
| 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()
| |
| | |
| | |
| | |
| 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()
| |
| | |
| | |
| | |
| TemplateData.getPlainJSON = function ( adapt )
| |
| -- Reduce enhanced JSON data to plain text localized JSON
| |
| -- Parameter:
| |
| -- adapt -- string, with enhanced JSON
| |
| -- Returns string, or not
| |
| if type( adapt ) == "string" then
| |
| local JSONutil = Fetch( "JSONutil", true )
| |
| Data.source = adapt
| |
| free()
| |
| if JSONutil 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()
| |
| elseif not Data.strip then
| |
| Fault( "fatal JSON error: " .. Data.got )
| |
| end
| |
| end
| |
| return Data.slim
| |
| end -- TemplateData.getPlainJSON()
| |
| | |
| | |
| | |
| TemplateData.test = function ( adapt, arglist )
| |
| TemplateData.frame = mw.getCurrentFrame()
| |
| return furnish( adapt, arglist )
| |
| end -- TemplateData.test()
| |
| | |
| | |
| | |
| -- Export
| |
| local p = { }
| |
| | |
| p.f = function ( frame )
| |
| -- Template call
| |
| local lucky, r
| |
| TemplateData.frame = frame
| |
| lucky, r = pcall( furnish, frame.args, frame:getParent().args )
| |
| if not lucky then
| |
| Fault( "INTERNAL: " .. r )
| |
| r = failures()
| |
| end
| |
| return r
| |
| end -- p.f()
| |
| | |
| p.failsafe = function ( frame )
| |
| -- Versioning interface
| |
| local s = type( frame )
| |
| local since
| |
| if s == "table" then
| |
| since = frame.args[ 1 ]
| |
| elseif s == "string" then
| |
| since = frame
| |
| end
| |
| if since then
| |
| since = mw.text.trim( since )
| |
| if since == "" then
| |
| since = false
| |
| end
| |
| end
| |
| return TemplateData.failsafe( since ) or ""
| |
| end -- p.failsafe()
| |
| | |
| p.TemplateData = function ()
| |
| -- Module interface
| |
| return TemplateData
| |
| end
| |
| | |
| return p
| |