Module:Tdoc
Jump to navigation
Jump to search
local p = {}
--------------------
local split = table.concat
local push = table.insert
--------------------
local mwTitle = mw.title.getCurrentTitle()
local pagename = mwTitle.text
local fullpagename = mwTitle.prefixedText
------------
local getArgs = require( 'Module:Arguments' ).getArgs
local wiki = require( 'Module:WikitextUtils' )
local HtmlRawElement = wiki.rawElementt
local QuotesStr = wiki.QuotesStr
local makeWikilink = wiki.makeWikilink
--------------------
--
-- "params" relation makes this difficult to return cleanly
local defaultSkeletonFields = {}
--
-- "ingroup" tag for behavior switches
local funcGroup = ''
--
-- Module: Tdoc - template documentation generator
--------------------
local tagList = mw.loadData( 'Module:Tdoc/tags' )
--
--------------------
local docTypeClasses = {
['Template'] = {
title = 'Template',
format = 'Template:FuncName',
},
['Parser functions'] = {
title = 'Hook',
category = 'Parser function hooks',
format = 'FuncName',
},
['Parser extension tags'] = {
title = 'Tag',
category = 'Parser extension tags',
format = '<FuncName>',
},
}
-- /*
-- * @return string Current running version of Lua on this server.
-- * @see https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#_VERSION
-- */
function p.getLuaVersion()
return _VERSION
end
-- /**
-- * @param int ns // namespace number
-- * @param string page // full page name
-- * @return bool, array // default cat or ingroup, type config
-- */
--------------------
function getTypeInfo( ns, page )
if ns == 10 then
return false, docTypeClasses['Template']
elseif ns == 12 then --help
return true, docTypeClasses[page]
end
end
-- /**
-- * @param string arg // tag + value pair to split
-- * @return string, string // tag name, tag value
-- */
--------------------
function splitTagKey( arg )
return string.match( arg, '^@(%S+)%s+(.+)' )
end
-- /**
-- * make a simple <dl> list w/ CSS class and full title
-- *
-- * @param string part // wikitext variable to retrieve
-- * @param string class // CSS class name
-- * @param string content // content string to process
-- * @return string // formatted HTML element
-- */
function makeDlList( tag, class, content, title )
return HtmlRawElement( 'dl', { ['class'] = ( class or '' ) .. tag },
HtmlRawElement( 'dt', {}, title )
.. HtmlRawElement( 'dd', {}, content )
)
end
-- /**
-- * prepend sub-headers for each of the main {{tdoc}} fields.
-- *
-- * @param string tag // name of tag group to process
-- * @param array content // instances of the respective tag
-- * @return string // formatted HTML element
-- */
function makeSubSection( tag, content, ns )
if string.match( tag, "^user%d" ) then
local tempContentFormat
if content[1] == 'Accepted values' then
tempContentFormat = content[2]
else
tempContentFormat = SyntaxHighlight( 'text', content[2] )
end
return makeDlList( tag, '', tempContentFormat, content[1] )
end
local tagCheck = tagList[tag]
local class = nil
if tagCheck ~= nil then
class = tagCheck.format
title = tagCheck.title
end
if class == 'section' then
return makeDlList( tag, 'section ', split ( content, '<br/>' ), title )
elseif class == 'params' then
return makeDlList( tag, '', makeParamsRows( tag, content ), title )
elseif class == 'comment' then
return makeDlList( tag, '', split ( content ), title )
elseif class == nil then
return HtmlRawElement( 'p', {}, content )
elseif class == 'transclude' and ns == 10 then
local categories = {}
for i, item in ipairs( content ) do
funcGroup = item --save outside
push( categories, '[[Category:' .. item .. ' templates]]' )
end
return split( categories )
else return ''
end
end
-- /**
-- * Process parameters for 'param', 'throws' tags
-- *
-- * @param string key // tag name
-- * @returns string // HTML table output
-- */
function makeParamsRows( key, rows )
local tag = tagList[key]
local subParams = tag.subparams
local pattern = { '^' }
for i = 1, #subParams do
push( pattern, '(%S+)%s+' )
end
pattern = split( pattern, '' ) .. '(.+)'
local paramRows = {}
for r, row in ipairs( rows ) do
------
--temp. replacement for concat issue
if key == 'param' then
row = { string.match( row, '^(%S+)%s+(%S+)%s+(.+)' ) }
elseif key == 'throws' then
row = { string.match( row, '^(%S+)%s+(.+)' ) }
end
------
local paramCells = {}
for f, field in ipairs( subParams ) do
local value = row[f]
if key == 'param' and field == 'name' then
local param, default = string.match( value, '(%S+)¦(%S+)' )
value = param or value
local rawName = string.gsub( value, '%$', '' )
push( defaultSkeletonFields,
'|' .. rawName .. '=' .. ( default or '' ) )
end
paramCells[f] = HtmlRawElement( 'td', {
['class'] = 'param' .. field,
}, value or 'null' )
end
paramRows[r] = HtmlRawElement( 'tr', {}, split( paramCells ) )
end
return HtmlRawElement( 'table', {
['class'] = tag.key or key,
}, split( paramRows ) )
end
-- /**
-- * @param object frame
-- */
function p.Main( frame )
local ogTitle = getArgs( frame ).title
local parentTitle = mw.title.new( ogTitle )
thisPageUsing = {}
thisPageOrder = {}
for keyName, _ in pairs( tagList ) do
thisPageUsing[keyName] = {}
end
local args = getArgs( frame:getParent(), {
removeBlanks = false
} )
for i, arg in ipairs( args ) do
if string.match( arg, '%S+' ) then
local tagName, tagContent = splitTagKey( arg )
if tagName == nil then
local fullblock = "plaintext" .. tonumber(i)
thisPageUsing['fullblock'] = arg
push( thisPageOrder, 'fullblock' )
elseif tagName == 'par' then
local customKeyName = "user" .. tostring( i )
local _, tagUserContent = splitTagKey( args[i + 1] )
-- maybe loop til != nil
thisPageUsing[customKeyName] = { tagContent, tagUserContent }
push( thisPageOrder, customKeyName )
args[i + 1] = '' -- nil will break
elseif tagList[tagName] ~= nil then
if next( thisPageUsing[tagName] ) == nil then
push( thisPageOrder, tagName )
end
push( thisPageUsing[tagName], tagContent )
end
end
end
for i, key in ipairs( thisPageOrder ) do
thisPageOrder[i] = makeSubSection( key, thisPageUsing[key], parentTitle.namespace )
end
local out = p.outputContainer( frame, thisPageOrder, parentTitle )
return frame:preprocess( out )
end
function upperCheck( name )
--probably gets treated as template
--maybe just ingroups
local out = mw.getCurrentFrame()
local funcCall = string.upper( name )
local funcTest = out:preprocess( '{{' .. funcCall .. '}}' )
if mw.ustring.find( funcTest, 'Template' ) == nil then
-- ~= out:preprocess( '[[Template:' .. funcCall .. ']]' ) then
return true
end
------
-- local varGroups = { 'Page names', 'Statistics' }
-- for i, groupName in ipairs( varGroups ) do
-- if group == groupName then return true end
-- end
end
function printSkelParams( params )
return '\n' .. split( params, '\n' ) .. '\n'
end
function makeSkeleton( funcType, funcName )
if funcType == 'Template' then
skelParams = printSkelParams( defaultSkeletonFields )
elseif funcType == 'Hook' then
if upperCheck( funcName ) == true then
funcName = string.upper( funcName )
else
funcName = '#' .. funcName .. ':'
if #defaultSkeletonFields then
local firstParam = string.gsub( defaultSkeletonFields[1], '|', ' ' )
table.remove( defaultSkeletonFields, 1 )
skelParams = firstParam .. printSkelParams( defaultSkeletonFields )
end
end
end
return HtmlRawElement( 'pre', {},
'{{' .. funcName .. ( skelParams or '' ) .. '}}'
)
end
function p.outputContainer( frame, thisPageOrder, parentTitle )
local options = '[[Help:Template documentation|Help]]' --getTemplateStyles( args["TemplateStyles"] or '' )
local baseCat, docClass = getTypeInfo( parentTitle.namespace, parentTitle.rootText )
local funcName = mwTitle.subpageText
local docHeader = subTable( { ['class'] = 'header-info-table' }, {
string.gsub( docClass.format, 'FuncName', funcName ),
HtmlRawElement( 'div', { ['class'] = 'prenomargin' },
makeSkeleton( docClass.title, funcName ) ),
-- '<div class="prenomargin"><pre>' .. skeleton .. '</pre></div>',
subTable( {}, { options } )
})
local usesQuery = frame:preprocess( '{{#dpl:'
.. '\n|uses=' .. fullpagename
.. '\n|namespace=Template'
.. '\n|noresultsheader=empty'
.. '\n}}' )
if usesQuery ~= 'empty' then
push( thisPageOrder, HtmlRawElement( 'p', {}, 'Used by ' .. usesQuery ) )
end
--------
local boxParts = HtmlRawElement( 'div', {
['class'] = 'template-doc-header',
['id'] = docClass.title,
}, docHeader )
.. HtmlRawElement( 'div', { ['class'] = 'template-doc-body' }, split( thisPageOrder ) )
if baseCat == true then
baseCat = docClass.category
baseCatLink = makeWikilink( 'Category:' .. baseCat, funcName )
else
baseCatLink = ''
end
return TemplateStyles( 'Tdoc/styles.css' )
-- .. HtmlRawElement( 'h2', {}, docClass.title .. " Documentation" )
.. HtmlRawElement( 'div', {
['class'] = 'template-doc',
}, boxParts )
.. baseCatLink
end
-- /**
-- * DynamicPageList parser function
-- *
-- * @param array templateParams // [key]=value pairs for arguments
-- * @return string (non-parsed)
-- */
function DynamicPageList( title, templateParams )
templateParams['format'] = title .. ' ,[[%PAGE%|%TITLE%]], ,,'
for key, value in pairs( templateParams ) do
push( templateParams, '|' .. key .. '=' .. value )
templateParams[key] = nil
end
return '<p>' .. '{{#dpl:\n'
.. split( templateParams, '\n' )
.. '\n}}' .. '</p>'
end
-- /**
-- * add TemplateStyles sheets if existing
-- *
-- * @param string src
-- * @return string
-- */
function getTemplateStyles( arg, value )
if arg ~= nil then
if arg == '' then
return TemplateStyles( fullpagename .. '/styles.css' )
else
return TemplateStyles( arg )
end
end
end
function TemplateStyles( src )
return '<templatestyles src=' .. QuotesStr( src ) .. '/>'
end
function SyntaxHighlight( lang, code )
return '<syntaxhighlight lang=' .. lang .. '>'
.. code .. '</syntaxhighlight>'
end
-- /**
-- * Bread-and-butter table generator
-- *
-- * @param array tableCells
-- * @return string
-- */
function makeRawTableRow( tableCells )
for i, tableCell in ipairs( tableCells ) do
tableCells[i] = HtmlRawElement( 'td', {}, tableCell )
end
return HtmlRawElement( 'tr', {}, split( tableCells ) )
end
function subTable( attribs, cells )
return HtmlRawElement( 'table', attribs, makeRawTableRow( cells ) )
end
-- /*
-- return string // formatted doc table w/ tag names and description
-- */
function p.listTagDescriptions( frame )
local docRows = { HtmlRawElement( 'tr', {},
HtmlRawElement( 'th', {}, 'Tag Name' )
.. HtmlRawElement( 'th', {}, 'Parameters' )
.. HtmlRawElement( 'th', {}, 'Description' )
)}
local docOrder = { 'todo', 'var', 'see', 'source', 'ingroup', 'param',
'return', 'throws', 'author' }
for _, tagName in ipairs( docOrder ) do
local docCells = {}
local docTag = tagList[tagName]
docCells[1] = '<code>@' .. tagName .. '</code>'
docCells[2] = formatSubParams( docTag.subparams or { 'info' } )
docCells[3] = docTag.description
push( docRows, makeRawTableRow( docCells ) )
end
return frame:preprocess( HtmlRawElement( 'table', {
['class'] = 'wikitable',
}, split( docRows ) ))
end
function formatSubParams( subParams )
-- if subParams ~= nil then
local subParamsText = {}
for i, subParam in ipairs( subParams ) do
subParamsText[i] = '$' .. subParam
end
return split( subParamsText, ' ' )
-- end
end
return p