1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
--- include-files.lua – filter to include Markdown files
---
--- Copyright: © 2019–2021 Albert Krewinkel
--- License: MIT – see LICENSE file for details
-- Module pandoc.path is required and was added in version 2.12
PANDOC_VERSION:must_be_at_least '2.12'
local List = require 'pandoc.List'
local path = require 'pandoc.path'
local system = require 'pandoc.system'
--- Get include auto mode
local include_auto = false
function get_vars (meta)
if meta['include-auto'] then
include_auto = true
end
end
--- Keep last heading level found
local last_heading_level = 0
function update_last_level(header)
last_heading_level = header.level
end
--- Update contents of included file
local function update_contents(blocks, shift_by, include_path)
local update_contents_filter = {
-- Shift headings in block list by given number
Header = function (header)
if shift_by then
header.level = header.level + shift_by
end
return header
end,
-- If image paths are relative then prepend include file path
Image = function (image)
if path.is_relative(image.src) and image.src:sub(1,5) ~= "logos" then
image.src = path.normalize(path.join({include_path, image.src}))
end
return image
end,
-- If tex input paths are relative then prepend include file path
RawBlock = function (el)
-- Only handle tex RawBlocks
if el.format ~= 'tex' then
return el
end
el.text = el.text:gsub('\\input{([^}]+)}', function(match)
local input_path = match
if path.is_relative(include_path) then
include_path = path.normalize(path.join({include_path, input_path}))
end
return '\\input{' .. include_path .. '}'
end)
return el
end,
-- Update path for include-code-files.lua filter style CodeBlocks
CodeBlock = function (cb)
if cb.attributes.include and path.is_relative(cb.attributes.include) then
cb.attributes.include =
path.normalize(path.join({include_path, cb.attributes.include}))
end
return cb
end
}
return pandoc.walk_block(pandoc.Div(blocks), update_contents_filter).content
end
--- Filter function for code blocks
local transclude
function transclude (cb)
-- ignore code blocks which are not of class "include".
if not cb.classes:includes 'include' then
return
end
-- Markdown is used if this is nil.
local format = cb.attributes['format']
-- Attributes shift headings
local shift_heading_level_by = 0
local shift_input = cb.attributes['shift-heading-level-by']
if shift_input then
shift_heading_level_by = tonumber(shift_input)
else
if include_auto then
-- Auto shift headings
shift_heading_level_by = last_heading_level
end
end
--- keep track of level before recursion
local buffer_last_heading_level = last_heading_level
local blocks = List:new()
for line in cb.text:gmatch('[^\n]+') do
if line:sub(1,2) ~= '//' then
local fh = io.open(line)
if not fh then
io.stderr:write("Cannot open file " .. line .. " | Skipping includes\n")
else
-- read file as the given format with global reader options
local contents = pandoc.read(
fh:read '*a',
format,
PANDOC_READER_OPTIONS
).blocks
last_heading_level = 0
-- recursive transclusion
contents = system.with_working_directory(
path.directory(line),
function ()
return pandoc.walk_block(
pandoc.Div(contents),
{ Header = update_last_level, CodeBlock = transclude }
)
end).content
--- reset to level before recursion
last_heading_level = buffer_last_heading_level
blocks:extend(update_contents(contents, shift_heading_level_by,
path.directory(line)))
fh:close()
end
end
end
return blocks
end
return {
{ Meta = get_vars },
{ Header = update_last_level, CodeBlock = transclude }
}
|