depth 1 replace
This commit is contained in:
@@ -6,4 +6,10 @@ This is a pandoc filter manipulating [fenced_divs](https://pandoc.org/MANUAL.htm
|
||||
Inspired by [this joke](https://www.zhihu.com/question/586807834/answer/2973535981).
|
||||
|
||||
useful refs:
|
||||
- https://pandoc.org/lua-filters.html
|
||||
- https://pandoc.org/lua-filters.html
|
||||
|
||||
# How does this work?
|
||||
|
||||
`filter.lua` walks the AST. There are some special leaf nodes with a `include` attr which is a string containing labels of some other divs to be included here.
|
||||
|
||||
For each of `include` node `i`, we maintain a list `fa[i]` containing nodes with labels on the path `i -> root`. Then for each label `l` in `i`'s include list, one can see that every node in `fa[i]` depends on `l`. Thus we build a digraph G on labels. If G is a DAG, then we can use topological sort to rank its vertices and thus decide the order of substitution; Otherwise, G contains a directed cycle, the filter reports an error.
|
||||
53
filter.lua
53
filter.lua
@@ -1,3 +1,11 @@
|
||||
local label_map = {} -- label has to be unique!
|
||||
|
||||
local function collect_labels(div) -- only collect labels in div
|
||||
if div.identifier and div.identifier ~= "" then
|
||||
label_map[div.identifier] = div:clone()
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function words(s)
|
||||
local res = {}
|
||||
@@ -10,27 +18,36 @@ local function words(s)
|
||||
return res
|
||||
end
|
||||
|
||||
local function label2Block(labels)
|
||||
local contents = ""
|
||||
for _,l in ipairs(words(labels)) do
|
||||
-- use file for now.
|
||||
local fh = io.open(l, "r")
|
||||
if not fh then
|
||||
io.stderr:write("Cannot open file: " .. l .. "\n")
|
||||
return { pandoc.Plain { pandoc.Str("[Error: cannot read file " .. l .. "]") } }
|
||||
end
|
||||
contents = contents .. fh:read("*a")
|
||||
fh:close()
|
||||
end
|
||||
return { pandoc.Plain { pandoc.Str(contents) } }
|
||||
end
|
||||
|
||||
function Div(e)
|
||||
local function replace(e)
|
||||
local include = e.attributes["include"]
|
||||
if include then
|
||||
local blocks = label2Block(include)
|
||||
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())
|
||||
io.stderr:write("insert [" .. label_map[l].identifier .. ']\n')
|
||||
else
|
||||
io.stderr:write("Cannot find AST node with label " .. l)
|
||||
end
|
||||
end
|
||||
return pandoc.Div(blocks, e.attr)
|
||||
end
|
||||
return nil -- no change
|
||||
return e -- no change
|
||||
end
|
||||
|
||||
return {
|
||||
-- traverse = 'topdown',
|
||||
Pandoc = function(doc)
|
||||
-- collect labels
|
||||
for _, blk in ipairs(doc.blocks) do
|
||||
collect_labels(blk)
|
||||
end
|
||||
|
||||
-- replace
|
||||
for i, blk in ipairs(doc.blocks) do
|
||||
doc.blocks[i] = replace(blk)
|
||||
end
|
||||
return doc
|
||||
end
|
||||
}
|
||||
|
||||
6
input.md
6
input.md
@@ -1,7 +1,9 @@
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce porta mattis neque, quis molestie nunc faucibus vitae. Phasellus vel commodo dolor, at faucibus arcu. Curabitur sit amet magna a neque euismod feugiat non et diam. Aliquam sit amet libero enim. Integer dignissim ullamcorper felis, ac ultrices turpis congue vel. Nulla id tempus orci. Curabitur ac vulputate tellus. Integer fermentum tempor facilisis. Duis egestas luctus tristique. Maecenas vitae arcu sit amet justo feugiat imperdiet. Nunc luctus erat sed ligula convallis hendrerit.
|
||||
::: {#lorem}
|
||||
Lorem ipsum dolor sit amet
|
||||
:::
|
||||
|
||||
:::{include="README.md , filter.lua , ,"}
|
||||
:::{include="lorem, thm2 , fakelabel , "}
|
||||
:::
|
||||
|
||||
|
||||
|
||||
69
output.html
69
output.html
@@ -1,62 +1,13 @@
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce porta
|
||||
mattis neque, quis molestie nunc faucibus vitae. Phasellus vel commodo
|
||||
dolor, at faucibus arcu. Curabitur sit amet magna a neque euismod
|
||||
feugiat non et diam. Aliquam sit amet libero enim. Integer dignissim
|
||||
ullamcorper felis, ac ultrices turpis congue vel. Nulla id tempus orci.
|
||||
Curabitur ac vulputate tellus. Integer fermentum tempor facilisis. Duis
|
||||
egestas luctus tristique. Maecenas vitae arcu sit amet justo feugiat
|
||||
imperdiet. Nunc luctus erat sed ligula convallis hendrerit.</p>
|
||||
<div data-include="README.md , filter.lua , ,">
|
||||
# Piecewise Readable Filter
|
||||
|
||||
This is a pandoc filter manipulating
|
||||
[fenced_divs](https://pandoc.org/MANUAL.html#extension-fenced_divs) in
|
||||
pandoc markdown.
|
||||
|
||||
Inspired by [this
|
||||
joke](https://www.zhihu.com/question/586807834/answer/2973535981).
|
||||
|
||||
useful refs:
|
||||
- https://pandoc.org/lua-filters.html
|
||||
|
||||
local function words(s)
|
||||
local res = {}
|
||||
for part in s:gmatch("[^,]+") do -- split by commas
|
||||
local trimmed = part:match("^%s*(.-)%s*$") -- remove
|
||||
leading/trailing spaces
|
||||
if trimmed ~= "" then
|
||||
table.insert(res, trimmed)
|
||||
end
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
local function label2Block(labels)
|
||||
local contents = ""
|
||||
for _,l in ipairs(words(labels)) do
|
||||
-- use file for now.
|
||||
local fh = io.open(l, "r")
|
||||
if not fh then
|
||||
io.stderr:write("Cannot open file: " .. l .. "\n")
|
||||
return { pandoc.Plain { pandoc.Str("[Error: cannot read file
|
||||
" .. l .. "]") } }
|
||||
end
|
||||
contents = contents .. fh:read("*a")
|
||||
fh:close()
|
||||
end
|
||||
return { pandoc.Plain { pandoc.Str(contents) } }
|
||||
end
|
||||
|
||||
function Div(e)
|
||||
local include = e.attributes["include"]
|
||||
if include then
|
||||
local blocks = label2Block(include)
|
||||
-- Replace the Div contents
|
||||
return pandoc.Div(blocks, e.attr)
|
||||
end
|
||||
return nil -- no change
|
||||
end
|
||||
|
||||
<div id="lorem">
|
||||
<p>Lorem ipsum dolor sit amet</p>
|
||||
</div>
|
||||
<div data-include="lorem, thm2 , fakelabel , ">
|
||||
<div id="lorem">
|
||||
<p>Lorem ipsum dolor sit amet</p>
|
||||
</div>
|
||||
<div id="thm2" class="Theorem">
|
||||
<p>test thm2</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="Theorem">
|
||||
<p>test thm1</p>
|
||||
|
||||
Reference in New Issue
Block a user