Модуль:TemplateDataGenerator
Для документации этого модуля может быть создана страница Модуль:TemplateDataGenerator/doc
--[=[ 2013-08-05 {{TemplateDataGenerator}} Basic idea by [[w:en:User:Salix alba]] в doc шаблона подстановка {{subst:#invoke:TemplateDataGenerator|f}} ]=] local config = { luxury = false, -- default alphabetical order for parameter list start = false, -- preceeding lines shift = " ", -- (not used now) indentation, like " " or "\t" suffix = false, -- following lines scheme = [=["%s": { "label": "%s", "description": "", "type": "string", "required": false }]=] -- config.scheme has placeholders %s -- for the parameter name and for "label". -- One of various indentation styles. -- Feel free to compose a different one, also using config.shift etc. }; local function factory( analyze, alphabetical ) -- Make parameter sequence from template source text -- analyze -- string; template source text -- alphabetical -- boolean or nil; sort parameter list -- Return: -- table (sequence) with parameter names local i, s; local r = { }; for s in analyze:gmatch( "{{{([^|}\n]+)" ) do for i = 1, #r do if r[ i ] == s then s = false; break; -- for i end end -- for i if s then table.insert( r, s ); end end -- for s in :gmatch() if alphabetical then table.sort( r, nil ); end return r; end -- factory() local function format( analyze, alphabetical ) -- Make JSON code from template source text -- analyze -- string; template source text -- alphabetical -- boolean or nil; sort parameter list -- Return: -- string with JSON code -- Uses: -- > config.shift -- > config.scheme -- factory() local i; local params = factory( analyze, alphabetical ); local r = '{ "description": "",\n'; -- local shift = config.shift or ""; -- currently unused local start = " "; local show, symbol; r = r .. ' "params": { '; for i = 1, #params do if i > 1 then r = string.format( "%s,\n%s ", r, start ); end symbol = params[ i ]; if mw.ustring.match( symbol, "^%u%u" ) then show = mw.ustring.sub( symbol, 1, 1 ) .. mw.ustring.lower( mw.ustring.sub( symbol, 2 ) ); else show = ""; end r = r .. string.format( config.scheme, symbol, show ); -- common JSON pattern is ASCII; string.format() will do end -- for i r = string.format( "%s\n%s}\n}", r, start ); return r; end -- format() local function fun( attempt, alphabetical ) -- Retrieve used template params and build TemplateData skeleton -- Precondition: -- attempt -- mw.title object; related to template code -- alphabetical -- boolean or nil; sort parameter list -- Return: -- string to be applied -- Uses: -- > config.luxury -- > config.start -- > config.suffix -- format() local r; local source = string.match( attempt.baseText .. "/", "^([^/]+)/" ); -- ensure top page in NS with no subpage property -- note that pattern is ASCII; string.match() will do local title = mw.title.makeTitle( attempt.namespace, source ); if title.exists then local luxury = config.luxury; local spec = "%s<templatedata>\n%s\n</templatedata>\n%s"; if type( alphabetical ) == "boolean" then luxury = alphabetical; end if config.start then r = config.start .. "\n"; else r = ""; end r = string.format( spec, r, format( title:getContent(), luxury ), config.suffix or "" ); -- note that format spec is ASCII only; string.format() will do else -- test only r = "ERROR * no page " .. title.fullText; end return r; end -- fun() -- Export local p = {}; function p.getBlock( pagetitle, namespace, alphabetical ) -- Precondition: -- pagetitle -- string; page title related to template code -- namespace -- string, number or nil; namespace (Template:) -- alphabetical -- boolean or nil; sort parameter list -- Uses: -- fun() local title = mw.title.makeTitle( namespace or 10, pagetitle ); local lucky, r = pcall( fun, title, alphabetical ); return r; end -- .getBlock() function p.f( frame ) -- Precondition: -- frame -- object -- Invoked on a template page or template subpage. -- Uses: -- fun() local luxury; local parental = frame:getParent().args; local sort = parental[ 1 ] or parental[ "1" ] or parental.sort; if sort then luxury = ( tonumber( sort) == 1 ); end local lucky, r = pcall( fun, mw.title.getCurrentTitle(), luxury ); -- return "<pre>" .. r .. "</pre>"; return r; end -- .f() return p;