docrev 0.10.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +1 -1
- package/CHANGELOG.md +173 -164
- package/PLAN-tables-and-postprocess.md +850 -850
- package/README.md +431 -431
- package/bin/rev.js +11 -11
- package/bin/rev.ts +145 -145
- package/completions/rev.bash +127 -127
- package/completions/rev.ps1 +210 -210
- package/completions/rev.zsh +207 -207
- package/dist/lib/anchor-match.d.ts +1 -1
- package/dist/lib/anchor-match.d.ts.map +1 -1
- package/dist/lib/anchor-match.js +17 -47
- package/dist/lib/anchor-match.js.map +1 -1
- package/dist/lib/build.js +4 -4
- package/dist/lib/commands/context.d.ts +1 -1
- package/dist/lib/commands/context.d.ts.map +1 -1
- package/dist/lib/commands/context.js +1 -1
- package/dist/lib/commands/context.js.map +1 -1
- package/dist/lib/commands/sections.js +7 -7
- package/dist/lib/commands/sections.js.map +1 -1
- package/dist/lib/commands/sync.d.ts.map +1 -1
- package/dist/lib/commands/sync.js +15 -14
- package/dist/lib/commands/sync.js.map +1 -1
- package/dist/lib/commands/utilities.js +164 -164
- package/dist/lib/commands/verify-anchors.js +6 -6
- package/dist/lib/commands/verify-anchors.js.map +1 -1
- package/dist/lib/commands/word-tools.js +8 -8
- package/dist/lib/grammar.js +3 -3
- package/dist/lib/macro-filter.lua +201 -201
- package/dist/lib/pdf-comments.js +44 -44
- package/dist/lib/plugins.js +57 -57
- package/dist/lib/pptx-color-filter.lua +37 -37
- package/dist/lib/pptx-themes.js +115 -115
- package/dist/lib/sections.d.ts +35 -0
- package/dist/lib/sections.d.ts.map +1 -1
- package/dist/lib/sections.js +81 -0
- package/dist/lib/sections.js.map +1 -1
- package/dist/lib/spelling.js +2 -2
- package/dist/lib/templates.js +387 -387
- package/dist/lib/themes.js +51 -51
- package/docs-src/build.py +113 -113
- package/docs-src/extra.css +208 -208
- package/docs-src/md-to-html.lua +6 -6
- package/docs-src/template.html +116 -116
- package/eslint.config.js +27 -27
- package/lib/anchor-match.ts +276 -308
- package/lib/annotations.ts +644 -644
- package/lib/build.ts +1766 -1766
- package/lib/citations.ts +160 -160
- package/lib/commands/build.ts +855 -855
- package/lib/commands/citations.ts +515 -515
- package/lib/commands/comments.ts +1050 -1050
- package/lib/commands/context.ts +176 -174
- package/lib/commands/core.ts +309 -309
- package/lib/commands/doi.ts +435 -435
- package/lib/commands/file-ops.ts +372 -372
- package/lib/commands/history.ts +320 -320
- package/lib/commands/index.ts +87 -87
- package/lib/commands/init.ts +259 -259
- package/lib/commands/merge-resolve.ts +378 -378
- package/lib/commands/preview.ts +178 -178
- package/lib/commands/project-info.ts +244 -244
- package/lib/commands/quality.ts +517 -517
- package/lib/commands/response.ts +454 -454
- package/lib/commands/section-boundaries.ts +82 -82
- package/lib/commands/sections.ts +451 -451
- package/lib/commands/sync.ts +709 -706
- package/lib/commands/text-ops.ts +449 -449
- package/lib/commands/utilities.ts +448 -448
- package/lib/commands/verify-anchors.ts +272 -272
- package/lib/commands/word-tools.ts +340 -340
- package/lib/comment-realign.ts +517 -517
- package/lib/config.ts +84 -84
- package/lib/crossref.ts +781 -781
- package/lib/csl.ts +191 -191
- package/lib/dependencies.ts +98 -98
- package/lib/diff-engine.ts +465 -465
- package/lib/doi-cache.ts +115 -115
- package/lib/doi.ts +897 -897
- package/lib/equations.ts +506 -506
- package/lib/errors.ts +346 -346
- package/lib/format.ts +541 -541
- package/lib/git.ts +326 -326
- package/lib/grammar.ts +303 -303
- package/lib/image-registry.ts +180 -180
- package/lib/import.ts +911 -911
- package/lib/journals.ts +543 -543
- package/lib/macro-filter.lua +201 -201
- package/lib/macros.ts +273 -273
- package/lib/merge.ts +633 -633
- package/lib/orcid.ts +144 -144
- package/lib/pdf-comments.ts +263 -263
- package/lib/pdf-import.ts +524 -524
- package/lib/plugins.ts +362 -362
- package/lib/postprocess.ts +188 -188
- package/lib/pptx-color-filter.lua +37 -37
- package/lib/pptx-template.ts +469 -469
- package/lib/pptx-themes.ts +483 -483
- package/lib/protect-restore.ts +520 -520
- package/lib/rate-limiter.ts +94 -94
- package/lib/response.ts +197 -197
- package/lib/restore-references.ts +240 -240
- package/lib/review.ts +327 -327
- package/lib/schema.ts +488 -488
- package/lib/scientific-words.ts +73 -73
- package/lib/sections.ts +425 -335
- package/lib/slides.ts +756 -756
- package/lib/spelling.ts +334 -334
- package/lib/templates.ts +526 -526
- package/lib/themes.ts +742 -742
- package/lib/trackchanges.ts +247 -247
- package/lib/tui.ts +450 -450
- package/lib/types.ts +550 -550
- package/lib/undo.ts +250 -250
- package/lib/utils.ts +69 -69
- package/lib/variables.ts +179 -179
- package/lib/word-extraction.ts +806 -806
- package/lib/word.ts +643 -643
- package/lib/wordcomments.ts +840 -840
- package/mkdocs.yml +64 -64
- package/package.json +137 -137
- package/scripts/postbuild.js +47 -47
- package/skill/REFERENCE.md +539 -539
- package/skill/SKILL.md +295 -295
- package/tsconfig.json +26 -26
- package/types/index.d.ts +525 -525
|
@@ -1,201 +1,201 @@
|
|
|
1
|
-
--[[
|
|
2
|
-
docrev macro filter.
|
|
3
|
-
|
|
4
|
-
Reads a JSON sidecar describing one-argument LaTeX-style macros and expands
|
|
5
|
-
them per output FORMAT. Used for the built-in \tofill{X} (bold orange [X]
|
|
6
|
-
placeholder) and any user-declared macros from rev.yaml.
|
|
7
|
-
|
|
8
|
-
Sidecar path is passed via the DOCREV_MACROS_FILE environment variable, set
|
|
9
|
-
by build.ts before spawning pandoc. Env vars (not metadata) because pandoc's
|
|
10
|
-
filter traversal runs RawInline/RawBlock BEFORE Meta, so by the time we'd
|
|
11
|
-
read metadata the inline expansions have already happened.
|
|
12
|
-
|
|
13
|
-
Why raw OpenXML for docx? Pandoc 3.x's docx writer does NOT honor
|
|
14
|
-
`Span{style="color: #..."}` — those spans render as plain text with no
|
|
15
|
-
<w:color> run property. So for docx we emit raw <w:r> nodes directly. Same
|
|
16
|
-
reasoning for the pptx-color-filter.
|
|
17
|
-
|
|
18
|
-
For latex/pdf/beamer the markdown source already contains \tofill{X} as a raw
|
|
19
|
-
LaTeX inline; we leave it alone because build.ts injects a \providecommand
|
|
20
|
-
into header-includes. For html we emit a raw <span> with inline style. For
|
|
21
|
-
everything else (markdown, gfm, plain) we degrade to **bold [X]** so the
|
|
22
|
-
placeholder never silently disappears.
|
|
23
|
-
]]
|
|
24
|
-
|
|
25
|
-
local json = require('pandoc.json')
|
|
26
|
-
|
|
27
|
-
local macros_by_name = {}
|
|
28
|
-
|
|
29
|
-
local function load_sidecar()
|
|
30
|
-
local path = os.getenv('DOCREV_MACROS_FILE')
|
|
31
|
-
if not path or path == '' then
|
|
32
|
-
return
|
|
33
|
-
end
|
|
34
|
-
local fh = io.open(path, 'r')
|
|
35
|
-
if not fh then
|
|
36
|
-
io.stderr:write('docrev macro-filter: cannot read sidecar: ' .. path .. '\n')
|
|
37
|
-
return
|
|
38
|
-
end
|
|
39
|
-
local content = fh:read('*a')
|
|
40
|
-
fh:close()
|
|
41
|
-
local ok, parsed = pcall(json.decode, content)
|
|
42
|
-
if not ok or type(parsed) ~= 'table' or type(parsed.macros) ~= 'table' then
|
|
43
|
-
io.stderr:write('docrev macro-filter: malformed sidecar JSON\n')
|
|
44
|
-
return
|
|
45
|
-
end
|
|
46
|
-
for _, m in ipairs(parsed.macros) do
|
|
47
|
-
if type(m) == 'table' and type(m.name) == 'string' then
|
|
48
|
-
macros_by_name[m.name] = m
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
load_sidecar()
|
|
54
|
-
|
|
55
|
-
local function xml_escape(s)
|
|
56
|
-
return (s:gsub('&', '&'):gsub('<', '<'):gsub('>', '>'))
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
local function html_escape(s)
|
|
60
|
-
return (s
|
|
61
|
-
:gsub('&', '&')
|
|
62
|
-
:gsub('<', '<')
|
|
63
|
-
:gsub('>', '>')
|
|
64
|
-
:gsub('"', '"'))
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
-- Resolve effective style for a macro in the current pandoc format.
|
|
68
|
-
-- Per-format entry wins over `default` (replacement, not merge — matches
|
|
69
|
-
-- macros.ts semantics).
|
|
70
|
-
local function pick_style(macro, format)
|
|
71
|
-
if macro.formats and macro.formats[format] then
|
|
72
|
-
return macro.formats[format]
|
|
73
|
-
end
|
|
74
|
-
return macro.default or {}
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
-- Build the inside of the bracket: [prefix][arg][suffix], optionally without
|
|
78
|
-
-- brackets when style.bracket == false.
|
|
79
|
-
local function compose_text(style, arg)
|
|
80
|
-
local prefix = style.prefix or ''
|
|
81
|
-
local suffix = style.suffix or ''
|
|
82
|
-
local inner = prefix .. arg .. suffix
|
|
83
|
-
if style.bracket == false then
|
|
84
|
-
return inner
|
|
85
|
-
end
|
|
86
|
-
return '[' .. inner .. ']'
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
local function render_docx_run(style, arg)
|
|
90
|
-
local rpr = {}
|
|
91
|
-
if style.color then
|
|
92
|
-
table.insert(rpr, '<w:color w:val="' .. style.color .. '"/>')
|
|
93
|
-
end
|
|
94
|
-
if style.bold then
|
|
95
|
-
table.insert(rpr, '<w:b/>')
|
|
96
|
-
end
|
|
97
|
-
if style.italic then
|
|
98
|
-
table.insert(rpr, '<w:i/>')
|
|
99
|
-
end
|
|
100
|
-
local rpr_xml = ''
|
|
101
|
-
if #rpr > 0 then
|
|
102
|
-
rpr_xml = '<w:rPr>' .. table.concat(rpr) .. '</w:rPr>'
|
|
103
|
-
end
|
|
104
|
-
local text = xml_escape(compose_text(style, arg))
|
|
105
|
-
return '<w:r>' .. rpr_xml ..
|
|
106
|
-
'<w:t xml:space="preserve">' .. text .. '</w:t></w:r>'
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
local function render_html(style, arg)
|
|
110
|
-
local css = {}
|
|
111
|
-
if style.color then
|
|
112
|
-
table.insert(css, 'color:#' .. style.color)
|
|
113
|
-
end
|
|
114
|
-
if style.bold then
|
|
115
|
-
table.insert(css, 'font-weight:bold')
|
|
116
|
-
end
|
|
117
|
-
if style.italic then
|
|
118
|
-
table.insert(css, 'font-style:italic')
|
|
119
|
-
end
|
|
120
|
-
local text = html_escape(compose_text(style, arg))
|
|
121
|
-
if #css == 0 then
|
|
122
|
-
return '<span>' .. text .. '</span>'
|
|
123
|
-
end
|
|
124
|
-
return '<span style="' .. table.concat(css, ';') .. '">' .. text .. '</span>'
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
-- Fallback path: produce native pandoc inlines so the macro never silently
|
|
128
|
-
-- disappears in markdown/gfm/plain output. Used when the current format has
|
|
129
|
-
-- no native rich-text path (or we couldn't open the sidecar).
|
|
130
|
-
local function fallback_inlines(style, arg)
|
|
131
|
-
local doc = pandoc.read(compose_text(style, arg), 'markdown')
|
|
132
|
-
local inlines = pandoc.utils.blocks_to_inlines(doc.blocks)
|
|
133
|
-
if style.bold then
|
|
134
|
-
inlines = { pandoc.Strong(inlines) }
|
|
135
|
-
end
|
|
136
|
-
if style.italic then
|
|
137
|
-
inlines = { pandoc.Emph(inlines) }
|
|
138
|
-
end
|
|
139
|
-
return inlines
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
-- Match `\NAME{...}` (with balanced braces inside the argument is NOT
|
|
143
|
-
-- supported — the use case is plain placeholder text, mirroring the reference
|
|
144
|
-
-- filter; users who need nested braces should use a different mechanism).
|
|
145
|
-
local function parse_call(text)
|
|
146
|
-
local name, arg = text:match('^\\([A-Za-z][A-Za-z0-9]*)%s*{(.*)}%s*$')
|
|
147
|
-
if name and arg and macros_by_name[name] then
|
|
148
|
-
return name, arg
|
|
149
|
-
end
|
|
150
|
-
return nil, nil
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
local function expand_inline(el)
|
|
154
|
-
if el.format ~= 'tex' and el.format ~= 'latex' then
|
|
155
|
-
return nil
|
|
156
|
-
end
|
|
157
|
-
local name, arg = parse_call(el.text)
|
|
158
|
-
if not name then return nil end
|
|
159
|
-
local macro = macros_by_name[name]
|
|
160
|
-
local style = pick_style(macro, FORMAT)
|
|
161
|
-
|
|
162
|
-
if FORMAT == 'docx' then
|
|
163
|
-
return pandoc.RawInline('openxml', render_docx_run(style, arg))
|
|
164
|
-
elseif FORMAT == 'html' or FORMAT == 'html4' or FORMAT == 'html5' or FORMAT == 'chunkedhtml' then
|
|
165
|
-
return pandoc.RawInline('html', render_html(style, arg))
|
|
166
|
-
elseif FORMAT == 'latex' or FORMAT == 'beamer' or FORMAT == 'context' then
|
|
167
|
-
-- Leave the raw LaTeX as-is. build.ts injects \providecommand into
|
|
168
|
-
-- header-includes, so the LaTeX engine renders it directly.
|
|
169
|
-
return nil
|
|
170
|
-
else
|
|
171
|
-
return fallback_inlines(style, arg)
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
local function expand_block(el)
|
|
176
|
-
if el.format ~= 'tex' and el.format ~= 'latex' then
|
|
177
|
-
return nil
|
|
178
|
-
end
|
|
179
|
-
local name, arg = parse_call(el.text)
|
|
180
|
-
if not name then return nil end
|
|
181
|
-
local macro = macros_by_name[name]
|
|
182
|
-
local style = pick_style(macro, FORMAT)
|
|
183
|
-
|
|
184
|
-
if FORMAT == 'docx' then
|
|
185
|
-
return pandoc.RawBlock('openxml', '<w:p>' .. render_docx_run(style, arg) .. '</w:p>')
|
|
186
|
-
elseif FORMAT == 'html' or FORMAT == 'html4' or FORMAT == 'html5' or FORMAT == 'chunkedhtml' then
|
|
187
|
-
return pandoc.RawBlock('html', '<p>' .. render_html(style, arg) .. '</p>')
|
|
188
|
-
elseif FORMAT == 'latex' or FORMAT == 'beamer' or FORMAT == 'context' then
|
|
189
|
-
return nil
|
|
190
|
-
else
|
|
191
|
-
return pandoc.Para(fallback_inlines(style, arg))
|
|
192
|
-
end
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
function RawInline(el)
|
|
196
|
-
return expand_inline(el)
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
function RawBlock(el)
|
|
200
|
-
return expand_block(el)
|
|
201
|
-
end
|
|
1
|
+
--[[
|
|
2
|
+
docrev macro filter.
|
|
3
|
+
|
|
4
|
+
Reads a JSON sidecar describing one-argument LaTeX-style macros and expands
|
|
5
|
+
them per output FORMAT. Used for the built-in \tofill{X} (bold orange [X]
|
|
6
|
+
placeholder) and any user-declared macros from rev.yaml.
|
|
7
|
+
|
|
8
|
+
Sidecar path is passed via the DOCREV_MACROS_FILE environment variable, set
|
|
9
|
+
by build.ts before spawning pandoc. Env vars (not metadata) because pandoc's
|
|
10
|
+
filter traversal runs RawInline/RawBlock BEFORE Meta, so by the time we'd
|
|
11
|
+
read metadata the inline expansions have already happened.
|
|
12
|
+
|
|
13
|
+
Why raw OpenXML for docx? Pandoc 3.x's docx writer does NOT honor
|
|
14
|
+
`Span{style="color: #..."}` — those spans render as plain text with no
|
|
15
|
+
<w:color> run property. So for docx we emit raw <w:r> nodes directly. Same
|
|
16
|
+
reasoning for the pptx-color-filter.
|
|
17
|
+
|
|
18
|
+
For latex/pdf/beamer the markdown source already contains \tofill{X} as a raw
|
|
19
|
+
LaTeX inline; we leave it alone because build.ts injects a \providecommand
|
|
20
|
+
into header-includes. For html we emit a raw <span> with inline style. For
|
|
21
|
+
everything else (markdown, gfm, plain) we degrade to **bold [X]** so the
|
|
22
|
+
placeholder never silently disappears.
|
|
23
|
+
]]
|
|
24
|
+
|
|
25
|
+
local json = require('pandoc.json')
|
|
26
|
+
|
|
27
|
+
local macros_by_name = {}
|
|
28
|
+
|
|
29
|
+
local function load_sidecar()
|
|
30
|
+
local path = os.getenv('DOCREV_MACROS_FILE')
|
|
31
|
+
if not path or path == '' then
|
|
32
|
+
return
|
|
33
|
+
end
|
|
34
|
+
local fh = io.open(path, 'r')
|
|
35
|
+
if not fh then
|
|
36
|
+
io.stderr:write('docrev macro-filter: cannot read sidecar: ' .. path .. '\n')
|
|
37
|
+
return
|
|
38
|
+
end
|
|
39
|
+
local content = fh:read('*a')
|
|
40
|
+
fh:close()
|
|
41
|
+
local ok, parsed = pcall(json.decode, content)
|
|
42
|
+
if not ok or type(parsed) ~= 'table' or type(parsed.macros) ~= 'table' then
|
|
43
|
+
io.stderr:write('docrev macro-filter: malformed sidecar JSON\n')
|
|
44
|
+
return
|
|
45
|
+
end
|
|
46
|
+
for _, m in ipairs(parsed.macros) do
|
|
47
|
+
if type(m) == 'table' and type(m.name) == 'string' then
|
|
48
|
+
macros_by_name[m.name] = m
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
load_sidecar()
|
|
54
|
+
|
|
55
|
+
local function xml_escape(s)
|
|
56
|
+
return (s:gsub('&', '&'):gsub('<', '<'):gsub('>', '>'))
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
local function html_escape(s)
|
|
60
|
+
return (s
|
|
61
|
+
:gsub('&', '&')
|
|
62
|
+
:gsub('<', '<')
|
|
63
|
+
:gsub('>', '>')
|
|
64
|
+
:gsub('"', '"'))
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
-- Resolve effective style for a macro in the current pandoc format.
|
|
68
|
+
-- Per-format entry wins over `default` (replacement, not merge — matches
|
|
69
|
+
-- macros.ts semantics).
|
|
70
|
+
local function pick_style(macro, format)
|
|
71
|
+
if macro.formats and macro.formats[format] then
|
|
72
|
+
return macro.formats[format]
|
|
73
|
+
end
|
|
74
|
+
return macro.default or {}
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
-- Build the inside of the bracket: [prefix][arg][suffix], optionally without
|
|
78
|
+
-- brackets when style.bracket == false.
|
|
79
|
+
local function compose_text(style, arg)
|
|
80
|
+
local prefix = style.prefix or ''
|
|
81
|
+
local suffix = style.suffix or ''
|
|
82
|
+
local inner = prefix .. arg .. suffix
|
|
83
|
+
if style.bracket == false then
|
|
84
|
+
return inner
|
|
85
|
+
end
|
|
86
|
+
return '[' .. inner .. ']'
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
local function render_docx_run(style, arg)
|
|
90
|
+
local rpr = {}
|
|
91
|
+
if style.color then
|
|
92
|
+
table.insert(rpr, '<w:color w:val="' .. style.color .. '"/>')
|
|
93
|
+
end
|
|
94
|
+
if style.bold then
|
|
95
|
+
table.insert(rpr, '<w:b/>')
|
|
96
|
+
end
|
|
97
|
+
if style.italic then
|
|
98
|
+
table.insert(rpr, '<w:i/>')
|
|
99
|
+
end
|
|
100
|
+
local rpr_xml = ''
|
|
101
|
+
if #rpr > 0 then
|
|
102
|
+
rpr_xml = '<w:rPr>' .. table.concat(rpr) .. '</w:rPr>'
|
|
103
|
+
end
|
|
104
|
+
local text = xml_escape(compose_text(style, arg))
|
|
105
|
+
return '<w:r>' .. rpr_xml ..
|
|
106
|
+
'<w:t xml:space="preserve">' .. text .. '</w:t></w:r>'
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
local function render_html(style, arg)
|
|
110
|
+
local css = {}
|
|
111
|
+
if style.color then
|
|
112
|
+
table.insert(css, 'color:#' .. style.color)
|
|
113
|
+
end
|
|
114
|
+
if style.bold then
|
|
115
|
+
table.insert(css, 'font-weight:bold')
|
|
116
|
+
end
|
|
117
|
+
if style.italic then
|
|
118
|
+
table.insert(css, 'font-style:italic')
|
|
119
|
+
end
|
|
120
|
+
local text = html_escape(compose_text(style, arg))
|
|
121
|
+
if #css == 0 then
|
|
122
|
+
return '<span>' .. text .. '</span>'
|
|
123
|
+
end
|
|
124
|
+
return '<span style="' .. table.concat(css, ';') .. '">' .. text .. '</span>'
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
-- Fallback path: produce native pandoc inlines so the macro never silently
|
|
128
|
+
-- disappears in markdown/gfm/plain output. Used when the current format has
|
|
129
|
+
-- no native rich-text path (or we couldn't open the sidecar).
|
|
130
|
+
local function fallback_inlines(style, arg)
|
|
131
|
+
local doc = pandoc.read(compose_text(style, arg), 'markdown')
|
|
132
|
+
local inlines = pandoc.utils.blocks_to_inlines(doc.blocks)
|
|
133
|
+
if style.bold then
|
|
134
|
+
inlines = { pandoc.Strong(inlines) }
|
|
135
|
+
end
|
|
136
|
+
if style.italic then
|
|
137
|
+
inlines = { pandoc.Emph(inlines) }
|
|
138
|
+
end
|
|
139
|
+
return inlines
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
-- Match `\NAME{...}` (with balanced braces inside the argument is NOT
|
|
143
|
+
-- supported — the use case is plain placeholder text, mirroring the reference
|
|
144
|
+
-- filter; users who need nested braces should use a different mechanism).
|
|
145
|
+
local function parse_call(text)
|
|
146
|
+
local name, arg = text:match('^\\([A-Za-z][A-Za-z0-9]*)%s*{(.*)}%s*$')
|
|
147
|
+
if name and arg and macros_by_name[name] then
|
|
148
|
+
return name, arg
|
|
149
|
+
end
|
|
150
|
+
return nil, nil
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
local function expand_inline(el)
|
|
154
|
+
if el.format ~= 'tex' and el.format ~= 'latex' then
|
|
155
|
+
return nil
|
|
156
|
+
end
|
|
157
|
+
local name, arg = parse_call(el.text)
|
|
158
|
+
if not name then return nil end
|
|
159
|
+
local macro = macros_by_name[name]
|
|
160
|
+
local style = pick_style(macro, FORMAT)
|
|
161
|
+
|
|
162
|
+
if FORMAT == 'docx' then
|
|
163
|
+
return pandoc.RawInline('openxml', render_docx_run(style, arg))
|
|
164
|
+
elseif FORMAT == 'html' or FORMAT == 'html4' or FORMAT == 'html5' or FORMAT == 'chunkedhtml' then
|
|
165
|
+
return pandoc.RawInline('html', render_html(style, arg))
|
|
166
|
+
elseif FORMAT == 'latex' or FORMAT == 'beamer' or FORMAT == 'context' then
|
|
167
|
+
-- Leave the raw LaTeX as-is. build.ts injects \providecommand into
|
|
168
|
+
-- header-includes, so the LaTeX engine renders it directly.
|
|
169
|
+
return nil
|
|
170
|
+
else
|
|
171
|
+
return fallback_inlines(style, arg)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
local function expand_block(el)
|
|
176
|
+
if el.format ~= 'tex' and el.format ~= 'latex' then
|
|
177
|
+
return nil
|
|
178
|
+
end
|
|
179
|
+
local name, arg = parse_call(el.text)
|
|
180
|
+
if not name then return nil end
|
|
181
|
+
local macro = macros_by_name[name]
|
|
182
|
+
local style = pick_style(macro, FORMAT)
|
|
183
|
+
|
|
184
|
+
if FORMAT == 'docx' then
|
|
185
|
+
return pandoc.RawBlock('openxml', '<w:p>' .. render_docx_run(style, arg) .. '</w:p>')
|
|
186
|
+
elseif FORMAT == 'html' or FORMAT == 'html4' or FORMAT == 'html5' or FORMAT == 'chunkedhtml' then
|
|
187
|
+
return pandoc.RawBlock('html', '<p>' .. render_html(style, arg) .. '</p>')
|
|
188
|
+
elseif FORMAT == 'latex' or FORMAT == 'beamer' or FORMAT == 'context' then
|
|
189
|
+
return nil
|
|
190
|
+
else
|
|
191
|
+
return pandoc.Para(fallback_inlines(style, arg))
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
function RawInline(el)
|
|
196
|
+
return expand_inline(el)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
function RawBlock(el)
|
|
200
|
+
return expand_block(el)
|
|
201
|
+
end
|
package/dist/lib/pdf-comments.js
CHANGED
|
@@ -8,42 +8,42 @@ import { escapeLatex } from './utils.js';
|
|
|
8
8
|
* LaTeX preamble for margin comments
|
|
9
9
|
* Uses todonotes package with custom styling
|
|
10
10
|
*/
|
|
11
|
-
export const MARGIN_NOTES_PREAMBLE = `
|
|
12
|
-
% Margin notes for comments
|
|
13
|
-
\\usepackage[colorinlistoftodos,textsize=scriptsize]{todonotes}
|
|
14
|
-
\\usepackage{xcolor}
|
|
15
|
-
|
|
16
|
-
% Define comment colors by author
|
|
17
|
-
\\definecolor{commentblue}{RGB}{59, 130, 246}
|
|
18
|
-
\\definecolor{commentgreen}{RGB}{34, 197, 94}
|
|
19
|
-
\\definecolor{commentorange}{RGB}{249, 115, 22}
|
|
20
|
-
\\definecolor{commentpurple}{RGB}{168, 85, 247}
|
|
21
|
-
\\definecolor{commentgray}{RGB}{107, 114, 128}
|
|
22
|
-
|
|
23
|
-
% Custom margin note command
|
|
24
|
-
\\newcommand{\\margincomment}[2][]{%
|
|
25
|
-
\\todo[linecolor=commentblue,backgroundcolor=commentblue!10,bordercolor=commentblue,size=\\scriptsize,#1]{#2}%
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
% Author-specific commands
|
|
29
|
-
\\newcommand{\\reviewercomment}[2]{%
|
|
30
|
-
\\todo[linecolor=commentgreen,backgroundcolor=commentgreen!10,bordercolor=commentgreen,size=\\scriptsize]{\\textbf{#1:} #2}%
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
% Increase margin for notes (if needed)
|
|
34
|
-
% \\setlength{\\marginparwidth}{2.5cm}
|
|
11
|
+
export const MARGIN_NOTES_PREAMBLE = `
|
|
12
|
+
% Margin notes for comments
|
|
13
|
+
\\usepackage[colorinlistoftodos,textsize=scriptsize]{todonotes}
|
|
14
|
+
\\usepackage{xcolor}
|
|
15
|
+
|
|
16
|
+
% Define comment colors by author
|
|
17
|
+
\\definecolor{commentblue}{RGB}{59, 130, 246}
|
|
18
|
+
\\definecolor{commentgreen}{RGB}{34, 197, 94}
|
|
19
|
+
\\definecolor{commentorange}{RGB}{249, 115, 22}
|
|
20
|
+
\\definecolor{commentpurple}{RGB}{168, 85, 247}
|
|
21
|
+
\\definecolor{commentgray}{RGB}{107, 114, 128}
|
|
22
|
+
|
|
23
|
+
% Custom margin note command
|
|
24
|
+
\\newcommand{\\margincomment}[2][]{%
|
|
25
|
+
\\todo[linecolor=commentblue,backgroundcolor=commentblue!10,bordercolor=commentblue,size=\\scriptsize,#1]{#2}%
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
% Author-specific commands
|
|
29
|
+
\\newcommand{\\reviewercomment}[2]{%
|
|
30
|
+
\\todo[linecolor=commentgreen,backgroundcolor=commentgreen!10,bordercolor=commentgreen,size=\\scriptsize]{\\textbf{#1:} #2}%
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
% Increase margin for notes (if needed)
|
|
34
|
+
% \\setlength{\\marginparwidth}{2.5cm}
|
|
35
35
|
`;
|
|
36
36
|
/**
|
|
37
37
|
* Simpler preamble using marginpar (no extra packages needed)
|
|
38
38
|
*/
|
|
39
|
-
export const SIMPLE_MARGIN_PREAMBLE = `
|
|
40
|
-
% Simple margin notes for comments
|
|
41
|
-
\\usepackage{xcolor}
|
|
42
|
-
\\definecolor{commentcolor}{RGB}{59, 130, 246}
|
|
43
|
-
|
|
44
|
-
\\newcommand{\\margincomment}[1]{%
|
|
45
|
-
\\marginpar{\\raggedright\\scriptsize\\textcolor{commentcolor}{#1}}%
|
|
46
|
-
}
|
|
39
|
+
export const SIMPLE_MARGIN_PREAMBLE = `
|
|
40
|
+
% Simple margin notes for comments
|
|
41
|
+
\\usepackage{xcolor}
|
|
42
|
+
\\definecolor{commentcolor}{RGB}{59, 130, 246}
|
|
43
|
+
|
|
44
|
+
\\newcommand{\\margincomment}[1]{%
|
|
45
|
+
\\marginpar{\\raggedright\\scriptsize\\textcolor{commentcolor}{#1}}%
|
|
46
|
+
}
|
|
47
47
|
`;
|
|
48
48
|
/**
|
|
49
49
|
* Convert CriticMarkup comments to LaTeX margin notes
|
|
@@ -110,12 +110,12 @@ export function convertTrackChangesToLatex(markdown) {
|
|
|
110
110
|
result = result.replace(/\{~~([^~]+)~>([^~]+)~~\}/g, (match, oldText, newText) => {
|
|
111
111
|
return `\\textcolor{red}{\\sout{${escapeLatex(oldText)}}}\\textcolor{green}{${escapeLatex(newText)}}`;
|
|
112
112
|
});
|
|
113
|
-
const preamble = `
|
|
114
|
-
% Track changes visualization
|
|
115
|
-
\\usepackage{xcolor}
|
|
116
|
-
\\usepackage[normalem]{ulem}
|
|
117
|
-
\\definecolor{green}{RGB}{34, 197, 94}
|
|
118
|
-
\\definecolor{red}{RGB}{239, 68, 68}
|
|
113
|
+
const preamble = `
|
|
114
|
+
% Track changes visualization
|
|
115
|
+
\\usepackage{xcolor}
|
|
116
|
+
\\usepackage[normalem]{ulem}
|
|
117
|
+
\\definecolor{green}{RGB}{34, 197, 94}
|
|
118
|
+
\\definecolor{red}{RGB}{239, 68, 68}
|
|
119
119
|
`;
|
|
120
120
|
return { markdown: result, preamble };
|
|
121
121
|
}
|
|
@@ -131,16 +131,16 @@ export function getCombinedPreamble(options = {}) {
|
|
|
131
131
|
preamble += useTodonotes ? MARGIN_NOTES_PREAMBLE : SIMPLE_MARGIN_PREAMBLE;
|
|
132
132
|
}
|
|
133
133
|
if (trackChanges) {
|
|
134
|
-
preamble += `
|
|
135
|
-
% Track changes visualization
|
|
136
|
-
\\usepackage[normalem]{ulem}
|
|
134
|
+
preamble += `
|
|
135
|
+
% Track changes visualization
|
|
136
|
+
\\usepackage[normalem]{ulem}
|
|
137
137
|
`;
|
|
138
138
|
if (!comments) {
|
|
139
139
|
preamble += `\\usepackage{xcolor}\n`;
|
|
140
140
|
}
|
|
141
|
-
preamble += `
|
|
142
|
-
\\definecolor{insertgreen}{RGB}{34, 197, 94}
|
|
143
|
-
\\definecolor{deletered}{RGB}{239, 68, 68}
|
|
141
|
+
preamble += `
|
|
142
|
+
\\definecolor{insertgreen}{RGB}{34, 197, 94}
|
|
143
|
+
\\definecolor{deletered}{RGB}{239, 68, 68}
|
|
144
144
|
`;
|
|
145
145
|
}
|
|
146
146
|
return preamble;
|
package/dist/lib/plugins.js
CHANGED
|
@@ -128,63 +128,63 @@ export function getPluginDirs() {
|
|
|
128
128
|
*/
|
|
129
129
|
export function createProfileTemplate(journalName) {
|
|
130
130
|
const id = journalName.toLowerCase().replace(/\s+/g, '-');
|
|
131
|
-
return `# Custom journal profile for ${journalName}
|
|
132
|
-
# Save as: ~/.rev/profiles/${id}.yaml (user-wide)
|
|
133
|
-
# Or: .rev/profiles/${id}.yaml (project-specific)
|
|
134
|
-
|
|
135
|
-
id: ${id}
|
|
136
|
-
name: "${journalName}"
|
|
137
|
-
url: "https://journal-website.com/author-guidelines"
|
|
138
|
-
|
|
139
|
-
# Word count limits
|
|
140
|
-
wordLimit:
|
|
141
|
-
main: 8000 # null for no limit
|
|
142
|
-
abstract: 300
|
|
143
|
-
title: null # characters
|
|
144
|
-
|
|
145
|
-
# Reference requirements
|
|
146
|
-
references:
|
|
147
|
-
max: null # null for no limit
|
|
148
|
-
doiRequired: true
|
|
149
|
-
|
|
150
|
-
# Figure/table limits
|
|
151
|
-
figures:
|
|
152
|
-
max: 8
|
|
153
|
-
combinedWithTables: false
|
|
154
|
-
|
|
155
|
-
# Required sections
|
|
156
|
-
sections:
|
|
157
|
-
required:
|
|
158
|
-
- Abstract
|
|
159
|
-
- Introduction
|
|
160
|
-
- Methods
|
|
161
|
-
- Results
|
|
162
|
-
- Discussion
|
|
163
|
-
methodsPosition: null # 'end' or 'before-results'
|
|
164
|
-
|
|
165
|
-
# Keywords
|
|
166
|
-
keywords:
|
|
167
|
-
min: 4
|
|
168
|
-
max: 8
|
|
169
|
-
|
|
170
|
-
# Other requirements
|
|
171
|
-
dataAvailability: true
|
|
172
|
-
highlights: false
|
|
173
|
-
graphicalAbstract: false
|
|
174
|
-
|
|
175
|
-
# Build formatting defaults (applied via rev build -j ${id})
|
|
176
|
-
# formatting:
|
|
177
|
-
# csl: "${id}" # CSL style name or path
|
|
178
|
-
# pdf:
|
|
179
|
-
# fontsize: 12pt
|
|
180
|
-
# geometry: margin=1in
|
|
181
|
-
# linestretch: 1.5
|
|
182
|
-
# numbersections: false
|
|
183
|
-
# docx:
|
|
184
|
-
# reference: null # Path to reference .docx template
|
|
185
|
-
# crossref:
|
|
186
|
-
# figPrefix: [Fig., Figs.]
|
|
187
|
-
# tblPrefix: [Table, Tables]
|
|
131
|
+
return `# Custom journal profile for ${journalName}
|
|
132
|
+
# Save as: ~/.rev/profiles/${id}.yaml (user-wide)
|
|
133
|
+
# Or: .rev/profiles/${id}.yaml (project-specific)
|
|
134
|
+
|
|
135
|
+
id: ${id}
|
|
136
|
+
name: "${journalName}"
|
|
137
|
+
url: "https://journal-website.com/author-guidelines"
|
|
138
|
+
|
|
139
|
+
# Word count limits
|
|
140
|
+
wordLimit:
|
|
141
|
+
main: 8000 # null for no limit
|
|
142
|
+
abstract: 300
|
|
143
|
+
title: null # characters
|
|
144
|
+
|
|
145
|
+
# Reference requirements
|
|
146
|
+
references:
|
|
147
|
+
max: null # null for no limit
|
|
148
|
+
doiRequired: true
|
|
149
|
+
|
|
150
|
+
# Figure/table limits
|
|
151
|
+
figures:
|
|
152
|
+
max: 8
|
|
153
|
+
combinedWithTables: false
|
|
154
|
+
|
|
155
|
+
# Required sections
|
|
156
|
+
sections:
|
|
157
|
+
required:
|
|
158
|
+
- Abstract
|
|
159
|
+
- Introduction
|
|
160
|
+
- Methods
|
|
161
|
+
- Results
|
|
162
|
+
- Discussion
|
|
163
|
+
methodsPosition: null # 'end' or 'before-results'
|
|
164
|
+
|
|
165
|
+
# Keywords
|
|
166
|
+
keywords:
|
|
167
|
+
min: 4
|
|
168
|
+
max: 8
|
|
169
|
+
|
|
170
|
+
# Other requirements
|
|
171
|
+
dataAvailability: true
|
|
172
|
+
highlights: false
|
|
173
|
+
graphicalAbstract: false
|
|
174
|
+
|
|
175
|
+
# Build formatting defaults (applied via rev build -j ${id})
|
|
176
|
+
# formatting:
|
|
177
|
+
# csl: "${id}" # CSL style name or path
|
|
178
|
+
# pdf:
|
|
179
|
+
# fontsize: 12pt
|
|
180
|
+
# geometry: margin=1in
|
|
181
|
+
# linestretch: 1.5
|
|
182
|
+
# numbersections: false
|
|
183
|
+
# docx:
|
|
184
|
+
# reference: null # Path to reference .docx template
|
|
185
|
+
# crossref:
|
|
186
|
+
# figPrefix: [Fig., Figs.]
|
|
187
|
+
# tblPrefix: [Table, Tables]
|
|
188
188
|
`;
|
|
189
189
|
}
|
|
190
190
|
/**
|