docrev 0.11.1 → 0.11.2

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.
Files changed (116) hide show
  1. package/.gitattributes +1 -1
  2. package/CHANGELOG.md +202 -197
  3. package/PLAN-tables-and-postprocess.md +850 -850
  4. package/README.md +433 -433
  5. package/bin/rev.js +11 -11
  6. package/bin/rev.ts +145 -145
  7. package/completions/rev.bash +127 -127
  8. package/completions/rev.ps1 +210 -210
  9. package/completions/rev.zsh +207 -207
  10. package/dist/lib/build.d.ts +28 -0
  11. package/dist/lib/build.d.ts.map +1 -1
  12. package/dist/lib/build.js +81 -4
  13. package/dist/lib/build.js.map +1 -1
  14. package/dist/lib/commands/utilities.js +164 -164
  15. package/dist/lib/commands/word-tools.js +8 -8
  16. package/dist/lib/grammar.js +3 -3
  17. package/dist/lib/macro-filter.lua +201 -201
  18. package/dist/lib/pdf-comments.js +44 -44
  19. package/dist/lib/plugins.js +57 -57
  20. package/dist/lib/pptx-color-filter.lua +37 -37
  21. package/dist/lib/pptx-themes.js +115 -115
  22. package/dist/lib/schema.d.ts.map +1 -1
  23. package/dist/lib/schema.js +8 -2
  24. package/dist/lib/schema.js.map +1 -1
  25. package/dist/lib/spelling.js +2 -2
  26. package/dist/lib/templates.js +387 -387
  27. package/dist/lib/themes.js +51 -51
  28. package/eslint.config.js +27 -27
  29. package/lib/anchor-match.ts +307 -307
  30. package/lib/annotations.ts +664 -664
  31. package/lib/build.ts +2047 -1956
  32. package/lib/citations.ts +160 -160
  33. package/lib/commands/build.ts +885 -885
  34. package/lib/commands/citations.ts +515 -515
  35. package/lib/commands/comments.ts +1050 -1050
  36. package/lib/commands/context.ts +176 -176
  37. package/lib/commands/core.ts +309 -309
  38. package/lib/commands/doi.ts +451 -451
  39. package/lib/commands/file-ops.ts +372 -372
  40. package/lib/commands/history.ts +320 -320
  41. package/lib/commands/index.ts +87 -87
  42. package/lib/commands/init.ts +259 -259
  43. package/lib/commands/merge-resolve.ts +378 -378
  44. package/lib/commands/preview.ts +178 -178
  45. package/lib/commands/project-info.ts +244 -244
  46. package/lib/commands/quality.ts +517 -517
  47. package/lib/commands/response.ts +454 -454
  48. package/lib/commands/section-boundaries.ts +82 -82
  49. package/lib/commands/sections.ts +451 -451
  50. package/lib/commands/sync.ts +689 -689
  51. package/lib/commands/text-ops.ts +449 -449
  52. package/lib/commands/utilities.ts +448 -448
  53. package/lib/commands/verify-anchors.ts +272 -272
  54. package/lib/commands/word-tools.ts +340 -340
  55. package/lib/comment-realign.ts +99 -99
  56. package/lib/config.ts +84 -84
  57. package/lib/crossref.ts +781 -781
  58. package/lib/csl.ts +191 -191
  59. package/lib/dependencies.ts +132 -132
  60. package/lib/diff-engine.ts +465 -465
  61. package/lib/doi-cache.ts +115 -115
  62. package/lib/doi.ts +879 -879
  63. package/lib/equations.ts +506 -506
  64. package/lib/errors.ts +350 -350
  65. package/lib/format.ts +541 -541
  66. package/lib/git.ts +326 -326
  67. package/lib/grammar.ts +303 -303
  68. package/lib/image-registry.ts +180 -180
  69. package/lib/import.ts +906 -906
  70. package/lib/journals.ts +543 -543
  71. package/lib/macro-filter.lua +201 -201
  72. package/lib/macros.ts +273 -273
  73. package/lib/merge.ts +633 -633
  74. package/lib/ooxml.ts +768 -768
  75. package/lib/orcid.ts +144 -144
  76. package/lib/pdf-comments.ts +263 -263
  77. package/lib/pdf-import.ts +524 -524
  78. package/lib/plugins.ts +362 -362
  79. package/lib/postprocess.ts +188 -188
  80. package/lib/pptx-color-filter.lua +37 -37
  81. package/lib/pptx-template.ts +469 -469
  82. package/lib/pptx-themes.ts +483 -483
  83. package/lib/protect-restore.ts +520 -520
  84. package/lib/rate-limiter.ts +127 -127
  85. package/lib/response.ts +197 -197
  86. package/lib/restore-references.ts +240 -240
  87. package/lib/review.ts +327 -327
  88. package/lib/schema.ts +494 -488
  89. package/lib/scientific-words.ts +73 -73
  90. package/lib/sections.ts +428 -428
  91. package/lib/slides.ts +756 -756
  92. package/lib/spelling.ts +334 -334
  93. package/lib/templates.ts +526 -526
  94. package/lib/themes.ts +742 -742
  95. package/lib/trackchanges.ts +166 -166
  96. package/lib/tui.ts +450 -450
  97. package/lib/types.ts +546 -546
  98. package/lib/undo.ts +250 -250
  99. package/lib/utils.ts +69 -69
  100. package/lib/variables.ts +179 -179
  101. package/lib/word-extraction.ts +525 -525
  102. package/lib/word.ts +526 -526
  103. package/lib/wordcomments.ts +789 -789
  104. package/package.json +1 -1
  105. package/scripts/postbuild.js +47 -47
  106. package/skill/REFERENCE.md +550 -550
  107. package/skill/SKILL.md +302 -302
  108. package/tsconfig.json +26 -26
  109. package/types/index.d.ts +531 -531
  110. package/issues.md +0 -180
  111. package/site/assets/extra.css +0 -208
  112. package/site/commands.html +0 -926
  113. package/site/configuration.html +0 -469
  114. package/site/index.html +0 -288
  115. package/site/troubleshooting.html +0 -461
  116. package/site/workflow.html +0 -518
@@ -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('&', '&amp;'):gsub('<', '&lt;'):gsub('>', '&gt;'))
57
- end
58
-
59
- local function html_escape(s)
60
- return (s
61
- :gsub('&', '&amp;')
62
- :gsub('<', '&lt;')
63
- :gsub('>', '&gt;')
64
- :gsub('"', '&quot;'))
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('&', '&amp;'):gsub('<', '&lt;'):gsub('>', '&gt;'))
57
+ end
58
+
59
+ local function html_escape(s)
60
+ return (s
61
+ :gsub('&', '&amp;')
62
+ :gsub('<', '&lt;')
63
+ :gsub('>', '&gt;')
64
+ :gsub('"', '&quot;'))
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
@@ -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;
@@ -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
  /**