pandoc2review 1.6.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/lint.yml +14 -0
- data/.github/workflows/pandoc.yml +1 -1
- data/.rubocop.yml +305 -0
- data/Gemfile +0 -2
- data/README.md +5 -0
- data/Rakefile +13 -3
- data/exe/pandoc2review +1 -2
- data/lib/pandoc2review.rb +17 -10
- data/lua/filters.lua +30 -67
- data/lua/review.lua +295 -155
- data/pandoc2review.gemspec +23 -16
- data/stylua.toml +3 -0
- metadata +62 -2
data/lua/review.lua
CHANGED
@@ -25,7 +25,7 @@ local footnotes = {}
|
|
25
25
|
|
26
26
|
-- internal
|
27
27
|
local metadata = nil
|
28
|
-
local stringify = (require
|
28
|
+
local stringify = (require("pandoc.utils")).stringify
|
29
29
|
local inline_commands = {
|
30
30
|
-- processed if given as classes of Span elements
|
31
31
|
-- true if syntax is `@<command>{string}`
|
@@ -48,7 +48,7 @@ local inline_commands = {
|
|
48
48
|
title = true,
|
49
49
|
chapref = true,
|
50
50
|
list = true,
|
51
|
-
img =
|
51
|
+
img = true,
|
52
52
|
table = true,
|
53
53
|
eq = true,
|
54
54
|
hd = true,
|
@@ -83,21 +83,19 @@ local function log(s)
|
|
83
83
|
end
|
84
84
|
|
85
85
|
local function surround_inline(s)
|
86
|
-
if
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
else
|
92
|
-
-- surround by ||
|
93
|
-
return "|" .. s .. "|"
|
94
|
-
end
|
95
|
-
else
|
96
|
-
-- surround by $$
|
97
|
-
return "$" .. s .. "$"
|
98
|
-
end
|
86
|
+
if not s:match("[{}]") then
|
87
|
+
return "{" .. s .. "}"
|
88
|
+
end
|
89
|
+
if not s:match("%$") then
|
90
|
+
return "$" .. s .. "$"
|
99
91
|
end
|
100
|
-
|
92
|
+
|
93
|
+
-- use % for regexp escape
|
94
|
+
if s:match("|") then
|
95
|
+
-- give up. escape } by \}
|
96
|
+
return "{" .. s:gsub("}", "\\}") .. "}"
|
97
|
+
end
|
98
|
+
return "|" .. s .. "|"
|
101
99
|
end
|
102
100
|
|
103
101
|
local function format_inline(fmt, s)
|
@@ -105,31 +103,18 @@ local function format_inline(fmt, s)
|
|
105
103
|
end
|
106
104
|
|
107
105
|
local function html_align(align)
|
108
|
-
|
109
|
-
return ""
|
110
|
-
elseif align == "AlignRight" then
|
111
|
-
return "right"
|
112
|
-
elseif align == "AlignCenter" then
|
113
|
-
return "center"
|
114
|
-
else
|
115
|
-
return ""
|
116
|
-
end
|
106
|
+
return ({ AlignRight = "right", AlignCenter = "center" })[align] or ""
|
117
107
|
end
|
118
108
|
|
119
109
|
function Blocksep()
|
120
110
|
return "\n\n"
|
121
111
|
end
|
122
112
|
|
123
|
-
function Doc(body,
|
124
|
-
|
125
|
-
|
126
|
-
table.insert(buffer, s)
|
127
|
-
end
|
128
|
-
add(body)
|
129
|
-
if (#footnotes > 0) then
|
130
|
-
add("\n" .. table.concat(footnotes, "\n"))
|
113
|
+
function Doc(body, meta, variables)
|
114
|
+
if #footnotes == 0 then
|
115
|
+
return body
|
131
116
|
end
|
132
|
-
return table.concat(
|
117
|
+
return table.concat({ body, "", table.concat(footnotes, "\n") }, "\n")
|
133
118
|
end
|
134
119
|
|
135
120
|
function Str(s)
|
@@ -145,11 +130,7 @@ function LineBreak()
|
|
145
130
|
end
|
146
131
|
|
147
132
|
function SoftBreak(s)
|
148
|
-
|
149
|
-
return " "
|
150
|
-
else
|
151
|
-
return "<P2RBR/>"
|
152
|
-
end
|
133
|
+
return metadata.softbreak and " " or "<P2RBR/>"
|
153
134
|
end
|
154
135
|
|
155
136
|
function Plain(s)
|
@@ -188,25 +169,27 @@ local function attr_scale(attr, key) -- a helper for CaptionedImage
|
|
188
169
|
return tonumber(scale) / 100
|
189
170
|
end
|
190
171
|
|
191
|
-
function
|
192
|
-
|
172
|
+
local function class_header(classes)
|
173
|
+
-- Re:VIEW's behavior
|
174
|
+
for _, cls in pairs({ "column", "nonum", "nodisp", "notoc" }) do
|
175
|
+
if classes[cls] then
|
176
|
+
return string.format("[%s]", cls)
|
177
|
+
end
|
178
|
+
end
|
193
179
|
|
194
|
-
|
180
|
+
-- Pandoc's behavior
|
181
|
+
if classes.unnumbered then
|
182
|
+
return classes.unlisted and "[notoc]" or "[nonum]"
|
183
|
+
end
|
184
|
+
|
185
|
+
-- None
|
186
|
+
return ""
|
187
|
+
end
|
195
188
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
classes["nodisp"] and "[nodisp]" or (
|
201
|
-
classes["notoc"] and "[notoc]" or (
|
202
|
-
-- Pandoc's behavior
|
203
|
-
classes["unnumbered"] and (
|
204
|
-
classes["unlisted"] and "[notoc]" or "[nonum]") or (
|
205
|
-
-- None
|
206
|
-
"")))))
|
207
|
-
)
|
208
|
-
|
209
|
-
if ((config.use_header_id == "true") and attr.id ~= "" and attr.id ~= s) then
|
189
|
+
function Header(level, s, attr)
|
190
|
+
local headmark = string.rep("=", level) .. class_header(attr_classes(attr))
|
191
|
+
|
192
|
+
if (config.use_header_id == "true") and attr.id ~= "" and attr.id ~= s then
|
210
193
|
headmark = headmark .. "{" .. attr.id .. "}"
|
211
194
|
end
|
212
195
|
|
@@ -214,17 +197,13 @@ function Header(level, s, attr)
|
|
214
197
|
end
|
215
198
|
|
216
199
|
function HorizontalRule()
|
217
|
-
|
218
|
-
return "//hr"
|
219
|
-
else
|
220
|
-
return ""
|
221
|
-
end
|
200
|
+
return config.use_hr == "true" and "//hr" or ""
|
222
201
|
end
|
223
202
|
|
224
203
|
local function lint_list(s)
|
225
|
-
return s:gsub("\n+(//beginchild)\n+",
|
226
|
-
|
227
|
-
|
204
|
+
return s:gsub("\n+(//beginchild)\n+", "\n\n%1\n\n")
|
205
|
+
:gsub("\n+(//endchild)\n+", "\n\n%1\n\n")
|
206
|
+
:gsub("\n+(//endchild)\n*$", "\n\n%1")
|
228
207
|
end
|
229
208
|
|
230
209
|
function BulletList(items)
|
@@ -270,39 +249,33 @@ end
|
|
270
249
|
function CodeBlock(s, attr)
|
271
250
|
local classes = attr_classes(attr)
|
272
251
|
|
273
|
-
local command =
|
274
|
-
for k,v in pairs({cmd = "cmd", source = "source", quote = "source"}) do
|
252
|
+
local command = "list" -- default
|
253
|
+
for k, v in pairs({ cmd = "cmd", source = "source", quote = "source" }) do
|
275
254
|
if classes[k] then
|
276
255
|
command = v
|
277
256
|
break
|
278
257
|
end
|
279
258
|
end
|
280
|
-
command = command or "list"
|
281
259
|
|
282
260
|
local is_list = command == "list"
|
283
261
|
|
284
|
-
|
285
|
-
local num = (is_list == false) and "" or (
|
286
|
-
(classes["numberLines"] or classes["number-lines"] or classes["num"]) and
|
287
|
-
"num" or ""
|
288
|
-
)
|
262
|
+
local num = (is_list and (classes["numberLines"] or classes["number-lines"] or classes["num"])) and "num" or ""
|
289
263
|
|
290
264
|
local firstlinenum = ""
|
291
265
|
if is_list and (num == "num") then
|
292
|
-
for _, key in ipairs({"startFrom", "start-from", "firstlinenum"}) do
|
293
|
-
|
294
|
-
|
295
|
-
firstlinenum = "//firstlinenum[" .. firstlinenum .. "]\n"
|
266
|
+
for _, key in ipairs({ "startFrom", "start-from", "firstlinenum" }) do
|
267
|
+
if attr[key] then
|
268
|
+
firstlinenum = "//firstlinenum[" .. attr[key] .. "]\n"
|
296
269
|
break
|
297
270
|
end
|
298
271
|
end
|
299
272
|
end
|
300
273
|
|
301
274
|
local lang = ""
|
302
|
-
local not_lang = {numberLines = true, num = true, em = true, source = true}
|
275
|
+
local not_lang = { numberLines = true, num = true, em = true, source = true }
|
303
276
|
not_lang["number-lines"] = true
|
304
277
|
if is_list or (command == "source") then
|
305
|
-
for key,_ in pairs(classes) do
|
278
|
+
for key, _ in pairs(classes) do
|
306
279
|
if not_lang[key] ~= true then
|
307
280
|
lang = "[" .. key .. "]"
|
308
281
|
break
|
@@ -313,9 +286,9 @@ function CodeBlock(s, attr)
|
|
313
286
|
local caption = (command == "cmd") and "" or attr_val(attr, "caption")
|
314
287
|
local identifier = ""
|
315
288
|
local em = is_list and classes["em"] and "em" or ""
|
316
|
-
if
|
289
|
+
if caption ~= "" then
|
317
290
|
if is_list and (em == "") then
|
318
|
-
if
|
291
|
+
if attr.id ~= "" then
|
319
292
|
identifier = "[" .. attr.id .. "]"
|
320
293
|
else
|
321
294
|
list_num = list_num + 1
|
@@ -332,11 +305,7 @@ function CodeBlock(s, attr)
|
|
332
305
|
end
|
333
306
|
end
|
334
307
|
|
335
|
-
return (
|
336
|
-
firstlinenum ..
|
337
|
-
"//" .. em .. command .. num .. identifier .. caption .. lang ..
|
338
|
-
"{\n" .. s .. "\n//}"
|
339
|
-
)
|
308
|
+
return (firstlinenum .. "//" .. em .. command .. num .. identifier .. caption .. lang .. "{\n" .. s .. "\n//}")
|
340
309
|
end
|
341
310
|
|
342
311
|
function LineBlock(s)
|
@@ -345,7 +314,7 @@ function LineBlock(s)
|
|
345
314
|
end
|
346
315
|
|
347
316
|
function Link(s, src, tit)
|
348
|
-
if
|
317
|
+
if src == s then
|
349
318
|
return format_inline("href", src)
|
350
319
|
else
|
351
320
|
return format_inline("href", src .. "," .. s)
|
@@ -412,7 +381,7 @@ function Table(caption, aligns, widths, headers, rows)
|
|
412
381
|
add("--------------")
|
413
382
|
for _, row in pairs(rows) do
|
414
383
|
tmp = {}
|
415
|
-
|
384
|
+
for i, c in pairs(row) do
|
416
385
|
local align = html_align(aligns[i])
|
417
386
|
if (config.use_table_align == "true") and (align ~= "") then
|
418
387
|
c = format_inline("dtp", "table align=" .. align) .. c
|
@@ -426,13 +395,6 @@ function Table(caption, aligns, widths, headers, rows)
|
|
426
395
|
return table.concat(buffer, "\n")
|
427
396
|
end
|
428
397
|
|
429
|
-
function Image(s, src, tit)
|
430
|
-
-- Re:VIEW @<icon> ignores caption and title
|
431
|
-
local id = string.gsub(src, "%.%w+$", "")
|
432
|
-
id = string.gsub(id, "^images/", "")
|
433
|
-
return format_inline("icon", id)
|
434
|
-
end
|
435
|
-
|
436
398
|
function CaptionedImage(s, src, tit, attr)
|
437
399
|
local path = "[" .. s:gsub("%.%w+$", ""):gsub("^images/", "") .. "]"
|
438
400
|
|
@@ -442,7 +404,7 @@ function CaptionedImage(s, src, tit, attr)
|
|
442
404
|
if scale == "" then
|
443
405
|
local width = attr_scale(attr, "width")
|
444
406
|
local height = attr_scale(attr, "height")
|
445
|
-
if
|
407
|
+
if width ~= "" then
|
446
408
|
if (height ~= "") and (width ~= height) then
|
447
409
|
log("WARNING: Image width and height must be same. Using width.\n")
|
448
410
|
end
|
@@ -455,26 +417,15 @@ function CaptionedImage(s, src, tit, attr)
|
|
455
417
|
scale = "[scale=" .. scale .. "]"
|
456
418
|
end
|
457
419
|
|
458
|
-
local command = "//image"
|
459
|
-
local caption = ""
|
460
|
-
if (tit == "") then
|
461
|
-
command = "//indepimage"
|
462
|
-
else
|
463
|
-
caption = "[" .. tit .. "]"
|
464
|
-
end
|
420
|
+
local command = tit == "" and "//indepimage" or "//image"
|
421
|
+
local caption = tit == "" and "" or ("[" .. tit .. "]")
|
465
422
|
|
466
|
-
return (
|
467
|
-
command .. path .. caption .. scale .. "{" .. comment .. "\n//}"
|
468
|
-
)
|
423
|
+
return (command .. path .. caption .. scale .. "{" .. comment .. "\n//}")
|
469
424
|
end
|
470
425
|
|
471
426
|
function Image(s, src, tit, attr)
|
472
427
|
-- Re:VIEW @<icon> ignores caption and title
|
473
|
-
|
474
|
-
return CaptionedImage(src, s, tit, attr)
|
475
|
-
end
|
476
|
-
local id = string.gsub(src, "%.%w+$", "")
|
477
|
-
id = string.gsub(id, "^images/", "")
|
428
|
+
local id = src:gsub("%.%w+$", ""):gsub("^images/", "")
|
478
429
|
return format_inline("icon", id)
|
479
430
|
end
|
480
431
|
|
@@ -490,12 +441,7 @@ function Cite(s, cs)
|
|
490
441
|
end
|
491
442
|
|
492
443
|
function Quoted(quotetype, s)
|
493
|
-
|
494
|
-
return SingleQuoted(s)
|
495
|
-
end
|
496
|
-
if (quotetype == "DoubleQuote") then
|
497
|
-
return DoubleQuoted(s)
|
498
|
-
end
|
444
|
+
return _G[quotetype](s)
|
499
445
|
end
|
500
446
|
|
501
447
|
function SingleQuoted(s)
|
@@ -511,13 +457,9 @@ function SmallCaps(s)
|
|
511
457
|
end
|
512
458
|
|
513
459
|
function Div(s, attr)
|
514
|
-
local blankline =
|
515
|
-
if blankline
|
516
|
-
|
517
|
-
for _ = 1, tonumber(blankline) do
|
518
|
-
table.insert(buffer, "//blankline")
|
519
|
-
end
|
520
|
-
return table.concat(buffer, "\n")
|
460
|
+
local blankline = tonumber(attr.blankline)
|
461
|
+
if blankline then
|
462
|
+
return string.rep("//blankline\n", blankline):gsub("\n$", "")
|
521
463
|
end
|
522
464
|
|
523
465
|
local classes = attr_classes(attr)
|
@@ -531,15 +473,11 @@ function Div(s, attr)
|
|
531
473
|
end
|
532
474
|
|
533
475
|
if classes["review-internal"] then
|
534
|
-
s, _ = s:gsub(
|
535
|
-
"%]{<P2RREMOVEBELOW/>\n", "]{"
|
536
|
-
):gsub(
|
537
|
-
"\n<P2RREMOVEABOVE/>//}", "//}"
|
538
|
-
)
|
476
|
+
s, _ = s:gsub("%]{<P2RREMOVEBELOW/>\n", "]{"):gsub("\n<P2RREMOVEABOVE/>//}", "//}")
|
539
477
|
return s
|
540
478
|
end
|
541
479
|
|
542
|
-
for cls,_ in pairs(classes) do
|
480
|
+
for cls, _ in pairs(classes) do
|
543
481
|
s = "//" .. cls .. "{\n" .. s .. "\n//}"
|
544
482
|
end
|
545
483
|
return s
|
@@ -548,7 +486,7 @@ end
|
|
548
486
|
function Span(s, attr)
|
549
487
|
-- ruby and kw with a supplement
|
550
488
|
local a = ""
|
551
|
-
for _, cmd in ipairs({"ruby", "kw"}) do
|
489
|
+
for _, cmd in ipairs({ "ruby", "kw" }) do
|
552
490
|
a = attr_val(attr, cmd)
|
553
491
|
if a ~= "" then
|
554
492
|
s = format_inline(cmd, s .. "," .. a)
|
@@ -566,15 +504,15 @@ function Span(s, attr)
|
|
566
504
|
end
|
567
505
|
|
568
506
|
function RawInline(format, text)
|
569
|
-
if
|
507
|
+
if format == "review" then
|
570
508
|
return text
|
571
509
|
end
|
572
510
|
|
573
|
-
if
|
511
|
+
if metadata.hideraw then
|
574
512
|
return ""
|
575
513
|
end
|
576
514
|
|
577
|
-
if
|
515
|
+
if format == "tex" then
|
578
516
|
return format_inline("embed", "|latex|" .. text)
|
579
517
|
else
|
580
518
|
return format_inline("embed", "|" .. format .. "|" .. text)
|
@@ -582,15 +520,15 @@ function RawInline(format, text)
|
|
582
520
|
end
|
583
521
|
|
584
522
|
function RawBlock(format, text)
|
585
|
-
if
|
523
|
+
if format == "review" then
|
586
524
|
return text
|
587
525
|
end
|
588
526
|
|
589
|
-
if
|
527
|
+
if metadata.hideraw then
|
590
528
|
return ""
|
591
529
|
end
|
592
530
|
|
593
|
-
if
|
531
|
+
if format == "tex" then
|
594
532
|
return "//embed[latex]{\n" .. text .. "\n//}"
|
595
533
|
else
|
596
534
|
return "//embed[" .. format .. "]{\n" .. text .. "\n//}"
|
@@ -598,16 +536,16 @@ function RawBlock(format, text)
|
|
598
536
|
end
|
599
537
|
|
600
538
|
local function configure()
|
601
|
-
try_catch
|
539
|
+
try_catch({
|
602
540
|
try = function()
|
603
541
|
metadata = PANDOC_DOCUMENT.meta
|
604
542
|
end,
|
605
543
|
catch = function(error)
|
606
544
|
log("Due to your pandoc version is too old, config.yml loader is disabled.\n")
|
607
|
-
end
|
608
|
-
}
|
545
|
+
end,
|
546
|
+
})
|
609
547
|
|
610
|
-
if
|
548
|
+
if metadata then
|
611
549
|
-- Load config from YAML
|
612
550
|
for k, _ in pairs(config) do
|
613
551
|
if metadata[k] ~= nil then
|
@@ -617,23 +555,225 @@ local function configure()
|
|
617
555
|
end
|
618
556
|
end
|
619
557
|
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
558
|
+
setmetatable(_G, {
|
559
|
+
__index = function(_, key)
|
560
|
+
log(string.format("WARNING: Undefined function '%s'\n", key))
|
561
|
+
return function()
|
562
|
+
return ""
|
563
|
+
end
|
564
|
+
end,
|
565
|
+
})
|
566
|
+
|
567
|
+
if PANDOC_VERSION < "3.0.0" then
|
629
568
|
configure()
|
569
|
+
return
|
630
570
|
end
|
631
571
|
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
572
|
+
Blocks = setmetatable({}, {
|
573
|
+
__index = function(_, key)
|
574
|
+
error("NotImplementedError: Blocks.%" .. tostring(key))
|
575
|
+
end,
|
576
|
+
})
|
577
|
+
|
578
|
+
Inlines = setmetatable({}, {
|
579
|
+
__index = function(_, key)
|
580
|
+
error("NotImplementedError: Inlines.%" .. tostring(key))
|
581
|
+
end,
|
582
|
+
})
|
583
|
+
|
584
|
+
local tidy_attr = function(el)
|
585
|
+
local ret = {}
|
586
|
+
for k, v in pairs(el.attr.attributes) do
|
587
|
+
ret[k] = v
|
588
|
+
end
|
589
|
+
ret.id = el.identifier or ""
|
590
|
+
ret.class = el.classes and table.concat(el.classes, " ")
|
591
|
+
return ret
|
592
|
+
end
|
593
|
+
|
594
|
+
local concat = pandoc.layout.concat
|
595
|
+
|
596
|
+
local function render(...)
|
597
|
+
local x = pandoc.layout.render(...):gsub("\n+$", "")
|
598
|
+
return x
|
599
|
+
end
|
600
|
+
|
601
|
+
local function inlines(els)
|
602
|
+
local buff = {}
|
603
|
+
for _, el in ipairs(els) do
|
604
|
+
table.insert(buff, Inlines[el.tag](el))
|
605
|
+
end
|
606
|
+
return concat(buff)
|
607
|
+
end
|
608
|
+
|
609
|
+
local function blocks(els, sep)
|
610
|
+
local buff = {}
|
611
|
+
for _, el in ipairs(els) do
|
612
|
+
table.insert(buff, Blocks[el.tag](el))
|
613
|
+
end
|
614
|
+
return concat(buff, sep)
|
615
|
+
end
|
616
|
+
|
617
|
+
Inlines.Str = function(el)
|
618
|
+
return Str(el.text)
|
619
|
+
end
|
620
|
+
|
621
|
+
for _, v in pairs({ "Space", "LineBreak", "SoftBreak" }) do
|
622
|
+
Inlines[v] = _G[v]
|
623
|
+
end
|
624
|
+
|
625
|
+
Blocks.HorizontalRule = function(_)
|
626
|
+
return HorizontalRule() .. "\n"
|
627
|
+
end
|
628
|
+
|
629
|
+
Blocks.Plain = function(el)
|
630
|
+
return inlines(el.content) .. "\n"
|
631
|
+
end
|
632
|
+
|
633
|
+
Blocks.Para = function(el)
|
634
|
+
if #el.content == 1 and el.content[1].tag == "Image" then
|
635
|
+
local img = el.content[1]
|
636
|
+
return CaptionedImage(img.src, img.title, render(inlines(img.caption)), tidy_attr(img)) .. "\n"
|
637
637
|
end
|
638
|
+
return inlines(el.content) .. "\n"
|
639
|
+
end
|
640
|
+
|
641
|
+
Blocks.Header = function(el)
|
642
|
+
return Header(el.level, render(inlines(el.content)), tidy_attr(el)) .. "\n"
|
643
|
+
end
|
644
|
+
|
645
|
+
local function render_blocks(blks, sep)
|
646
|
+
local ret = {}
|
647
|
+
for _, v in pairs(blks) do
|
648
|
+
table.insert(ret, render(blocks(v, sep or "\n")))
|
649
|
+
end
|
650
|
+
return ret
|
651
|
+
end
|
652
|
+
|
653
|
+
Blocks.BulletList = function(el)
|
654
|
+
return BulletList(render_blocks(el.content)) .. "\n"
|
655
|
+
end
|
656
|
+
|
657
|
+
Blocks.OrderedList = function(el)
|
658
|
+
return OrderedList(render_blocks(el.content), el.start) .. "\n"
|
659
|
+
end
|
660
|
+
|
661
|
+
Blocks.DefinitionList = function(el)
|
662
|
+
local items = {}
|
663
|
+
for _, v in pairs(el.content) do
|
664
|
+
local term = render(inlines(v[1]))
|
665
|
+
table.insert(items, { [term] = render_blocks(v[2]) })
|
666
|
+
end
|
667
|
+
return DefinitionList(items) .. "\n"
|
668
|
+
end
|
669
|
+
|
670
|
+
Blocks.BlockQuote = function(el)
|
671
|
+
return BlockQuote(render(blocks(el.content, "\n"))) .. "\n"
|
672
|
+
end
|
673
|
+
|
674
|
+
Blocks.CodeBlock = function(el)
|
675
|
+
return CodeBlock(el.text, tidy_attr(el)) .. "\n"
|
676
|
+
end
|
677
|
+
|
678
|
+
Blocks.LineBlock = function(el)
|
679
|
+
local lines = {}
|
680
|
+
for _, v in pairs(el.content) do
|
681
|
+
table.insert(lines, render(inlines(v)))
|
682
|
+
end
|
683
|
+
return LineBlock(lines) .. "\n"
|
684
|
+
end
|
685
|
+
|
686
|
+
Inlines.Link = function(el)
|
687
|
+
return Link(render(inlines(el.content)), el.target, el.title)
|
688
|
+
end
|
689
|
+
|
690
|
+
Inlines.Code = function(el)
|
691
|
+
return Code(el.text, tidy_attr(el))
|
692
|
+
end
|
693
|
+
|
694
|
+
for _, k in pairs({ "Emph", "Strong", "Strikeout", "Underline", "Subscript", "Superscript", "SmallCaps" }) do
|
695
|
+
Inlines[k] = function(el)
|
696
|
+
return _G[k](render(inlines(el.content)))
|
697
|
+
end
|
698
|
+
end
|
638
699
|
|
639
|
-
|
700
|
+
Inlines.Math = function(el)
|
701
|
+
return _G[el.mathtype](el.text)
|
702
|
+
end
|
703
|
+
|
704
|
+
Blocks.Table = function(el)
|
705
|
+
local tbl = pandoc.utils.to_simple_table(el)
|
706
|
+
local headers = render_blocks(tbl.headers)
|
707
|
+
local rows = {}
|
708
|
+
for _, row in pairs(tbl.rows) do
|
709
|
+
table.insert(rows, render_blocks(row, ""))
|
710
|
+
end
|
711
|
+
return Table(render(inlines(tbl.caption)), tbl.aligns, tbl.widths, headers, rows) .. "\n"
|
712
|
+
end
|
713
|
+
|
714
|
+
Inlines.Image = function(el)
|
715
|
+
return Image(render(inlines(el.caption)), el.src, el.title, tidy_attr(el))
|
716
|
+
end
|
717
|
+
|
718
|
+
Inlines.Note = function(el)
|
719
|
+
return Note(render(blocks(el.content, "\n")))
|
720
|
+
end
|
721
|
+
|
722
|
+
Inlines.Cite = function(el)
|
723
|
+
return Cite(render(inlines(el.content)))
|
724
|
+
end
|
725
|
+
|
726
|
+
Inlines.Quoted = function(el)
|
727
|
+
return Quoted(el.quotetype, render(inlines(el.content)))
|
728
|
+
end
|
729
|
+
|
730
|
+
Blocks.Div = function(el)
|
731
|
+
return Div(render(blocks(el.content, "\n")), tidy_attr(el)) .. "\n"
|
732
|
+
end
|
733
|
+
|
734
|
+
Inlines.Span = function(el)
|
735
|
+
return Span(render(inlines(el.content)), tidy_attr(el))
|
736
|
+
end
|
737
|
+
|
738
|
+
Inlines.RawInline = function(el)
|
739
|
+
return RawInline(el.format, el.text)
|
740
|
+
end
|
741
|
+
|
742
|
+
Blocks.RawBlock = function(el)
|
743
|
+
return RawBlock(el.format, el.text) .. "\n"
|
744
|
+
end
|
745
|
+
|
746
|
+
Blocks.Figure = function(el)
|
747
|
+
if #el.content > 1 or #el.content[1].content > 1 or el.content[1].content[1].tag ~= "Image" then
|
748
|
+
error("NotImplementedError: current implementation assumes Figure contains only a single image.")
|
749
|
+
-- because Pandoc 3.1.4 does not support Pandoc's markdown cotaining Figure with multiple images...
|
750
|
+
end
|
751
|
+
|
752
|
+
local img = el.content[1].content[1]
|
753
|
+
|
754
|
+
return CaptionedImage(img.src, img.title, render(inlines(img.caption)), tidy_attr(img)) .. "\n"
|
755
|
+
end
|
756
|
+
|
757
|
+
function Writer(doc, opts)
|
758
|
+
PANDOC_DOCUMENT = doc
|
759
|
+
PANDOC_WRITER_OPTIONS = opts
|
760
|
+
configure()
|
761
|
+
|
762
|
+
if metadata.classicwriter then
|
763
|
+
if pandoc.write_classic then
|
764
|
+
return pandoc.write_classic(
|
765
|
+
doc:walk({
|
766
|
+
Figure = function(el)
|
767
|
+
return pandoc.RawBlock("review", render(Blocks.Figure(el)))
|
768
|
+
end,
|
769
|
+
}),
|
770
|
+
opts
|
771
|
+
)
|
772
|
+
end
|
773
|
+
log("WARNING: pandoc.write_classic is defunct. Using modern writer")
|
774
|
+
end
|
775
|
+
|
776
|
+
-- body should keep trailing new lines but remove one if there are footnotes for the backward-compatibility
|
777
|
+
local body = pandoc.layout.render(pandoc.layout.concat({ blocks(doc.blocks, "\n") }))
|
778
|
+
return Doc(#footnotes == 0 and body or body:gsub("\n$", ""))
|
779
|
+
end
|