From 7c717fe6df582111efc0907f5535d32ce8d72786 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 19 Mar 2014 13:57:37 +0100 Subject: APIDump: Reformatted the plugin to avoid all ZBS Analyzer issues. --- MCServer/Plugins/APIDump/main_APIDump.lua | 897 ++++++++++++++---------------- 1 file changed, 429 insertions(+), 468 deletions(-) (limited to 'MCServer/Plugins/APIDump/main_APIDump.lua') diff --git a/MCServer/Plugins/APIDump/main_APIDump.lua b/MCServer/Plugins/APIDump/main_APIDump.lua index 4ed692b52..6d4a6ebc5 100644 --- a/MCServer/Plugins/APIDump/main_APIDump.lua +++ b/MCServer/Plugins/APIDump/main_APIDump.lua @@ -7,92 +7,22 @@ -- Global variables: -g_Plugin = nil; -g_PluginFolder = ""; +local g_Plugin = nil +local g_PluginFolder = "" +local g_Stats = {} +local g_TrackedPages = {} -function Initialize(Plugin) - g_Plugin = Plugin; - g_PluginFolder = Plugin:GetLocalFolder(); - - LOG("Initialising " .. Plugin:GetName() .. " v." .. Plugin:GetVersion()) - - cPluginManager:BindConsoleCommand("api", HandleCmdApi, "Dumps the Lua API docs into the API/ subfolder") - g_Plugin:AddWebTab("APIDump", HandleWebAdminDump) - -- TODO: Add a WebAdmin tab that has a Dump button - return true -end - - - - - -function HandleCmdApi(a_Split) - DumpApi() - return true -end - - - - - -function DumpApi() - LOG("Dumping the API...") - - -- Load the API descriptions from the Classes and Hooks subfolders: - -- This needs to be done each time the command is invoked because the export modifies the tables' contents - dofile(g_PluginFolder .. "/APIDesc.lua") - if (g_APIDesc.Classes == nil) then - g_APIDesc.Classes = {}; - end - if (g_APIDesc.Hooks == nil) then - g_APIDesc.Hooks = {}; - end - LoadAPIFiles("/Classes/", g_APIDesc.Classes); - LoadAPIFiles("/Hooks/", g_APIDesc.Hooks); - - -- Reset the stats: - g_TrackedPages = {}; -- List of tracked pages, to be checked later whether they exist. Each item is an array of referring pagenames. - g_Stats = -- Statistics about the documentation - { - NumTotalClasses = 0, - NumUndocumentedClasses = 0, - NumTotalFunctions = 0, - NumUndocumentedFunctions = 0, - NumTotalConstants = 0, - NumUndocumentedConstants = 0, - NumTotalVariables = 0, - NumUndocumentedVariables = 0, - NumTotalHooks = 0, - NumUndocumentedHooks = 0, - NumTrackedLinks = 0, - NumInvalidLinks = 0, - } - - -- dump all available API functions and objects: - -- DumpAPITxt(); - - -- Dump all available API object in HTML format into a subfolder: - DumpAPIHtml(); - - LOG("APIDump finished"); - return true -end - - - - - -function LoadAPIFiles(a_Folder, a_DstTable) +local function LoadAPIFiles(a_Folder, a_DstTable) assert(type(a_Folder) == "string") assert(type(a_DstTable) == "table") local Folder = g_PluginFolder .. a_Folder; - for idx, fnam in ipairs(cFile:GetFolderContents(Folder)) do + for _, fnam in ipairs(cFile:GetFolderContents(Folder)) do local FileName = Folder .. fnam; -- We only want .lua files from the folder: if (cFile:IsFile(FileName) and fnam:match(".*%.lua$")) then @@ -113,45 +43,7 @@ end -function DumpAPITxt() - LOG("Dumping all available functions to API.txt..."); - function dump (prefix, a, Output) - for i, v in pairs (a) do - if (type(v) == "table") then - if (GetChar(i, 1) ~= ".") then - if (v == _G) then - -- LOG(prefix .. i .. " == _G, CYCLE, ignoring"); - elseif (v == _G.package) then - -- LOG(prefix .. i .. " == _G.package, ignoring"); - else - dump(prefix .. i .. ".", v, Output) - end - end - elseif (type(v) == "function") then - if (string.sub(i, 1, 2) ~= "__") then - table.insert(Output, prefix .. i .. "()"); - end - end - end - end - - local Output = {}; - dump("", _G, Output); - - table.sort(Output); - local f = io.open("API.txt", "w"); - for i, n in ipairs(Output) do - f:write(n, "\n"); - end - f:close(); - LOG("API.txt written."); -end - - - - - -function CreateAPITables() +local function CreateAPITables() --[[ We want an API table of the following shape: local API = { @@ -218,7 +110,7 @@ function CreateAPITables() -- Member variables: local SetField = a_ClassObj[".set"] or {}; if ((a_ClassObj[".get"] ~= nil) and (type(a_ClassObj[".get"]) == "table")) then - for k, v in pairs(a_ClassObj[".get"]) do + for k in pairs(a_ClassObj[".get"]) do if (SetField[k] == nil) then -- It is a read-only variable, add it as a constant: table.insert(res.Constants, {Name = k, Value = ""}); @@ -259,7 +151,7 @@ local function WriteArticles(f)

The following articles provide various extra information on plugin development

- - -]]); - f:close(); - - LOG("API subfolder written"); -end - - - - - -function ReadDescriptions(a_API) +local function ReadDescriptions(a_API) -- Returns true if the class of the specified name is to be ignored local function IsClassIgnored(a_ClsName) if (g_APIDesc.IgnoreClasses == nil) then return false; end - for i, name in ipairs(g_APIDesc.IgnoreClasses) do + for _, name in ipairs(g_APIDesc.IgnoreClasses) do if (a_ClsName:match(name)) then return true; end @@ -511,7 +359,7 @@ function ReadDescriptions(a_API) return false; end local FnName = a_ClassName .. "." .. a_FnName; - for i, name in ipairs(g_APIDesc.IgnoreFunctions) do + for _, name in ipairs(g_APIDesc.IgnoreFunctions) do if (FnName:match(name)) then return true; end @@ -524,7 +372,7 @@ function ReadDescriptions(a_API) if (g_APIDesc.IgnoreConstants == nil) then return false; end; - for i, name in ipairs(g_APIDesc.IgnoreConstants) do + for _, name in ipairs(g_APIDesc.IgnoreConstants) do if (a_CnName:match(name)) then return true; end @@ -537,7 +385,7 @@ function ReadDescriptions(a_API) if (g_APIDesc.IgnoreVariables == nil) then return false; end; - for i, name in ipairs(g_APIDesc.IgnoreVariables) do + for _, name in ipairs(g_APIDesc.IgnoreVariables) do if (a_VarName:match(name)) then return true; end @@ -547,7 +395,7 @@ function ReadDescriptions(a_API) -- Remove ignored classes from a_API: local APICopy = {}; - for i, cls in ipairs(a_API) do + for _, cls in ipairs(a_API) do if not(IsClassIgnored(cls.Name)) then table.insert(APICopy, cls); end @@ -557,14 +405,14 @@ function ReadDescriptions(a_API) end; -- Process the documentation for each class: - for i, cls in ipairs(a_API) do + for _, cls in ipairs(a_API) do -- Initialize default values for each class: cls.ConstantGroups = {}; cls.NumConstantsInGroups = 0; cls.NumConstantsInGroupsForDescendants = 0; -- Rename special functions: - for j, fn in ipairs(cls.Functions) do + for _, fn in ipairs(cls.Functions) do if (fn.Name == ".call") then fn.DocID = "constructor"; fn.Name = "() (constructor)"; @@ -594,7 +442,7 @@ function ReadDescriptions(a_API) -- Process inheritance: if (APIDesc.Inherits ~= nil) then - for j, icls in ipairs(a_API) do + for _, icls in ipairs(a_API) do if (icls.Name == APIDesc.Inherits) then table.insert(icls.Descendants, cls); cls.Inherits = icls; @@ -614,7 +462,7 @@ function ReadDescriptions(a_API) if (APIDesc.Functions ~= nil) then -- Assign function descriptions: - for j, func in ipairs(cls.Functions) do + for _, func in ipairs(cls.Functions) do local FnName = func.DocID or func.Name; local FnDesc = APIDesc.Functions[FnName]; if (FnDesc == nil) then @@ -630,7 +478,7 @@ function ReadDescriptions(a_API) AddFunction(func.Name, FnDesc.Params, FnDesc.Return, FnDesc.Notes); else -- Multiple function overloads - for k, desc in ipairs(FnDesc) do + for _, desc in ipairs(FnDesc) do AddFunction(func.Name, desc.Params, desc.Return, desc.Notes); end -- for k, desc - FnDesc[] end @@ -641,7 +489,7 @@ function ReadDescriptions(a_API) -- Replace functions with their described and overload-expanded versions: cls.Functions = DoxyFunctions; else -- if (APIDesc.Functions ~= nil) - for j, func in ipairs(cls.Functions) do + for _, func in ipairs(cls.Functions) do local FnName = func.DocID or func.Name; if not(IsFunctionIgnored(cls.Name, FnName)) then table.insert(cls.UndocumentedFunctions, FnName); @@ -651,7 +499,7 @@ function ReadDescriptions(a_API) if (APIDesc.Constants ~= nil) then -- Assign constant descriptions: - for j, cons in ipairs(cls.Constants) do + for _, cons in ipairs(cls.Constants) do local CnDesc = APIDesc.Constants[cons.Name]; if (CnDesc == nil) then -- Not documented @@ -664,7 +512,7 @@ function ReadDescriptions(a_API) end end -- for j, cons else -- if (APIDesc.Constants ~= nil) - for j, cons in ipairs(cls.Constants) do + for _, cons in ipairs(cls.Constants) do if not(IsConstantIgnored(cls.Name .. "." .. cons.Name)) then table.insert(cls.UndocumentedConstants, cons.Name); end @@ -673,7 +521,7 @@ function ReadDescriptions(a_API) -- Assign member variables' descriptions: if (APIDesc.Variables ~= nil) then - for j, var in ipairs(cls.Variables) do + for _, var in ipairs(cls.Variables) do local VarDesc = APIDesc.Variables[var.Name]; if (VarDesc == nil) then -- Not documented @@ -688,7 +536,7 @@ function ReadDescriptions(a_API) end end -- for j, var else -- if (APIDesc.Variables ~= nil) - for j, var in ipairs(cls.Variables) do + for _, var in ipairs(cls.Variables) do if not(IsVariableIgnored(cls.Name .. "." .. var.Name)) then table.insert(cls.UndocumentedVariables, var.Name); end @@ -706,8 +554,8 @@ function ReadDescriptions(a_API) group.Include = { group.Include }; end local NumInGroup = 0; - for idx, incl in ipairs(group.Include or {}) do - for cidx, cons in ipairs(cls.Constants) do + for _, incl in ipairs(group.Include or {}) do + for _, cons in ipairs(cls.Constants) do if ((cons.Group == nil) and cons.Name:match(incl)) then cons.Group = group; table.insert(group.Constants, cons); @@ -733,7 +581,7 @@ function ReadDescriptions(a_API) -- Remove grouped constants from the normal list: local NewConstants = {}; - for idx, cons in ipairs(cls.Constants) do + for _, cons in ipairs(cls.Constants) do if (cons.Group == nil) then table.insert(NewConstants, cons); end @@ -749,18 +597,18 @@ function ReadDescriptions(a_API) cls.UndocumentedVariables = {}; cls.Variables = cls.Variables or {}; g_Stats.NumUndocumentedClasses = g_Stats.NumUndocumentedClasses + 1; - for j, func in ipairs(cls.Functions) do + for _, func in ipairs(cls.Functions) do local FnName = func.DocID or func.Name; if not(IsFunctionIgnored(cls.Name, FnName)) then table.insert(cls.UndocumentedFunctions, FnName); end end -- for j, func - cls.Functions[] - for j, cons in ipairs(cls.Constants) do + for _, cons in ipairs(cls.Constants) do if not(IsConstantIgnored(cls.Name .. "." .. cons.Name)) then table.insert(cls.UndocumentedConstants, cons.Name); end end -- for j, cons - cls.Constants[] - for j, var in ipairs(cls.Variables) do + for _, var in ipairs(cls.Variables) do if not(IsConstantIgnored(cls.Name .. "." .. var.Name)) then table.insert(cls.UndocumentedVariables, var.Name); end @@ -769,7 +617,7 @@ function ReadDescriptions(a_API) -- Remove ignored functions: local NewFunctions = {}; - for j, fn in ipairs(cls.Functions) do + for _, fn in ipairs(cls.Functions) do if (not(IsFunctionIgnored(cls.Name, fn.Name))) then table.insert(NewFunctions, fn); end @@ -792,7 +640,7 @@ function ReadDescriptions(a_API) -- Remove ignored constants: local NewConstants = {}; - for j, cn in ipairs(cls.Constants) do + for _, cn in ipairs(cls.Constants) do if (not(IsFunctionIgnored(cls.Name, cn.Name))) then table.insert(NewConstants, cn); end @@ -808,7 +656,7 @@ function ReadDescriptions(a_API) -- Remove ignored member variables: local NewVariables = {}; - for j, var in ipairs(cls.Variables) do + for _, var in ipairs(cls.Variables) do if (not(IsVariableIgnored(cls.Name .. "." .. var.Name))) then table.insert(NewVariables, var); end @@ -824,7 +672,7 @@ function ReadDescriptions(a_API) end -- for i, cls -- Sort the descendants lists: - for i, cls in ipairs(a_API) do + for _, cls in ipairs(a_API) do table.sort(cls.Descendants, function(c1, c2) return (c1.Name < c2.Name); @@ -837,7 +685,7 @@ end -function ReadHooks(a_Hooks) +local function ReadHooks(a_Hooks) --[[ a_Hooks = { { Name = "HOOK_1"}, @@ -846,7 +694,7 @@ function ReadHooks(a_Hooks) }; We want to add hook descriptions to each hook in this array --]] - for i, hook in ipairs(a_Hooks) do + for _, hook in ipairs(a_Hooks) do local HookDesc = g_APIDesc.Hooks[hook.Name]; if (HookDesc ~= nil) then for key, val in pairs(HookDesc) do @@ -861,63 +709,10 @@ end --- Make a link out of anything with the special linkifying syntax {{link|title}} -function LinkifyString(a_String, a_Referrer) - assert(a_Referrer ~= nil); - assert(a_Referrer ~= ""); - - --- Adds a page to the list of tracked pages (to be checked for existence at the end) - local function AddTrackedPage(a_PageName) - local Pg = (g_TrackedPages[a_PageName] or {}); - table.insert(Pg, a_Referrer); - g_TrackedPages[a_PageName] = Pg; - end - - --- Creates the HTML for the specified link and title - local function CreateLink(Link, Title) - if (Link:sub(1, 7) == "http://") then - -- The link is a full absolute URL, do not modify, do not track: - return "" .. Title .. ""; - end - local idxHash = Link:find("#"); - if (idxHash ~= nil) then - -- The link contains an anchor: - if (idxHash == 1) then - -- Anchor in the current page, no need to track: - return "" .. Title .. ""; - end - -- Anchor in another page: - local PageName = Link:sub(1, idxHash - 1); - AddTrackedPage(PageName); - return "" .. Title .. ""; - end - -- Link without anchor: - AddTrackedPage(Link); - return "" .. Title .. ""; - end - - -- Linkify the strings using the CreateLink() function: - local txt = a_String:gsub("{{([^|}]*)|([^}]*)}}", CreateLink) -- {{link|title}} - txt = txt:gsub("{{([^|}]*)}}", -- {{LinkAndTitle}} - function(LinkAndTitle) - local idxHash = LinkAndTitle:find("#"); - if (idxHash ~= nil) then - -- The LinkAndTitle contains a hash, remove the hashed part from the title: - return CreateLink(LinkAndTitle, LinkAndTitle:sub(1, idxHash - 1)); - end - return CreateLink(LinkAndTitle, LinkAndTitle); - end - ); - return txt; -end - - - - - -function WriteHtmlClass(a_ClassAPI, a_AllAPI, a_ClassMenu) +local function WriteHtmlClass(a_ClassAPI, a_ClassMenu) local cf, err = io.open("API/" .. a_ClassAPI.Name .. ".html", "w"); if (cf == nil) then + LOGINFO("Cannot write HTML API for class " .. a_ClassAPI.Name .. ": " .. err) return; end @@ -931,7 +726,7 @@ function WriteHtmlClass(a_ClassAPI, a_AllAPI, a_ClassMenu) cf:write("

Functions inherited from ", a_InheritedName, "

\n"); end cf:write("\n\n"); - for i, func in ipairs(a_Functions) do + for _, func in ipairs(a_Functions) do cf:write("\n"); cf:write("\n"); cf:write("\n"); @@ -942,7 +737,7 @@ function WriteHtmlClass(a_ClassAPI, a_AllAPI, a_ClassMenu) local function WriteConstantTable(a_Constants, a_Source) cf:write("
NameParametersReturn valueNotes
", func.Name, "", LinkifyString(func.Params or "", (a_InheritedName or a_ClassAPI.Name)), "", LinkifyString(func.Return or "", (a_InheritedName or a_ClassAPI.Name)), "
\n\n"); - for i, cons in ipairs(a_Constants) do + for _, cons in ipairs(a_Constants) do cf:write("\n"); cf:write("\n"); cf:write("\n"); @@ -965,7 +760,7 @@ function WriteHtmlClass(a_ClassAPI, a_AllAPI, a_ClassMenu) WriteConstantTable(a_Constants, Source); end - for k, group in pairs(a_ConstantGroups) do + for _, group in pairs(a_ConstantGroups) do if ((a_InheritedName == nil) or group.ShowInDescendants) then cf:write("

"); cf:write(LinkifyString(group.TextBefore or "", Source)); @@ -985,7 +780,7 @@ function WriteHtmlClass(a_ClassAPI, a_AllAPI, a_ClassMenu) end cf:write("

NameValueNotes
", cons.Name, "", cons.Value, "", LinkifyString(cons.Notes or "", a_Source), "
\n"); - for i, var in ipairs(a_Variables) do + for _, var in ipairs(a_Variables) do cf:write("\n"); cf:write("\n"); cf:write("\n \n"); @@ -998,7 +793,7 @@ function WriteHtmlClass(a_ClassAPI, a_AllAPI, a_ClassMenu) return; end cf:write("
NameTypeNotes
", var.Name, "", LinkifyString(var.Type or "(undocumented)", a_InheritedName or a_ClassAPI.Name), "", LinkifyString(var.Notes or "", a_InheritedName or a_ClassAPI.Name), "
]]); - cf:close(); -end - - - - - -function WriteHtmlHook(a_Hook, a_HookNav) - local fnam = "API/" .. a_Hook.DefaultFnName .. ".html"; - local f, error = io.open(fnam, "w"); - if (f == nil) then - LOG("Cannot write \"" .. fnam .. "\": \"" .. error .. "\"."); - return; - end - local HookName = a_Hook.DefaultFnName; - - f:write([[ - - MCServer API - ]], HookName, [[ Hook - - - - - - -
-
-

]], a_Hook.Name, [[

-
-
-
- Index:
- Articles
- Classes
- Hooks
-
- Quick navigation:
- ]]); - f:write(a_HookNav); - f:write([[ -

- ]]); - f:write(LinkifyString(a_Hook.Desc, HookName)); - f:write("

\n

Callback function

\n

The default name for the callback function is "); - f:write(a_Hook.DefaultFnName, ". It has the following signature:\n"); - f:write("

function ", HookName, "(");
-	if (a_Hook.Params == nil) then
-		a_Hook.Params = {};
-	end
-	for i, param in ipairs(a_Hook.Params) do
-		if (i > 1) then
-			f:write(", ");
+	
+	-- Write the functions, including the inherited ones:
+	if (HasFunctions) then
+		cf:write("

Functions

\n"); + WriteFunctions(a_ClassAPI.Functions, nil); + g_Stats.NumTotalFunctions = g_Stats.NumTotalFunctions + #a_ClassAPI.Functions; + for _, cls in ipairs(InheritanceChain) do + WriteFunctions(cls.Functions, cls.Name); end - f:write(param.Name); end - f:write(")
\n

Parameters:

\n\n"); - for i, param in ipairs(a_Hook.Params) do - f:write("\n"); + + -- Write the additional infos: + if (a_ClassAPI.AdditionalInfo ~= nil) then + for i, additional in ipairs(a_ClassAPI.AdditionalInfo) do + cf:write("

", additional.Header, "

\n"); + cf:write(LinkifyString(additional.Contents, ClassName)); + end end - f:write("
NameTypeNotes
", param.Name, "", LinkifyString(param.Type, HookName), "", LinkifyString(param.Notes, HookName), "
\n

" .. (a_Hook.Returns or "") .. "

\n\n"); - f:write([[

Code examples

Registering the callback

]]); - f:write("
\n");
-	f:write([[cPluginManager:AddHook(cPluginManager.]] .. a_Hook.Name .. ", My" .. a_Hook.DefaultFnName .. [[);]]);
-	f:write("
\n\n"); - local Examples = a_Hook.CodeExamples or {}; - for i, example in ipairs(Examples) do - f:write("

", (example.Title or "missing Title"), "

\n"); - f:write("

", (example.Desc or "missing Desc"), "

\n"); - f:write("
", (example.Code or "missing Code"), "\n
\n\n"); + + cf:write([[
]]); + cf:close(); +end + + + + + +local function WriteClasses(f, a_API, a_ClassMenu) + f:write([[ +

Class index

+

The following classes are available in the MCServer Lua scripting language: +

+
+ ]]); end @@ -1218,12 +962,12 @@ end --- Writes a list of undocumented objects into a file -function ListUndocumentedObjects(API, UndocumentedHooks) +local function ListUndocumentedObjects(API, UndocumentedHooks) f = io.open("API/_undocumented.lua", "w"); if (f ~= nil) then f:write("\n-- This is the list of undocumented API objects, automatically generated by APIDump\n\n"); f:write("g_APIDesc =\n{\n\tClasses =\n\t{\n"); - for i, cls in ipairs(API) do + for _, cls in ipairs(API) do local HasFunctions = ((cls.UndocumentedFunctions ~= nil) and (#cls.UndocumentedFunctions > 0)); local HasConstants = ((cls.UndocumentedConstants ~= nil) and (#cls.UndocumentedConstants > 0)); local HasVariables = ((cls.UndocumentedVariables ~= nil) and (#cls.UndocumentedVariables > 0)); @@ -1240,7 +984,7 @@ function ListUndocumentedObjects(API, UndocumentedHooks) if (HasFunctions) then f:write("\t\t\tFunctions =\n\t\t\t{\n"); table.sort(cls.UndocumentedFunctions); - for j, fn in ipairs(cls.UndocumentedFunctions) do + for _, fn in ipairs(cls.UndocumentedFunctions) do f:write("\t\t\t\t" .. fn .. " = { Params = \"\", Return = \"\", Notes = \"\" },\n"); end -- for j, fn - cls.UndocumentedFunctions[] f:write("\t\t\t},\n\n"); @@ -1249,7 +993,7 @@ function ListUndocumentedObjects(API, UndocumentedHooks) if (HasConstants) then f:write("\t\t\tConstants =\n\t\t\t{\n"); table.sort(cls.UndocumentedConstants); - for j, cn in ipairs(cls.UndocumentedConstants) do + for _, cn in ipairs(cls.UndocumentedConstants) do f:write("\t\t\t\t" .. cn .. " = { Notes = \"\" },\n"); end -- for j, fn - cls.UndocumentedConstants[] f:write("\t\t\t},\n\n"); @@ -1258,7 +1002,7 @@ function ListUndocumentedObjects(API, UndocumentedHooks) if (HasVariables) then f:write("\t\t\tVariables =\n\t\t\t{\n"); table.sort(cls.UndocumentedVariables); - for j, vn in ipairs(cls.UndocumentedVariables) do + for _, vn in ipairs(cls.UndocumentedVariables) do f:write("\t\t\t\t" .. vn .. " = { Type = \"\", Notes = \"\" },\n"); end -- for j, fn - cls.UndocumentedVariables[] f:write("\t\t\t},\n\n"); @@ -1306,7 +1050,7 @@ end --- Lists the API objects that are documented but not available in the API: -function ListUnexportedObjects() +local function ListUnexportedObjects() f = io.open("API/_unexported-documented.txt", "w"); if (f ~= nil) then for clsname, cls in pairs(g_APIDesc.Classes) do @@ -1338,7 +1082,7 @@ end -function ListMissingPages() +local function ListMissingPages() local MissingPages = {}; local NumLinks = 0; for PageName, Referrers in pairs(g_TrackedPages) do @@ -1368,7 +1112,7 @@ function ListMissingPages() LOGWARNING("Cannot open _missingPages.txt for writing: '" .. err .. "'. There are " .. #MissingPages .. " pages missing."); return; end - for idx, pg in ipairs(MissingPages) do + for _, pg in ipairs(MissingPages) do f:write(pg.Name .. ":\n"); -- Sort and output the referrers: table.sort(pg.Refs); @@ -1384,7 +1128,7 @@ end --- Writes the documentation statistics (in g_Stats) into the given HTML file -function WriteStats(f) +local function WriteStats(f) local function ExportMeter(a_Percent) local Color; if (a_Percent > 99) then @@ -1453,7 +1197,198 @@ end -function HandleWebAdminDump(a_Request) +local function DumpAPIHtml(a_API) + LOG("Dumping all available functions and constants to API subfolder..."); + + -- Create the output folder + if not(cFile:IsFolder("API")) then + cFile:CreateFolder("API"); + end + + LOG("Copying static files.."); + cFile:CreateFolder("API/Static"); + local localFolder = g_Plugin:GetLocalFolder(); + for _, fnam in ipairs(cFile:GetFolderContents(localFolder .. "/Static")) do + cFile:Delete("API/Static/" .. fnam); + cFile:Copy(localFolder .. "/Static/" .. fnam, "API/Static/" .. fnam); + end + + -- Extract hook constants: + local Hooks = {}; + local UndocumentedHooks = {}; + for name, obj in pairs(cPluginManager) do + if ( + (type(obj) == "number") and + name:match("HOOK_.*") and + (name ~= "HOOK_MAX") and + (name ~= "HOOK_NUM_HOOKS") + ) then + table.insert(Hooks, { Name = name }); + end + end + table.sort(Hooks, + function(Hook1, Hook2) + return (Hook1.Name < Hook2.Name); + end + ); + + -- Read in the descriptions: + LOG("Reading descriptions..."); + ReadDescriptions(a_API); + ReadHooks(Hooks); + + -- Create a "class index" file, write each class as a link to that file, + -- then dump class contents into class-specific file + LOG("Writing HTML files..."); + local f, err = io.open("API/index.html", "w"); + if (f == nil) then + LOGINFO("Cannot output HTML API: " .. err); + return; + end + + -- Create a class navigation menu that will be inserted into each class file for faster navigation (#403) + local ClassMenuTab = {}; + for _, cls in ipairs(a_API) do + table.insert(ClassMenuTab, ""); + table.insert(ClassMenuTab, cls.Name); + table.insert(ClassMenuTab, "
"); + end + local ClassMenu = table.concat(ClassMenuTab, ""); + + -- Create a hook navigation menu that will be inserted into each hook file for faster navigation(#403) + local HookNavTab = {}; + for _, hook in ipairs(Hooks) do + table.insert(HookNavTab, ""); + table.insert(HookNavTab, (hook.Name:gsub("^HOOK_", ""))); -- remove the "HOOK_" part of the name + table.insert(HookNavTab, "
"); + end + local HookNav = table.concat(HookNavTab, ""); + + -- Write the HTML file: + f:write([[ + + + MCServer API - Index + + + +
+
+

MCServer API - Index

+
+
+

The API reference is divided into the following sections:

+ +
+ ]]); + + WriteArticles(f); + WriteClasses(f, a_API, ClassMenu); + WriteHooks(f, Hooks, UndocumentedHooks, HookNav); + + -- Copy the static files to the output folder: + local StaticFiles = + { + "main.css", + "prettify.js", + "prettify.css", + "lang-lua.js", + }; + for _, fnam in ipairs(StaticFiles) do + cFile:Delete("API/" .. fnam); + cFile:Copy(g_Plugin:GetLocalFolder() .. "/" .. fnam, "API/" .. fnam); + end + + -- List the documentation problems: + LOG("Listing leftovers..."); + ListUndocumentedObjects(a_API, UndocumentedHooks); + ListUnexportedObjects(); + ListMissingPages(); + + WriteStats(f); + + f:write([[ +
+ +]]); + f:close(); + + LOG("API subfolder written"); +end + + + + + +local function DumpApi() + LOG("Dumping the API...") + + -- Load the API descriptions from the Classes and Hooks subfolders: + -- This needs to be done each time the command is invoked because the export modifies the tables' contents + dofile(g_PluginFolder .. "/APIDesc.lua") + if (g_APIDesc.Classes == nil) then + g_APIDesc.Classes = {}; + end + if (g_APIDesc.Hooks == nil) then + g_APIDesc.Hooks = {}; + end + LoadAPIFiles("/Classes/", g_APIDesc.Classes); + LoadAPIFiles("/Hooks/", g_APIDesc.Hooks); + + -- Reset the stats: + g_TrackedPages = {}; -- List of tracked pages, to be checked later whether they exist. Each item is an array of referring pagenames. + g_Stats = -- Statistics about the documentation + { + NumTotalClasses = 0, + NumUndocumentedClasses = 0, + NumTotalFunctions = 0, + NumUndocumentedFunctions = 0, + NumTotalConstants = 0, + NumUndocumentedConstants = 0, + NumTotalVariables = 0, + NumUndocumentedVariables = 0, + NumTotalHooks = 0, + NumUndocumentedHooks = 0, + NumTrackedLinks = 0, + NumInvalidLinks = 0, + } + + -- Create the API tables: + local API, Globals = CreateAPITables(); + + -- Sort the classes by name: + table.sort(API, + function (c1, c2) + return (string.lower(c1.Name) < string.lower(c2.Name)); + end + ); + g_Stats.NumTotalClasses = #API; + + -- Add Globals into the API: + Globals.Name = "Globals"; + table.insert(API, Globals); + + -- Dump all available API object in HTML format into a subfolder: + DumpAPIHtml(API); + + LOG("APIDump finished"); + return true +end + + + + + +local function HandleWebAdminDump(a_Request) if (a_Request.PostParams["Dump"] ~= nil) then DumpApi() end @@ -1467,3 +1402,29 @@ end + +local function HandleCmdApi(a_Split) + DumpApi() + return true +end + + + + + +function Initialize(Plugin) + g_Plugin = Plugin; + g_PluginFolder = Plugin:GetLocalFolder(); + + LOG("Initialising " .. Plugin:GetName() .. " v." .. Plugin:GetVersion()) + + cPluginManager:BindConsoleCommand("api", HandleCmdApi, "Dumps the Lua API docs into the API/ subfolder") + g_Plugin:AddWebTab("APIDump", HandleWebAdminDump) + -- TODO: Add a WebAdmin tab that has a Dump button + return true +end + + + + + -- cgit v1.2.3