2011-07-05 16:30:49 +02:00
|
|
|
--------------
|
|
|
|
-- Handling markup transformation.
|
|
|
|
-- Currently just does Markdown, but this is intended to
|
|
|
|
-- be the general module for managing other formats as well.
|
|
|
|
|
2011-07-05 18:19:49 +02:00
|
|
|
require 'pl'
|
2011-07-11 15:40:44 +02:00
|
|
|
local doc = require 'ldoc.doc'
|
2011-07-05 16:30:49 +02:00
|
|
|
local utils = require 'pl.utils'
|
2011-07-12 14:14:55 +02:00
|
|
|
local prettify = require 'ldoc.prettify'
|
|
|
|
local quit, concat, lstrip = utils.quit, table.concat, stringx.lstrip
|
2011-07-05 16:30:49 +02:00
|
|
|
local markup = {}
|
|
|
|
|
2011-07-06 15:24:05 +02:00
|
|
|
-- workaround Markdown's need for blank lines around indented blocks
|
|
|
|
-- (does mean you have to keep indentation discipline!)
|
|
|
|
function markup.insert_markdown_lines (txt)
|
|
|
|
local res, append = {}, table.insert
|
2011-07-12 14:14:55 +02:00
|
|
|
local last_indent, start_indent, skip, code = -1, -1, false, nil
|
2011-07-06 15:24:05 +02:00
|
|
|
for line in stringx.lines(txt) do
|
2011-07-12 14:14:55 +02:00
|
|
|
line = line:gsub('\t',' ') -- some people like tabs ;)
|
2011-07-06 15:24:05 +02:00
|
|
|
if not line:match '^%s*$' then --ignore blank lines
|
|
|
|
local indent = #line:match '^%s*'
|
|
|
|
if start_indent < 0 then -- initialize indents at start
|
|
|
|
start_indent = indent
|
|
|
|
last_indent = indent
|
|
|
|
end
|
|
|
|
if indent < start_indent then -- end of indented block
|
|
|
|
append(res,'')
|
|
|
|
skip = false
|
2011-07-12 14:14:55 +02:00
|
|
|
if code then
|
|
|
|
code = concat(code,'\n')
|
|
|
|
code, err = prettify.lua(code)
|
|
|
|
if code then
|
|
|
|
append(res,code)
|
|
|
|
append(res,'</pre>')
|
|
|
|
end
|
|
|
|
code = nil
|
|
|
|
end
|
2011-07-06 15:24:05 +02:00
|
|
|
end
|
|
|
|
if not skip and indent > last_indent then -- start of indent
|
|
|
|
append(res,'')
|
|
|
|
skip = true
|
|
|
|
start_indent = indent
|
2011-07-12 14:14:55 +02:00
|
|
|
if indent >= 4 then
|
|
|
|
code = {}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if code then
|
|
|
|
append(code, line:sub(start_indent))
|
|
|
|
else
|
|
|
|
append(res,line)
|
2011-07-06 15:24:05 +02:00
|
|
|
end
|
|
|
|
last_indent = indent
|
2011-07-12 14:14:55 +02:00
|
|
|
elseif not code then
|
2011-07-06 15:24:05 +02:00
|
|
|
append(res,'')
|
|
|
|
end
|
|
|
|
end
|
2011-07-12 14:14:55 +02:00
|
|
|
res = concat(res,'\n')
|
|
|
|
return res
|
2011-07-06 15:24:05 +02:00
|
|
|
end
|
|
|
|
|
2011-07-11 15:40:44 +02:00
|
|
|
-- for readme text, the idea here is to insert module sections at ## so that
|
|
|
|
-- they can appear in the contents list as a ToC
|
|
|
|
function markup.add_sections(F, txt)
|
|
|
|
local res, append = {}, table.insert
|
|
|
|
for line in stringx.lines(txt) do
|
|
|
|
local title = line:match '^##[^#]%s*(.+)'
|
|
|
|
if title then
|
2011-07-12 14:14:55 +02:00
|
|
|
local section = F:add_document_section(title)
|
2011-07-11 15:40:44 +02:00
|
|
|
append(res,('<a id="%s"></a>\n'):format(section))
|
|
|
|
append(res,line)
|
|
|
|
else
|
|
|
|
append(res,line)
|
2011-07-06 15:24:05 +02:00
|
|
|
end
|
2011-07-11 15:40:44 +02:00
|
|
|
end
|
2011-07-12 14:14:55 +02:00
|
|
|
return concat(res,'\n')
|
2011-07-11 15:40:44 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function handle_reference (ldoc, name)
|
|
|
|
local ref,err = markup.process_reference(name)
|
|
|
|
if not ref then
|
|
|
|
if ldoc.item then ldoc.item:warning(err)
|
|
|
|
else
|
|
|
|
io.stderr:write(err,'\n')
|
|
|
|
end
|
|
|
|
return ''
|
|
|
|
end
|
|
|
|
local label = ref.label
|
|
|
|
if not ldoc.plain then -- a nastiness with markdown.lua and underscores
|
|
|
|
label = label:gsub('_','\\_')
|
|
|
|
end
|
|
|
|
local res = ('<a href="%s">%s</a>'):format(ldoc.href(ref),label)
|
|
|
|
return res
|
|
|
|
end
|
|
|
|
|
|
|
|
local ldoc_handle_reference
|
|
|
|
|
|
|
|
-- inline <references> use same lookup as @see
|
|
|
|
local function resolve_inline_references (ldoc, txt)
|
|
|
|
return (txt:gsub('@{([%w_%.%-]-)}',ldoc_handle_reference))
|
2011-07-06 15:24:05 +02:00
|
|
|
end
|
|
|
|
|
2011-07-05 18:19:49 +02:00
|
|
|
function markup.create (ldoc, format)
|
2011-07-11 15:40:44 +02:00
|
|
|
local processor
|
|
|
|
ldoc_handle_reference = utils.bind1(handle_reference,ldoc)
|
|
|
|
markup.plain = true
|
|
|
|
markup.process_reference = function(name)
|
|
|
|
local mod = ldoc.single or ldoc.module
|
|
|
|
return mod:process_see_reference(name, ldoc.modules)
|
|
|
|
end
|
|
|
|
markup.href = function(ref)
|
|
|
|
return ldoc.href(ref)
|
|
|
|
end
|
2011-07-12 14:14:55 +02:00
|
|
|
|
2011-07-06 15:24:05 +02:00
|
|
|
if format == 'plain' then
|
2011-07-11 15:40:44 +02:00
|
|
|
processor = function(txt)
|
2011-07-06 15:24:05 +02:00
|
|
|
if txt == nil then return '' end
|
2011-07-11 15:40:44 +02:00
|
|
|
return resolve_inline_references(ldoc, txt)
|
2011-07-06 15:24:05 +02:00
|
|
|
end
|
|
|
|
else
|
|
|
|
local ok,formatter = pcall(require,format)
|
|
|
|
if not ok then quit("cannot load formatter: "..format) end
|
2011-07-11 15:40:44 +02:00
|
|
|
markup.plain = false
|
|
|
|
processor = function (txt)
|
2011-07-06 15:24:05 +02:00
|
|
|
if txt == nil then return '' end
|
2011-07-11 15:40:44 +02:00
|
|
|
txt = resolve_inline_references(ldoc, txt)
|
2011-07-06 15:24:05 +02:00
|
|
|
if txt:find '\n' and not ldoc.classic_markdown then -- multiline text
|
|
|
|
txt = markup.insert_markdown_lines(txt)
|
2011-07-05 18:53:28 +02:00
|
|
|
end
|
2011-07-06 15:24:05 +02:00
|
|
|
txt = formatter (txt)
|
|
|
|
-- We will add our own paragraph tags, if needed.
|
|
|
|
return (txt:gsub('^%s*<p>(.+)</p>%s*$','%1'))
|
2011-07-05 18:53:28 +02:00
|
|
|
end
|
2011-07-05 16:30:49 +02:00
|
|
|
end
|
2011-07-11 15:40:44 +02:00
|
|
|
markup.resolve_inline_references = function(txt)
|
|
|
|
return resolve_inline_references(ldoc, txt)
|
|
|
|
end
|
|
|
|
markup.processor = processor
|
2011-07-12 14:14:55 +02:00
|
|
|
prettify.resolve_inline_references = markup.resolve_inline_references
|
2011-07-11 15:40:44 +02:00
|
|
|
return processor
|
2011-07-05 16:30:49 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
return markup
|