yay
This commit is contained in:
82
filter.lua
82
filter.lua
@@ -4,8 +4,8 @@ local function show(s)
|
||||
end
|
||||
|
||||
------------------------------------------------
|
||||
local label_map = {} -- label has to be unique!
|
||||
local adj = {} -- graph
|
||||
local adj = {} -- graph
|
||||
local include_nodes = {}
|
||||
local function add_edge(u, v)
|
||||
if not adj[u] then
|
||||
adj[u] = {}
|
||||
@@ -14,7 +14,7 @@ local function add_edge(u, v)
|
||||
end
|
||||
|
||||
---------------------------------------------------------
|
||||
-- Topological sort (DFS-based, with cycle detection)
|
||||
-- Topological sort (DFS-based, with cycle detection) -- chatgpt
|
||||
---------------------------------------------------------
|
||||
local visited = {} -- "perm" mark: node completely processed
|
||||
local in_stack = {} -- "temp" mark: node currently in recursion stack
|
||||
@@ -49,28 +49,21 @@ local function _dfs(u, path)
|
||||
end
|
||||
|
||||
local function topo_sort()
|
||||
local rank = {}
|
||||
for u, _ in pairs(adj) do
|
||||
if not visited[u] then
|
||||
_dfs(u, {})
|
||||
if cycle then return nil, cycle end
|
||||
if cycle then return rank, cycle end
|
||||
end
|
||||
end
|
||||
|
||||
-- build rank map
|
||||
local rank = {}
|
||||
for i, u in ipairs(order) do
|
||||
rank[u] = i
|
||||
end
|
||||
return rank
|
||||
end
|
||||
|
||||
local function collect_labels(blk)
|
||||
if blk.identifier and blk.identifier ~= "" then
|
||||
label_map[blk.identifier] = blk:clone()
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function words(s)
|
||||
local res = {}
|
||||
for part in s:gmatch("[^,]+") do -- split by commas
|
||||
@@ -83,12 +76,12 @@ local function words(s)
|
||||
end
|
||||
|
||||
local function dfs(blk, stack) -- depth first search on a top level blk
|
||||
-- check for identifier and build label_map
|
||||
-- look for 2 types of AST node: divs with include attr and divs with labels
|
||||
local labelled = false
|
||||
local include = false
|
||||
if blk.attributes and blk.attributes["include"] then -- this must be a leaf node
|
||||
include = true
|
||||
table.insert(include_nodes, blk.identifier)
|
||||
-- labels in include may appears later in the dfs than this include-node
|
||||
-- but we assume every label will be there and build the graph now
|
||||
-- This is a directed bipartite grpah.
|
||||
@@ -107,7 +100,6 @@ local function dfs(blk, stack) -- depth first search on a top level blk
|
||||
elseif blk.identifier and blk.identifier ~= "" then
|
||||
-- collect labelled nodes & maintain the stack
|
||||
labelled = true
|
||||
label_map[blk.identifier] = blk:clone()
|
||||
table.insert(stack, blk.identifier)
|
||||
end
|
||||
|
||||
@@ -125,22 +117,31 @@ local function dfs(blk, stack) -- depth first search on a top level blk
|
||||
end
|
||||
end
|
||||
|
||||
local function replace(e)
|
||||
local include = e.attributes["include"]
|
||||
if include then
|
||||
local blocks = {}
|
||||
-- Replace the Div contents
|
||||
for _, l in ipairs(words(include)) do
|
||||
if label_map[l] then
|
||||
table.insert(blocks, label_map[l]:clone())
|
||||
show("insert [" .. label_map[l].identifier .. ']\n')
|
||||
else
|
||||
io.stderr:write("Cannot find AST node with label " .. l .. "\n")
|
||||
-- read doc and return the concatenation of target nodes for an include-node
|
||||
-- Things become messy here since the include list is ordered.
|
||||
-- one has to again transverse the AST to collect labelled nodes and then
|
||||
-- do the concatenation...
|
||||
local function collect_node(doc, l)
|
||||
local blocks = {}
|
||||
local targets = words(l.attributes["include"])
|
||||
local nodes = {}
|
||||
doc:walk {
|
||||
Div = function(div)
|
||||
if div.identifier and div.identifier ~= "" then
|
||||
nodes[div.identifier] = div:clone()
|
||||
end
|
||||
return nil
|
||||
end
|
||||
}
|
||||
for _, t in ipairs(targets) do
|
||||
if nodes[t] then
|
||||
table.insert(blocks, nodes[t]:clone())
|
||||
-- show("insert [" .. nodes[t].identifier .. ']\n')
|
||||
else
|
||||
io.stderr:write("Cannot find AST node with label " .. t .. "\n")
|
||||
end
|
||||
return pandoc.Div(blocks, e.attr)
|
||||
end
|
||||
return e -- no change
|
||||
return pandoc.Div(blocks, l.attr)
|
||||
end
|
||||
|
||||
return {
|
||||
@@ -151,30 +152,23 @@ return {
|
||||
dfs(blk, {})
|
||||
end
|
||||
|
||||
-- sanity check
|
||||
show("edges:")
|
||||
for u, vs in pairs(adj) do
|
||||
for _, v in ipairs(vs) do
|
||||
show(u .. "->" .. v)
|
||||
end
|
||||
end
|
||||
|
||||
-- topological sort
|
||||
local rank, cycle = topo_sort()
|
||||
if cycle then
|
||||
error("Cycle detected:" .. table.concat(cycle, " -> ") .. "\n")
|
||||
end
|
||||
|
||||
-- sanity check
|
||||
show("ranks:")
|
||||
for k, v in pairs(rank) do
|
||||
show(k .. "--" .. v)
|
||||
end
|
||||
|
||||
-- replace
|
||||
-- for i, blk in ipairs(doc.blocks) do
|
||||
-- doc.blocks[i] = replace(blk)
|
||||
-- end
|
||||
table.sort(include_nodes, function(x, y)
|
||||
return rank[x] > rank[y]
|
||||
end)
|
||||
for _, v in ipairs(include_nodes) do
|
||||
doc = doc:walk { Div = function(div)
|
||||
if div.identifier and div.identifier == v then
|
||||
return collect_node(doc, div)
|
||||
end
|
||||
end }
|
||||
end
|
||||
return doc
|
||||
end
|
||||
}
|
||||
|
||||
4
input.md
4
input.md
@@ -1,6 +1,6 @@
|
||||
|
||||
::: {#structure}
|
||||
inc (need thm2 and a fake label)
|
||||
inc (need thm2, thm1 and a fake label)
|
||||
|
||||
thm1 - inthm1
|
||||
|
||||
@@ -8,7 +8,7 @@ thm2 - inthm2 (need thm1)
|
||||
|
||||
::::::::::::::::
|
||||
|
||||
:::{include="thm2 , fakelabel" #inc}
|
||||
:::{include="thm2, thm1 , fakelabel" #inc}
|
||||
This line will be ignored
|
||||
:::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
|
||||
29
output.html
29
output.html
@@ -1,10 +1,26 @@
|
||||
<div id="structure">
|
||||
<p>inc (need thm2 and a fake label)</p>
|
||||
<p>inc (need thm2, thm1 and a fake label)</p>
|
||||
<p>thm1 - inthm1</p>
|
||||
<p>thm2 - inthm2 (need thm1)</p>
|
||||
</div>
|
||||
<div id="inc" data-include="thm2 , fakelabel">
|
||||
<p>This line will be ignored</p>
|
||||
<div id="inc" data-include="thm2, thm1 , fakelabel">
|
||||
<div id="thm2" class="Theorem">
|
||||
<p>test thm2</p>
|
||||
<div id="inthm2" data-include="thm1">
|
||||
<div id="thm1" class="Theorem">
|
||||
<p>test thm1</p>
|
||||
<div id="inthm1" class="Definition">
|
||||
<p>something</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="thm1" class="Theorem">
|
||||
<p>test thm1</p>
|
||||
<div id="inthm1" class="Definition">
|
||||
<p>something</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="thm1" class="Theorem">
|
||||
<p>test thm1</p>
|
||||
@@ -15,7 +31,12 @@
|
||||
<div id="thm2" class="Theorem">
|
||||
<p>test thm2</p>
|
||||
<div id="inthm2" data-include="thm1">
|
||||
<p>i need theorem 1</p>
|
||||
<div id="thm1" class="Theorem">
|
||||
<p>test thm1</p>
|
||||
<div id="inthm1" class="Definition">
|
||||
<p>something</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="thm3" class="Theorem">
|
||||
|
||||
Reference in New Issue
Block a user