Module:TemplateDataGenerator

--[=[ 2013-08-05

Basic idea by w:en:User:Salix alba ]=]

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: --    &#x3e;  config.shift --    &#x3e;  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 &#x3e; 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: --    &#x3e;  config.luxury --    &#x3e;  config.start --    &#x3e;  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&#x3c;templatedata&#x3e;\n%s\n&#x3c;/templatedata&#x3e;\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 "&#x3c;pre&#x3e;" .. r .. "&#x3c;/pre&#x3e;"; return r;

end -- .f

return p;