145 lines
3.6 KiB
Lua
145 lines
3.6 KiB
Lua
|
local l = require("pandoc.logging")
|
||
|
local read = pandoc.read
|
||
|
|
||
|
assert(#arg == 2, "\n" ..
|
||
|
"[ERROR] usage: pandoc lua sitemap.lua <index file> <output file>")
|
||
|
|
||
|
local node_list = {}
|
||
|
local graph_map = {}
|
||
|
local function collect (fp)
|
||
|
local f = assert(io.open(fp), "\n" ..
|
||
|
"[ERROR] could not open " .. fp .. " for reading.")
|
||
|
table.insert(node_list, fp)
|
||
|
graph_map[fp] = { order = #node_list, nodes = {} }
|
||
|
local data = f:read("a")
|
||
|
f:close()
|
||
|
local visited = {}
|
||
|
read(data):walk({ Link = function (link)
|
||
|
local f = io.open(link.target)
|
||
|
if f == nil then return else f:close() end
|
||
|
if visited[link.target] then return end
|
||
|
visited[link.target] = true
|
||
|
table.insert(graph_map[fp]["nodes"], link.target)
|
||
|
if not graph_map[link.target] then collect(link.target) end
|
||
|
end })
|
||
|
end
|
||
|
|
||
|
collect(arg[1])
|
||
|
|
||
|
local L = {
|
||
|
SW = ".", L = "<", W = "-", NW = ".",
|
||
|
S = "|", X = " ", N = "|",
|
||
|
SE = "'", R = ">", E = "-", NE = "'",
|
||
|
}
|
||
|
|
||
|
local layout = {}
|
||
|
local r_wing = {}
|
||
|
local l_wing = {}
|
||
|
for i,node in ipairs(node_list) do
|
||
|
r_wing[i] = {}
|
||
|
layout[i] = node
|
||
|
l_wing[i] = {}
|
||
|
end
|
||
|
|
||
|
local function reverse (t)
|
||
|
for i=1,#t//2 do
|
||
|
t[i],t[#t-i+1] = t[#t-i+1],t[i]
|
||
|
end
|
||
|
return t
|
||
|
end
|
||
|
|
||
|
local function find_free_col(wing, a, b)
|
||
|
local col = 1
|
||
|
while true do
|
||
|
for i=a,b do
|
||
|
local cell = wing[i][col]
|
||
|
if cell ~= nil and cell ~= L["X"] then
|
||
|
goto continue
|
||
|
end
|
||
|
end
|
||
|
do return col end
|
||
|
::continue::
|
||
|
col = col + 1
|
||
|
end
|
||
|
return col
|
||
|
end
|
||
|
|
||
|
for _,node in ipairs(node_list) do
|
||
|
local a_node = graph_map[node]
|
||
|
for _,node in ipairs(a_node["nodes"]) do
|
||
|
local a = a_node["order"]
|
||
|
local b = graph_map[node]["order"]
|
||
|
|
||
|
local i1 = 1
|
||
|
local ia = math.min(a,b)
|
||
|
local ib = math.max(a,b)
|
||
|
local iz = #node_list
|
||
|
local wing = a < b and r_wing or l_wing
|
||
|
local r_first, l_first = true, true
|
||
|
local first = a < b and r_first or l_first
|
||
|
|
||
|
local col = find_free_col(wing, ia, ib)
|
||
|
if col == 1 then col = 2 end
|
||
|
local a_row = wing[ia]
|
||
|
if a_row[1] == nil or a_row[1] == " " then
|
||
|
a_row[1] = a < b and "-" or "<"
|
||
|
end
|
||
|
for i=1,col-1 do
|
||
|
if a_row[i] == nil or a_row[i] == L["X"] then a_row[i] = "-" end
|
||
|
end
|
||
|
a_row[col] = "."
|
||
|
for i=ia+1,ib-1 do
|
||
|
for j=1,col-1 do
|
||
|
if wing[i][j] == nil then wing[i][j] = " " end
|
||
|
end
|
||
|
wing[i][col] = "|"
|
||
|
end
|
||
|
local b_row = wing[ib]
|
||
|
if b_row[1] == nil or b_row[1] == " " then
|
||
|
b_row[1] = a < b and ">" or "-"
|
||
|
end
|
||
|
for i=1,col-1 do
|
||
|
if b_row[i] == nil or b_row[i] == L["X"] then b_row[i] = "-" end
|
||
|
end
|
||
|
b_row[col] = "'"
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- write
|
||
|
local data = {}
|
||
|
table.insert(data, "<nav id=\"sitemap\">")
|
||
|
table.insert(data, "<header>")
|
||
|
table.insert(data, "<h1>sitemap</h1>")
|
||
|
table.insert(data, "</header>")
|
||
|
table.insert(data, "<pre>")
|
||
|
|
||
|
-- pad right wing
|
||
|
local r_wing_pad = 1
|
||
|
for _,len in pairs(r_wing) do
|
||
|
if #len > r_wing_pad then r_wing_pad = #len end
|
||
|
end
|
||
|
-- pad node names
|
||
|
local node_pad = 1
|
||
|
for _,s in pairs(layout) do
|
||
|
if s:len() > node_pad then node_pad = s:len() end
|
||
|
end
|
||
|
|
||
|
for i,v in ipairs(layout) do
|
||
|
local row = {}
|
||
|
local v = ("%-"..node_pad.."s"):format(v)
|
||
|
local a = v:gsub("(.+)%.md", "<a href=\"%1.html\">%0</a>")
|
||
|
table.insert(row,(("%"..r_wing_pad.."s"):format(table.concat(reverse(r_wing[i])))))
|
||
|
table.insert(row,((" %s "):format(a)))
|
||
|
table.insert(row,(table.concat(l_wing[i])))
|
||
|
|
||
|
table.insert(data,table.concat(row))
|
||
|
end
|
||
|
|
||
|
table.insert(data, "</pre>")
|
||
|
table.insert(data, "</nav>")
|
||
|
|
||
|
local f = assert(io.open(arg[2], "w"), "\n" ..
|
||
|
"[ERROR] could not open " .. arg[2] .. " for writing.")
|
||
|
f:write(table.concat(data, "\n"))
|
||
|
f:close()
|