From 96c85498c019e381d0aeed2e33e626563563ea8c Mon Sep 17 00:00:00 2001 From: mitchell <70453897+667e-11@users.noreply.github.com> Date: Wed, 7 Mar 2012 09:28:43 -0500 Subject: Documentation overhaul with Discount (Markdown implementation). The standard LuaDoc template is no longer used. Instead, the new `scripts/markdowndoc.lua` has the template for LuaDoc and `scripts/update_doc` has the template for the Manual. Also added README, CHANGELOG, and THANKS files. --- scripts/adeptsensedoc.lua | 10 +-- scripts/markdowndoc.lua | 221 ++++++++++++++++++++++++++++++++++++++++++++++ scripts/update_doc | 156 +++++++++++++------------------- 3 files changed, 284 insertions(+), 103 deletions(-) create mode 100644 scripts/markdowndoc.lua (limited to 'scripts') diff --git a/scripts/adeptsensedoc.lua b/scripts/adeptsensedoc.lua index cfae8898..61f651b4 100644 --- a/scripts/adeptsensedoc.lua +++ b/scripts/adeptsensedoc.lua @@ -184,12 +184,10 @@ function start(doc) end -- Tag the functions and write the apidoc. for _, f in ipairs(m.functions) do - if not f:find('no_functions') then -- ignore placeholders - local func = f:match('[^%.:]+$') - local ext_fields = module == '_G' and '' or 'class:'..module - write_tag(ctags, func, 'f', ext_fields) - write_apidoc(apidoc, m, m.functions[f]) - end + local func = f:match('[^%.:]+$') + local ext_fields = module == '_G' and '' or 'class:'..module + write_tag(ctags, func, 'f', ext_fields) + write_apidoc(apidoc, m, m.functions[f]) end -- Tag the tables and write the apidoc. for _, t in ipairs(m.tables or {}) do diff --git a/scripts/markdowndoc.lua b/scripts/markdowndoc.lua new file mode 100644 index 00000000..4bfb10ed --- /dev/null +++ b/scripts/markdowndoc.lua @@ -0,0 +1,221 @@ +-- Copyright 2007-2012 Mitchell mitchellcaladbolg.net. See LICENSE. + +local ipairs, type = ipairs, type +local io_open, io_popen = io.open, io.popen +local string_format, string_rep = string.format, string.rep +local table_concat = table.concat + +--- +-- Markdown doclet for Luadoc. +-- Requires Discount (http://www.pell.portland.or.us/~orc/Code/discount/). +-- @usage luadoc -d [output_path] -doclet path/to/markdowndoc [file(s)] +module('markdowndoc') + +local NAVFILE = '%s* [%s](%s)\n' +local FUNCTION = '\n### `%s` (%s)\n\n' +--local FUNCTION = '### `%s` (%s)\n\n' +local DESCRIPTION = '> %s\n\n' +local LIST_TITLE = '> %s:\n\n' +local PARAM = '> * `%s`: %s\n' +local USAGE = '> * `%s`\n' +local RETURN = '> * %s\n' +local SEE = '> * [`%s`](#%s)\n' +local TABLE = '\n### `%s`\n\n' +--local TABLE = '### `%s`\n\n' +local FIELD = '> * `%s`: %s\n' +local HTML = [[ + + + + %(title) + + + + +
+ +
+
Contents
+ %(toc) +
+
+ %(main) +
+
+ + +]] + +-- Writes LuaDoc hierarchical module navigation to the given file. +-- @param f The navigation file being written to. +-- @param list The module list. +-- @param parent String parent module with a trailing '.' for sub-modules in +-- order to generate full page links. +local function write_nav(f, list, parent) + if not parent then parent = '' end + local level = 0 + for _ in parent:gmatch('%.') do level = level + 1 end + for _, name in ipairs(list) do + f:write(string_format(NAVFILE, string_rep(' ', level * 4), name, + parent..name..'.html')) + if list[name] then + f:write('\n') + write_nav(f, list[name], parent..name..'.') + end + end +end + +-- Writes a LuaDoc description to the given file. +-- @param f The markdown file being written to. +-- @param description The description. +local function write_description(f, description) + f:write(string_format(DESCRIPTION, description)) +end + +-- Writes a LuaDoc list to the given file. +-- @param f The markdown file being written to. +-- @param title The title of the list. +-- @param fmt The format of a list item. +-- @param list The LuaDoc list. +local function write_list(f, title, fmt, list) + if not list or #list == 0 then return end + if type(list) == 'string' then list = { list } end + f:write(string_format(LIST_TITLE, title)) + for _, value in ipairs(list) do + f:write(string_format(fmt, value, value)) + end + f:write('\n') +end + +-- Writes a LuaDoc hashmap to the given file. +-- @param f The markdown file being written to. +-- @param title The title of the hashmap. +-- @param fmt The format of a hashmap item. +-- @param list The LuaDoc hashmap. +local function write_hashmap(f, title, fmt, hashmap) + if not hashmap or #hashmap == 0 then return end + f:write(string_format(LIST_TITLE, title)) + for _, name in ipairs(hashmap) do + f:write(string_format(fmt, name, hashmap[name] or '')) + end + f:write('\n') +end + +-- Called by LuaDoc to process a doc object. +-- @param doc The LuaDoc doc object. +function start(doc) + local modules, files = doc.modules, doc.files + + -- Create the navigation list. + local hierarchy = {} + for _, name in ipairs(modules) do + local parent, self = name:match('^(.-)%.?([^.]+)$') + local h = hierarchy + for table in parent:gmatch('[^.]+') do + if not h[table] then h[table] = {} end + h = h[table] + end + h[#h + 1] = self + end + local navfile = options.output_dir..'/api/.nav.md' + local f = io_open(navfile, 'wb') + write_nav(f, hierarchy) + f:close() + local p = io_popen('markdown "'..navfile..'"') + local nav = p:read('*all') + p:close() + + -- Create a map of doc objects to file names so their Markdown doc comments + -- can be extracted. + local filedocs = {} + for _, name in ipairs(files) do filedocs[files[name].doc] = name end + + -- Loop over modules, creating Markdown documents. + for _, name in ipairs(modules) do + local module = modules[name] + local filename = filedocs[module.doc] + + local mdfile = options.output_dir..'/api/'..name..'.md' + local f = io_open(mdfile, 'wb') + + -- Write the header and description. + f:write('# ', name, '\n\n') + f:write(module.description, '\n\n') + + -- Extract any Markdown doc comments and insert them. + -- Markdown doc comments must immediately proceed a 'module' declaration + -- (excluding blank lines), start with '-- Markdown:', and end on a blank or + -- uncommented line. + if filename then + local module_declaration, markdown = false, false + local module_file = io_open(filename, 'rb') + for line in module_file:lines() do + if not module_declaration and line:find('^module') then + module_declaration = true + elseif module_declaration and not markdown and line ~= '' then + if line ~= '-- Markdown:' then break end + markdown = true + elseif markdown then + line = line:match('^%-%-%s?(.*)$') + if not line then break end + f:write(line, '\n') + end + end + module_file:close() + end + f:write('\n') + f:write('- - -\n\n') + + -- Write functions. + local funcs = module.functions + if #funcs > 0 then + f:write('## Functions\n\n') + f:write('- - -\n\n') + for _, fname in ipairs(funcs) do + local func = funcs[fname] + f:write(string_format(FUNCTION, func.name, func.name, + table_concat(func.param, ', '):gsub('_', '\\_'))) + write_description(f, func.description) + write_hashmap(f, 'Parameters', PARAM, func.param) + write_list(f, 'Usage', USAGE, func.usage) + write_list(f, 'Return', RETURN, func.ret) + write_list(f, 'See also', SEE, func.see) + f:write('- - -\n\n') + end + f:write('\n') + end + + -- Write tables. + local tables = module.tables + if #tables > 0 then + f:write('## Tables\n\n') + f:write('- - -\n\n') + for _, tname in ipairs(tables) do + local tbl = tables[tname] + f:write(string_format(TABLE, tbl.name, tbl.name)) + write_description(f, tbl.description) + write_hashmap(f, 'Fields', FIELD, tbl.field) + write_list(f, 'Usage', USAGE, tbl.usage) + write_list(f, 'See also', SEE, tbl.see) + f:write('- - -\n\n') + end + end + + f:close() + + -- Write HTML. + local p = io_popen('markdown -f toc -T "'..mdfile..'"') + local toc, main = p:read('*all'):match('^(.-\n\n)(.+)$') + p:close() + toc = toc:gsub('()', '%1%2') -- strip function parameters + f = io_open(options.output_dir..'/api/'..name..'.html', 'wb') + local html = HTML:gsub('%%%(([^)]+)%)', { + title = name..' - Textadept API', nav = nav, toc = toc, main = main + }) + f:write(html) + f:close() + end +end diff --git a/scripts/update_doc b/scripts/update_doc index 74d1dd72..ccd42444 100755 --- a/scripts/update_doc +++ b/scripts/update_doc @@ -23,115 +23,77 @@ end -- Generate LuaDoc. if luadoc then - os.execute('rm -rf ../doc/modules/') - os.execute('cd ../; luadoc -d doc/ --nofiles modules/ core/ lexers/lexer.lua') - - -- Insert Markdown in modules into LuaDoc. - local p = io.popen('grep -r "\\-\\- Markdown:" ../*') - for file in p:lines() do - local module - - -- Open the Lua file and extract the Markdown lines. - local f = io.open(file:match('^[^:]+')) - local markdown, flag = {}, false - for line in f:lines() do - if flag and line:match('^%-%-') then - local match = line:match('^%-%- ([^\n]+)') - if match and match:find('^%s*[*+] ') then match = match..'
' end - markdown[#markdown + 1] = match or '' - elseif flag then -- markdown ended - break - elseif line:match('^%-%- Markdown:') then - flag = true - elseif line:match('^module') then - module = line:match("^module%('([^']+)") - end - end - f:close() - - -- Convert the Markdown into HTML. - markdown = table.concat(markdown, '\n') - f = io.open('tmp', 'w') - f:write(markdown) - f:close() - f = io.popen('perl ../doc/MultiMarkdown.pl tmp') - markdown = f:read('*all') - f:close() - os.execute('rm tmp') - - -- Insert the Marked down HTML in the LuaDoc HTML file. - local filename = '../doc/modules/'..module..'.html' - f = io.open(filename) - local contents = f:read('*all') - f:close() - local s = contents:find('

Functions

') - if not s then s = contents:find('

Tables

') end - contents = contents:sub(1, s - 1)..markdown..contents:sub(s) - f = io.open(filename, 'w') - f:write(contents) - f:close() - end - p:close() - - -- Modify default CSS. - os.execute("sed -i 's/pre.example/pre, pre.example/;' ../doc/luadoc.css") + os.execute('rm -r ../doc/api/*') + os.execute('luadoc -d ../doc -doclet markdowndoc '.. + '../modules ../core ../lexers/lexer.lua') end -- Generate the Manual. if manual then - p = io.popen('ls -1 ../doc/manual/*.md') - for mdfile in p:lines() do - local htmlfile = mdfile:match('^(.+).md$')..'.html' - html = [[ - - + local HTML = [[ + + - Textadept Manual - - + %(title) + + - -
-
- -
- - %content% - -
-
-
-

Valid XHTML 1.0!

-
-
+
+ +
+
Contents
+ %(toc) +
+
+ %(main) +
+
- - ]] - - local sidebar_md = io.popen('../doc/MultiMarkdown.pl ../doc/sidebar.md') - html = html:gsub('%%sidebar%%', sidebar_md:read('*all')) - sidebar_md:close() - local content_md = io.popen('../doc/MultiMarkdown.pl '..mdfile) - local md = content_md:read('*all'):gsub('%%', '%%%%') - md = md:gsub('()([^<]+)()', - function(s, text, e) - return string.format('%s%s%s', s, - text:gsub(' ', '_'):lower(), text, e) - end) - html = html:gsub('%%content%%', md) - content_md:close() + + ]] + + -- Get manual pages. + local pages = {} + local lfs = require 'lfs' + for file in lfs.dir('../doc/manual/') do + if file:find('^%d+_.-%.md$') then pages[#pages + 1] = file end + end + table.sort(pages) + pages[#pages + 1] = '../../README.md' + pages[#pages + 1] = '../../CHANGELOG.md' + pages[#pages + 1] = '../../THANKS.md' + + -- Create the navigation list. + local navfile = '../doc/manual/.nav.md' + local f = io.open(navfile, 'wb') + for _, page in ipairs(pages) do + local name = page:match('^%A+(.-)%.md$'):gsub('(%l)(%u)', '%1 %2') + if page:find('^%.%./') then page = page:match('^%A+(.+)$') end + f:write('* [', name, '](', page:gsub('%.md$', '.html'), ')\n') + end + f:close() + local p = io.popen('markdown "'..navfile..'"') + local nav = p:read('*all') + p:close() - local f = io.open(htmlfile, 'w') + -- Write HTML. + for _, page in ipairs(pages) do + local name = page:match('^%A+(.-)%.md$'):gsub('(%l)(%u)', '%1 %2') + local p = io.popen('markdown -f toc -T "../doc/manual/'..page..'"') + local toc, main = p:read('*all'):match('^(.-\n\n)(.+)$') + p:close() + if page:find('^%.%./') then page = page:match('^%A+(.+)$') end + f = io.open('../doc/manual/'..page:gsub('%.md$', '.html'), 'wb') + local html = HTML:gsub('%%%(([^)]+)%)', { + title = name..' - Textadept Manual', nav = nav, toc = toc, main = main + }) f:write(html) f:close() end - p:close() end -- Generate Doxygen documentation. -- cgit v1.2.3