-
Notifications
You must be signed in to change notification settings - Fork 4
/
tangle.lua
193 lines (149 loc) · 3.21 KB
/
tangle.lua
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
require "css-selector"
local blocks={}
--- Utilities
--- =========
local function split_classes(str)
local classes = {}
for class in string.gmatch(str, "[^ ]+") do
classes[class] = true
end
return classes
end
local function keep_only_lines(str)
local count = 0
for _ in string.gmatch(str,'\n') do
count = count + 1
end
return string.rep('\n',count)
end
--- Document Printers
--- =================
function Doc(body, metadata, variables)
local targets = parse(metadata.code or '*')
local block = 1
local function replace()
local classes = {}
for k,_ in pairs(blocks[block][1]) do
table.insert(classes,k)
end
local code = blocks[block][2]
block = block + 1
if eval(targets, classes) then
return code
else
return keep_only_lines(code)
end
end
return string.gsub(body,'#',replace)
end
--- Blocks
--- ------
function Plain(s)
return s..' '
end
function Para(s)
return s..'\n'
end
--- LineBlock
function CodeBlock(s, attr)
table.insert(blocks,{split_classes(attr.class or ''),s})
return '\n#\n\n'
end
--- RawBlock
--- BlockQuote
function OrderedList(items)
return BulletList(items)
end
function BulletList(items)
if #items == 0 then
return ''
else
if items[#items]:byte(-1) ~= 10 then
items[#items] = items[#items]..'\n'
end
return keep_only_lines(table.concat(items,'\n'))
end
end
--- DefinitionList
function Header(lvl,text)
text = keep_only_lines(text)
if lvl == 1 then
return text..'\n\n'
elseif lvl == 2 then
return text..'\n\n'
elseif lvl == 3 then
return text..'\n'
else
return text..'\n'
end
end
--- HorizontalRule
function Table(s)
return keep_only_lines(s)
end
--- Div
--- Null
--- Inlines
--- -------
local function InlineMarkup(s)
return keep_only_lines(s)
end
function Str(s)
return keep_only_lines(s)
end
Emph = InlineMarkup
Strong = InlineMarkup
Strikeout = InlineMarkup
Superscript = InlineMarkup
Subscript = InlineMarkup
SmallCaps = InlineMarkup
--- Quoted
--- Cite
Code = InlineMarkup
function Space()
return ''
end
function SoftBreak()
return '\n'
end
function LineBreak()
return '\n'
end
--- Math
--- RawInline
function Link(text,target,title,attr)
return keep_only_lines(text)..keep_only_lines(target)
end
function Image()
return ''
end
function Note()
return ''
end
Span = InlineMarkup
--- Backwards compatibility
--- -----------------------
function DisplayMath(s)
return keep_only_lines(s)
end
function Blocksep()
return '\n'
end
local function IgnoreBlock(key)
return function(s,a,b,c)
return (type(s) == 'string' and keep_only_lines(s)) or ''
end
end
InlineMath = InlineMarkup
DiplayMath = InlineMarkup
DoubleQuoted = InlineMarkup
--- Ignore Non-Existant Document Elements
--- =====================================
local meta = {}
meta.__index =
function(_, key)
io.stderr:write(string.format("WARNING: Undefined tangle function '%s'\n",key))
_G[key] = IgnoreBlock(key)
return _G[key]
end
setmetatable(_G, meta)