--This code is work in progress, with all the problems that imply.Note that documentation in this module is made to test various aspects of themodule itself. Because of this the documentation isn't complete, and can evenbe bogus.--
--- Format documentation of a module and make it linkable-- The module makes some assumptions about the layout, basically the same as-- JavaDoc and LuaDoc, but does not follow those examples strictly. Especially,-- it makes no attempt to do a deeper analysis of the provided code.-- @author -- @copyright [mailto:jeblad@gmail.com]-- @license Creative Commons: Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) local luadoc =
-- don't pollute with globalsrequire('strict')
--- Registry for fragment typeslocal fragTypes =
--- Registry for access pointslocal access =
--- Table acting as a baseclass for fragments-- @access private-- @var ..?-- @field _class string acting as a class marker for the fragment-- @field _summary table holding the summary (the first line of the description) for the fragment-- @field _description table holding the description (the remaining text of the description) for the fragmentlocal Frag = Frag.__index = Frag
setmetatable(Frag,)
--- Initialiser for the Frag class-- @param t table holding data used during initializationfunction Frag:_init(t) self['_class'] = t['_class'] self['_weight'] = t['_weight'] self['_summary'] = t['_summary'] self['_description'] = t['_description']end
--- Weight of the given class viewed as a possible Frag instance-- @param t table holding data used during initializationfunction Frag.weightOfClass(t) local weight = 0 weight = weight + Frag.weightOfClassDescription(t) weight = weight + Frag.weightOfClassSignature(t['_code']) return weightend
--- Weight of the given description viewed as a possible Frag instance-- @param s string holding a code snippetfunction Frag.weightOfClassDescription(s) local weight = 0 return weightend
--- Weight of the given signature viewed as a possible Frag instance-- @param s string holding a code snippetfunction Frag.weightOfClassSignature(s) local weight = 0 return weightend
--- Render method for the class member field-- @param t table for optional data used while renderingfunction Frag:renderClass(t) local html = mw.html.create('div') :addClass('luadoc-tagline') :wikitext(self['_class']) return htmlend
--- Render method for the weight member field-- @param t table for optional data used while renderingfunction Frag:renderWeight(t) local html = mw.html.create('div') :addClass('luadoc-weight') :wikitext(self['_weight']) return htmlend
--- Render method for the summary member field-- @param t table for optional data used while renderingfunction Frag:renderSummary(t) local html = mw.html.create('div') :addClass('luadoc-summary') :wikitext(self['_summary']) return htmlend
--- Render method for the description member field-- @param t table for optional data used while renderingfunction Frag:renderDescription(t) local html = mw.html.create('div') :addClass('luadoc-description') :wikitext(self['_description']) return htmlend
--- Render method for the total Frag structure-- @param t table for optional data used while rendering-- @return table the extended parentfunction Frag:render(t) local html = mw.html.create('div') :addClass('luadoc-fragment') html :node(self:renderClass(t)) :node(self:renderWeight(t)) :node(self:renderSummary(t)) :node(self:renderDescription(t)) return htmlend
--- Table acting as a subclass for varables-- @var ..?-- @field _var string ..?-- @access privatelocal Var = Var.__index = Var
fragTypes['variable'] = Var
setmetatable(Var,)
--- Initialiser for the Var class-- @param t table holding data used during initializationfunction Var:_init(t) Frag._init(self, t) self['_var'] = t['_var']end
--- Weight of the given class viewed as a possible Var instance-- @param t table holding data used during initializationfunction Var.weightOfClass(t) local weight = 0 weight = weight + Var.weightOfClassDescription(t) weight = weight + Var.weightOfClassSignature(t['_code']) return weightend
--- Weight of the given description viewed as a possible Var instance-- @param t table holding data used during initializationfunction Var.weightOfClassDescription(t) local weight = 0 if not t then return weight end weight = weight + Frag.weightOfClassDescription(t) weight = weight + (t._class
--- Weight of the given signature viewed as a possible Var instance-- @param s string holding a code snippetfunction Var.weightOfClassSignature(s) local weight = 0 if not s then return weight end weight = weight + Frag.weightOfClassSignature(s) local exclude = local loc, nme = s:match('(local)%s+([_%a][_%a%d]*)') if loc and not exclude[nme] then weight = weight + 25 end local nme, eqv = s:match('([_%a][_%a%d]*)%s+(=)') if eqv and not exclude[nme] then weight = weight + 25 end return weightend
function Var:renderVar(t) local html = mw.html.create('div') :addClass('luadoc-variable') :wikitext(self['_var']) return htmlend
--- Render method for the total Var structure-- @param t table for optional data used while rendering-- @return table the extended parentfunction Var:render(t) local html = Frag.render(self, t) return htmlend
--- Table acting as a subclass for modules-- @var ..?-- @access privatelocal Mod = Mod.__index = Mod
fragTypes['module'] = Mod
setmetatable(Mod,)
--- Initialiser for the Mod class-- @param t table holding data used during initializationfunction Mod:_init(t) Frag._init(self, t)end
--- Weight of the given class viewed as a possible Frag instance-- @param t table holding data used during initializationfunction Mod.weightOfClass(t) local weight = 0 weight = weight + Mod.weightOfClassDescription(t) weight = weight + Mod.weightOfClassSignature(t['_code']) return weightend
--- Weight of the given description viewed as a possible Mod instance-- @param t table holding data used during initializationfunction Mod.weightOfClassDescription(t) local weight = 0 if not t then return weight end weight = weight + Var.weightOfClassDescription(t) weight = weight + (t._class
--- Weight of the given signature viewed as a possible Mod instance-- @param s string holding a code snippetfunction Mod.weightOfClassSignature(s) local weight = 0 if not s then return weight end weight = weight + Var.weightOfClassSignature(s) if s:match('^[\t]*[\n\r]') then weight = weight + 25 end return weightend
--- Render method for the total Mod structure-- @param t table for optional data used while rendering-- @return table the extended parentfunction Mod:render(t) local html = Frag.render(self, t) return htmlend
--- Table acting as a subclass for modules-- @var ..?-- @access privatelocal Ret = Ret.__index = Ret
fragTypes['return'] = Ret
setmetatable(Ret,)
--- Initialiser for the ret class-- @param t table holding data used during initializationfunction Ret:_init(t) Frag._init(self, t)end
--- Weight of the given class viewed as a possible Ret instance-- @param t table holding data used during initializationfunction Ret.weightOfClass(t) local weight = 0 weight = weight + Ret.weightOfClassDescription(t) weight = weight + Ret.weightOfClassSignature(t['_code']) return weightend
--- Weight of the given description viewed as a possible ret instance-- @param t table holding data used during initializationfunction Ret.weightOfClassDescription(t) local weight = 0 if not t then return weight end weight = weight + Frag.weightOfClassDescription(t) return weightend
--- Weight of the given signature viewed as a possible Ret instance-- @param s string holding a code snippetfunction Ret.weightOfClassSignature(s) local weight = 0 if not s then return weight end weight = weight + Frag.weightOfClassSignature(s) if s:match('(return)%s+([_%a][_%a%d]*)') then weight = weight + 25 end return weightend
--- Render method for the total Ret structure-- @param t table for optional data used while rendering-- @return table the extended parentfunction Ret:render(t) local html = Frag.render(self, t) return htmlend
--- Table acting as a subclass for functions-- @var ..?-- @field _param table holding all params to the function-- @field _return table holding all returns from the function-- @access privatelocal Func = Func.__index = Func
fragTypes['function'] = Func
setmetatable(Func,)
--- Initialiser for the Func class-- @param t table holding data used during initializationfunction Func:_init(t) Frag._init(self, t) self['_param'] = t['_param'] self['_return'] = t['_return']end
--- Weight of the given class viewed as a possible Func instance-- @param t table holding data used during initializationfunction Func.weightOfClass(t) local weight = 0 weight = weight + Func.weightOfClassDescription(t) weight = weight + Func.weightOfClassSignature(t['_code']) return weightend
--- Weight of the given description viewed as a possible Func instance-- @param t table holding data used during initializationfunction Func.weightOfClassDescription(t) local weight = 0 if not t then return weight end weight = weight + Var.weightOfClassDescription(t) weight = weight + (t._class
--- Weight of the given signature viewed as a possible Func instance-- @param s string holding a code snippetfunction Func.weightOfClassSignature(s) local weight = 0 if not s then return weight end weight = weight + Var.weightOfClassSignature(s) local include = local loc, nme = s:match('(local)%s+([_%a][_%a%d]*)') if loc and include[nme] then weight = weight + 25 end local eqv,nme = s:match('(=)%s+([_%a][_%a%d]*)') if eqv and include[nme] then weight = weight + 25 end return weightend
function Func:renderParam(t) local html = mw.html.create('div') :addClass('luadoc-parameter') :wikitext(self['_param']) return htmlend
function Func:renderReturn(t) local html = mw.html.create('div') :addClass('luadoc-return') :wikitext(self['_return']) return htmlend
--- Render method for the total Func structure-- @param parent table reference to the containing element-- @param t table for optional data used while rendering-- @return table the parent make the method chainable-- @return table the extended parentfunction Func:render(t) local html = Frag.render(self, t) return htmlend
--- Load page identified by text and namespace-- @since somedate-- @param text string base name and any subparts-- @param namespace string containing the namespace on a valid form-- @return string in a raw form according to the content model-- @throw string verbatim 'Unknown' if can't find a valid title object-- @throw string verbatim 'Got no content' if can't get contentlocal function loadDoc(text, namespace) local title = mw.title.new(text, namespace) assert(title, 'Unknown title') local content = title:getContent assert(content, 'Got no content') return contentend
--- Create a fragment according to a best guess-- @param frag table containing a single fragment-- @return table as a subclass of Fraglocal function createFragment(frag) local maxWeight = -1000 local clss = nil local name = nil for k,v in pairs(fragTypes) do local weight = v.weightOfClass(frag) if weight > maxWeight then maxWeight = weight clss = v name = k end end
frag._weight = maxWeight if maxWeight>=0 then frag._class = name return clss(frag) --return Frag(frag) end frag._class = 'unknown' return Frag(frag)end
--- Strip provided code for block comments-- @since somedate-- @param code string providing the program-- @return string clensed for block commentslocal function stripBlockComments(code) local collapse = function(s) return s:gsub('^%-%-%[(=*)%[.*]%1%]$', ) end return code:gsub('(%-%-+%b[])', collapse)end
--- Split provided code in fragments-- @x-access public this should be public if everything works out-- @since somedate-- @param code string providing the program-- @return table of fragmentslocal function splitOutFragments(code) local fragments = local fragNum = 0 for slice in mw.text.gsplit(code, "\n%s*%-%-%-%s*") do fragNum = 1+fragNum if not slice:match('^%s*$') then local fragment = if fragNum
1 and 'module' or 'unknown' slice = slice:gsub('^%s*%-%-%-[\ \t]*([^\n\r]+)[\n\r]*', function(str) fragment._summary = str; return end) else fragment._class = #fragment
--- Parse provided code-- @x-access public this will be private if everything works out-- @deprecated somedate this call will not be used-- @param code string providing the program-- @return table of fragmentslocal function parseCode(code) local fragments = local fragment = local last = nil for line in code:gmatch('([^\n]+)') do local desc = line:match('^\s*%-%-%-\s*(.+)') if desc then if fragment.lines > 0 then fragments[1+#fragments] = parseFragment(fragment) fragment = end fragment = last = '_description' fragment[last] = desc else if line:match('^\s*--') then local attr, text = line:match('^\s*%-%-\s*@(\w+)\s+(.*)') if attr then last = '_'..attr if not fragment[last] then fragment[last] = end fragment[last][1+#fragment[last]] = text else local text = line:match('^\s*--\s*(.*)') fragment[last][#fragment[last]] = text end else last = '_code' fragment[last] = line end end end -- @todo check if last fragment is empty return fragmentsend
if 1 or _G['_BDD'] then luadoc.Frag = Frag luadoc.Mod = Mod luadoc.Ret = Ret luadoc.Var = Var luadoc.Func = Func luadoc.loadDoc = loadDoc luadoc.createFragment = createFragmentend
--- Invokable method to build a document-- @access public-- @param frame table for contextual information-- @return string for display on a rendered pagefunction luadoc.build(frame) local docs = for _,v in ipairs(frame.args) do local str = mw.text.trim(v) if str
--- Final return of the provided modulereturn luadoc