-
Notifications
You must be signed in to change notification settings - Fork 0
/
image-ms.lua
405 lines (383 loc) · 12.2 KB
/
image-ms.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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
--
--------------------------------------------------------------------------------
-- File: image-ms.lua
--
-- Usage: pandoc --lua-filter=image-ms.lua
--
-- Description: - make graphic a float in Pandoc -ms export
-- - make float if {float=true} or {float=1} in
-- parameters
-- - correct unlinkable labels in BibTeX ("/" -> "+")
-- - options to render small caps
-- - handle font within font
-- - wrap BlockQuote in .STARTQUOTE/.ENDQUOTE
-- - make links breakable
-- - scale references section down
--
-- Restrictions: - only treats height if width is given
-- - no notion of "%"
--
-- Author: Bernhard Fisseni (teoric), <[email protected]>
-- Version: 0.5
-- Created: 2018-03-30
-- Last Changed: 2024-05-16, 09:36:54 (CEST)
--------------------------------------------------------------------------------
--
-- local inspect = require('inspect')
local text = require 'text'
local List = require 'pandoc.List'
local utils = require 'pandoc.utils'
-- pattern for keep macro:
local keep_pattern = ".ANYPIC"
-- characters to protect from Pandoc smartness
local protected = {"’", "…"} -- not used currently
-- references section title
local refsec = {
References = true,
Quellen = true,
Literatur = true,
Bibliographie = true,
Bibliography = true,
Bibliografia = true,
["Bibliografía"] = true,
}
local zero_space = ""
local utilPath = string.match(PANDOC_SCRIPT_FILE, '.*[/\\]')
if PANDOC_VERSION >= {2,12} then
local path = require 'pandoc.path'
utilPath = path.directory(PANDOC_SCRIPT_FILE) .. path.separator
end
local loc_utils = dofile ((utilPath or '') .. 'utils.lua')
function convert_measurements(size)
-- convert and guess HTML/LaTeX units to [gt]roff units
if size ~= nil then
size = string.gsub(size, "[;:,]$", "")
size = string.gsub(size, "pt$", "p") -- pt called p
size = string.gsub(size, "px$", "p") -- assuming 72 dpi, 1px is 1p
size = string.gsub(size, "em$", "m") -- em called m
size = string.gsub(size, "ex$", "n") -- ex called n
if (string.match(size, "^[0-9.]+cm") or
string.match(size, "^[0-9.]+p") or
string.match(size, "^[0-9.]+P") or
string.match(size, "^[0-9.]+in")) then
return size
end
end
return nil
end
-- http://lua-users.org/wiki/CopyTable
function table.clone(org)
return {table.unpack(org)}
end
--[[
function deepcopy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[deepcopy(orig_key)] = deepcopy(orig_value)
end
setmetatable(copy, deepcopy(getmetatable(orig)))
else -- number, string, boolean, etc
copy = orig
end
return copy
end
--]]
-- end
local use_small_caps = false
local walker = {
Strong=pandoc.walk_inline,
Emph=pandoc.walk_inline,
Header=pandoc.walk_block,
}
function embolden_emph(elem)
if FORMAT == "ms" then
return walker[elem.t](
elem,
{
Emph = function (el)
local ret = List:new({
pandoc.RawInline("ms", "\\f[BI]"),
})
ret:extend(el.c)
ret:extend({
pandoc.RawInline("ms", "\\f[R]\\f[B]"),
})
return pandoc.Span(ret)
end
})
end
end
function emphasize_bold(elem)
if FORMAT == "ms" then
return walker[elem.t](
elem,
{
Strong = function (el)
local ret = List:new({
pandoc.RawInline("ms", "\\f[BI]")
})
ret:extend(el.c)
ret:extend({
pandoc.RawInline("ms", "\\f[R]\\f[I]"),
})
return pandoc.Span(ret)
end
})
end
end
return {
{
Meta = function(meta)
if meta["use-small-caps"] == true then
use_small_caps = "small-caps"
elseif meta["use-small-caps"] == false then
use_small_caps = "none"
else
use_small_caps = (meta["use-small-caps"] ~= nil) and text.lower(utils.stringify(meta["use-small-caps"]))
end
end,
Link = function (cit)
-- hangs if in last filter
function space(el)
-- allow line breaking of links
if el.t == "Str" and el.content then
el.content = string.gsub(el.c, "/", "/" .. zero_space)
el.content = string.gsub(el.c, "%.", "." .. zero_space)
el.content = string.gsub(el.c, "_", "_" .. zero_space)
end
end
cit.content:map(space)
return cit
end,
},
{
-- -- broken / unused now (2.18ff?)
-- SimpleTable = function (tab)
-- -- wrap tables in macros and a caption macro
-- -- RESULT:
-- -- .TABLESTART
-- -- .\" (table)
-- -- .TABLELABLE \" if caption
-- -- .\" caption if given
-- -- .TABLEEND
-- if FORMAT == "ms" then
-- cap = pandoc.Plain(table.clone(tab.caption))
-- -- cap = utils.stringify(tab.caption) or ""
-- tab.caption = {} -- delete old caption
-- local ret = List:new{
-- pandoc.RawBlock("ms", ".TABLESTART\n"),
-- tab,
-- }
-- if cap ~= nil then
-- ret:extend({pandoc.RawBlock("ms", string.format('.TABLELABLE')),
-- cap})
-- end
-- ret:extend({pandoc.RawBlock("ms", string.format('.TABLEEND'))})
-- return ret
-- end
-- end,
Cite = function (cit)
-- sanitize cite id
-- this is not used, anyway!?
if FORMAT == "ms" then
for k, v in pairs(cit.citations) do
v.id = string.gsub(v.id, '/', "+")
end
return cit
end
end,
Div = function(div)
-- sanitize div id
-- this is not used, anyway!?
if FORMAT == "ms" then
if string.find(div.identifier, "^ref-.*/") then
div.identifier = string.gsub(div.identifier, '/', '+')
end
end
end,
DefinitionList = function(div)
-- make definitions Bold
if FORMAT == "ms" then
for i = 1, #(div.c) do
local ret = pandoc.List:new{}
for j = 1, #(div.c[i][1]) do
ret:extend({pandoc.Strong(div.c[i][1][j])})
end
div.c[i][1] = ret
end
return div
end
end,
-- broken now (2.18ff?)
Link = function (cit)
-- sanitize Link ID
-- protect against https://github.com/jgm/pandoc/issues/4515
if FORMAT == "ms" then
if string.sub(cit.target, 1, 1) == "#" then
cit.target = string.gsub(cit.target, '/', "+")
end
return cit
end
end,
Image = function (im)
-- cf. https://github.com/jgm/pandoc/issues/4475
-- Image inclusion is by default disabled for ms in pandoc
-- this uses the private macro .ANYPIC to include PDF graphics
--
-- uses image property `float`; if set, uses ANYPIC F
--
-- If there is no graphics file that can be included (PDF),
-- it is generated by ImageMagicks convert – this may not be the
-- optimal way to deal with this.
--
-- Determines size using pdfinfo not strictly necessary, but a
-- starting point for changing size in ms.
--
if FORMAT == "ms" then
pat = keep_pattern
if im.attributes.float and
(text.lower(im.attributes.float) == "true" or
im.attributes.float == "1") then
pat = pat .. " F"
else
pat = pat .. " S"
end
pat = pat .. string.format(' "%s"', utils.stringify(im.caption))
local im_src_old = im.src
if not loc_utils.endswith(text.lower(im.src), ".pdf") then
im.src = string.gsub(im.src, "%.[^.]+$", ".pdf")
end
if not loc_utils.file_exists(im.src) and loc_utils.file_exists(im_src_old) then
-- if this fails, check policies in /etc/ImageMagick-[67]/policy.xml
-- whether they forbid conversion of EPS, PDF etc.
pandoc.pipe("convert", {im_src_old, im.src}, "")
end
pat = pat .. string.format(' "%s"', im.src)
if im.attributes ~= nil then
if im.attributes.width ~= nil then
im.attributes.width = convert_measurements(im.attributes.width)
end
if im.attributes.height ~= nil then
im.attributes.height = convert_measurements(im.attributes.height)
end
size = pandoc.pipe('pdfinfo', {im.src}, "")
local w
local h
_, _, w, h = string.find(size, "Page size:%s+([%d.]+)%s+x%s+([%d.]+)")
local height = im.attributes.height or h and (h .. "p")
local width = im.attributes.width or w and (w .. "p") or nil
if width ~= nil then
pat = pat .. string.format(' "%s"', width)
-- height only matters if width was given
if height ~= nil then
pat = pat .. string.format(' "%s"', height)
end
end
end
return pandoc.RawInline("ms", pat)
end
end,
BlockQuote = function(el)
return {
pandoc.RawBlock("ms", ".STARTQUOTE"),
el,
pandoc.RawBlock("ms", ".ENDQUOTE"),
}
end,
Header = embolden_emph,
Strong = embolden_emph,
Emph = emphasize_bold,
SmallCaps = function (elem)
-- use different macros for small caps – potentially better than
-- size escapes
if FORMAT == "ms" then
if use_small_caps == "underline" then
return List:new{
pandoc.RawInline("ms",
string.format('\\c\n.UL "%s"\\c\n', utils.stringify(elem.c)))
}
elseif use_small_caps == "space-out" then
return List:new{
pandoc.RawInline("ms",
string.format('\\c\n.SPERR "%s"\n', utils.stringify(elem.c)))
}
elseif use_small_caps == "small-caps" then
local ret = List:new{
pandoc.RawInline("ms", '\n.smallcaps\n')
}
for i, el in pairs(elem.c) do
ret:extend({el})
end
ret:extend({pandoc.RawInline("ms", '\\c\n./smallcaps\n')})
return ret
elseif use_small_caps == "all-caps" then
return pandoc.walk_inline(
pandoc.Span(elem.c), {
Str = function(el)
return pandoc.Str(text.upper(el.text))
end
})
elseif use_small_caps == "strong" then
return pandoc.Strong(elem.c)
elseif use_small_caps == "emph" then
return pandoc.Emph(elem.c)
elseif use_small_caps == "none" then
return pandoc.Span(elem.c)
elseif use_small_caps == "pandoc-default" then
end
end
end,
Str = function(str)
-- Protect letters in `protected` against smartness
-- Protect U+2019 against
-- https://github.com/jgm/pandoc/issues/4550
if FORMAT == "ms" then
local s = str.text
local substrings = List:new()
local i = 1
while i <= text.len(s) do
local il
for j, p in ipairs(protected) do
il = text.len(p)
skip = 1
if text.sub(s, i, i + il - 1) == p then
substrings:extend({{i, il}})
skip = il
break
end
end
i = i + skip
end
local old_start = 1
local ret = List:new()
substrings:map(function (p)
local start = p[1]
local il = p[2]
if start > old_start then
ret:extend({pandoc.Str(text.sub(s, old_start, start - 1))})
end
ret:extend({pandoc.RawInline("ms", text.sub(s, start, start + il - 1))})
old_start = start + il
end)
if old_start <= text.len(s) then
ret:extend({pandoc.Str(text.sub(s, old_start, text.len(s)))})
end
return ret
end
end,
},
{
Header = function (h)
if FORMAT == "ms" then
if refsec[utils.stringify(h)] then
return {pandoc.RawBlock("ms", ".HANG"), pandoc.RawBlock("ms", ".REF_SIZE"), h}
else
return {pandoc.RawBlock("ms", ".RESTORE_SIZE"), pandoc.RawBlock("ms", ".UNHANG"), h}
end
end
end,
}
}