Jump to content

Module:Sandbox/Jeblad/LuaDoc

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Jeblad (talk | contribs) at 21:55, 21 January 2016 (Created page with '--- 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...'). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)

  1. ^ "Block Tags". @use JSDoc.
--- 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. Especaially,
-- it makes no attempt to do a deeper analysis of the provided code.
local luadoc = {}

-- don't pollute with globals
require('Module:No globals')

local Frag= {}
Frag.__index = Frag

setmetatable(Frag, {
  __call = function (cls, ...)
    local self = setmetatable({}, cls)
    self:_init(...)
    return self
  end,
})

function Frag:_init( t )
  self['_class'] = t['class']
  self['_summary'] = t['summary']
  self['_desc'] = t['desc']
end

function Frag:renderClass( t )
	local html = mw.html.create( 'div' )
	:addClass( 'tagline' )
	:wikitext( self['_summary'] )
	return html
end

function Frag:renderSummary( t )
	local html = mw.html.create( 'div' )
	:addClass( 'summary' )
	:wikitext( self['_summary'] )
	return html
end

function Frag:renderDesc( t )
	local html = mw.html.create( 'div' )
	:addClass( 'desc' )
	:wikitext( self['_desc'] )
	return html
end

function Frag:render( parent, t )
	parent
		:append(self:renderClass(t))
		:append(self:renderSummary(t))
		:append(self:renderDesc(t))
	return parent
end

local Mod = {}
Mod.__index = Mod

setmetatable(Mod, {
  __index = Frag,
  __call = function (cls, ...)
    local self = setmetatable({}, cls)
    self:_init(...)
    return self
  end,
})

function Mod:_init( t )
  Frag._init(self, t)
end

function Frag:render( parent, t )
	return parent
end

local Var = {}
Var.__index = Var

setmetatable(Var, {
  __index = Frag,
  __call = function (cls, ...)
    local self = setmetatable({}, cls)
    self:_init(...)
    return self
  end,
})

function Var:_init( t )
  Frag._init(self, t)
  self['_var'] = t['var']
end

function Var:renderVar( t )
	local html = mw.html.create( 'div' )
	:addClass( 'var' )
	:wikitext( self['_var'] )
	return html
end

local Func = {}
Func.__index = Func

setmetatable(Func, {
  __index = Frag,
  __call = function (cls, ...)
    local self = setmetatable({}, cls)
    self:_init(...)
    return self
  end,
})

function Func:_init( t )
  Frag._init(self, t)
  self['_param'] = t['param']
  self['_return'] = t['return']
end

function Func:renderParam( t )
	local html = mw.html.create( 'div' )
	:addClass( 'param' )
	:wikitext( self['_param'] )
	return html
end

function Func:renderReturn( t )
	local html = mw.html.create( 'div' )
	:addClass( 'return' )
	:wikitext( self['_return'] )
	return html
end

local parse = {
	['module'] = Mod,
	['function'] = Func,
	['variable'] = Var,
}

local function loadDoc( namespace, text )
	local title = mw.title.new( text, namespace )
	assert( title, 'Unknown title')
	local content = title:getContent()
	assert( content, 'Got no content' )
	return content
end

local function parseFragment( frag )
	if frag._class and frag['var'] then
		for i,v in ipairs(frag['var']) do
			frag._class = 'variable'
			break
		end
	end

	if frag._class and frag['param'] then
		for i,v in ipairs(frag['param']) do
			frag._class = 'function'
			break
		end
	end

	if frag._class and frag['return'] then
		for i,v in ipairs(frag['return']) do
			frag._class = 'function'
			break
		end
	end

	if frag._class and frag['code'] then
		for i,v in ipairs(frag['code']) do
			if line:match( 'function' ) then
				frag._class = 'function'
				break
			end
		end
	end

	local constructor = parse[frag._class]
	assert( constructor, 'Unknown class' )
	
	return constructor( frag )
end

local function parseDoc( code )
	local fragments = {}
	local fragment = { ["_class"] = 'module', ["lines"] = 0 }
	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 = { ["_class"] = nil, ["lines"] = 0 }
			end
			fragment ={}
			last = '_desc'
			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

	return fragments
end

if 1 or _G['_BDD'] then
	luadoc.Mod = Mod
	luadoc.Var = Var
	luadoc.Func = Func
	luadoc.loadDoc = loadDoc
end

function luadoc.build( frame )
	local docs = {}
	for _,v in ipairs( frame.args ) do
		local str = mw.text.trim( v )
		if str == '' then
			-- do nothing
		else
			-- local name or canonical name, at english only canonical name
			if str:match( '^[mM]module:' ) then
				local namespace = str:match( '^(%S-)%s*:' )
				local text = str:match( ':%s*(.-)%s*$' )
				local code = loadDoc( text, namespace )
				docs[1+#docs] = parseDoc( code )
			end
		end
	end
	local parent = mw.html.create( 'div' )
	for _,v in ipairs( docs ) do
		parent:append(v:render())
	end
	return parent
end

return luadoc