docrev 0.11.3 → 0.12.0
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/CHANGELOG.md +22 -0
- package/LICENSE +21 -0
- package/dist/bin/rev.js +29 -21
- package/dist/bin/rev.js.map +1 -1
- package/dist/lib/build.d.ts +43 -0
- package/dist/lib/build.d.ts.map +1 -1
- package/dist/lib/build.js +175 -5
- package/dist/lib/build.js.map +1 -1
- package/dist/lib/commands/build.d.ts.map +1 -1
- package/dist/lib/commands/build.js +39 -125
- package/dist/lib/commands/build.js.map +1 -1
- package/dist/lib/commands/comments.js +3 -3
- package/dist/lib/commands/comments.js.map +1 -1
- package/dist/lib/commands/context.d.ts +12 -1
- package/dist/lib/commands/context.d.ts.map +1 -1
- package/dist/lib/commands/context.js +34 -1
- package/dist/lib/commands/context.js.map +1 -1
- package/dist/lib/commands/merge-resolve.js +1 -1
- package/dist/lib/commands/merge-resolve.js.map +1 -1
- package/dist/lib/commands/quality.js +2 -2
- package/dist/lib/commands/quality.js.map +1 -1
- package/dist/lib/commands/sections.js +1 -1
- package/dist/lib/commands/sections.js.map +1 -1
- package/dist/lib/commands/text-ops.js +1 -1
- package/dist/lib/commands/text-ops.js.map +1 -1
- package/dist/lib/commands/utilities.d.ts.map +1 -1
- package/dist/lib/commands/utilities.js +5 -2
- package/dist/lib/commands/utilities.js.map +1 -1
- package/dist/lib/commands/word-tools.js +2 -2
- package/dist/lib/commands/word-tools.js.map +1 -1
- package/dist/lib/crossref.d.ts.map +1 -1
- package/dist/lib/crossref.js +12 -41
- package/dist/lib/crossref.js.map +1 -1
- package/dist/lib/csl.d.ts.map +1 -1
- package/dist/lib/csl.js +14 -22
- package/dist/lib/csl.js.map +1 -1
- package/dist/lib/diff-engine.js +1 -1
- package/dist/lib/diff-engine.js.map +1 -1
- package/dist/lib/equations.d.ts.map +1 -1
- package/dist/lib/equations.js +12 -3
- package/dist/lib/equations.js.map +1 -1
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +1 -30
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/image-registry.d.ts.map +1 -1
- package/dist/lib/image-registry.js +4 -0
- package/dist/lib/image-registry.js.map +1 -1
- package/dist/lib/import.d.ts +1 -1
- package/dist/lib/import.d.ts.map +1 -1
- package/dist/lib/import.js +1 -1
- package/dist/lib/import.js.map +1 -1
- package/dist/lib/input.d.ts +0 -11
- package/dist/lib/input.d.ts.map +1 -1
- package/dist/lib/input.js +0 -35
- package/dist/lib/input.js.map +1 -1
- package/dist/lib/merge.d.ts.map +1 -1
- package/dist/lib/merge.js +9 -1
- package/dist/lib/merge.js.map +1 -1
- package/dist/lib/ooxml.d.ts +22 -0
- package/dist/lib/ooxml.d.ts.map +1 -1
- package/dist/lib/ooxml.js +130 -0
- package/dist/lib/ooxml.js.map +1 -1
- package/dist/lib/orcid.d.ts.map +1 -1
- package/dist/lib/orcid.js +16 -7
- package/dist/lib/orcid.js.map +1 -1
- package/dist/lib/plugins.d.ts.map +1 -1
- package/dist/lib/plugins.js +8 -4
- package/dist/lib/plugins.js.map +1 -1
- package/dist/lib/protect-restore.d.ts.map +1 -1
- package/dist/lib/protect-restore.js +7 -5
- package/dist/lib/protect-restore.js.map +1 -1
- package/dist/lib/restore-references.d.ts.map +1 -1
- package/dist/lib/restore-references.js +25 -3
- package/dist/lib/restore-references.js.map +1 -1
- package/dist/lib/schema.d.ts.map +1 -1
- package/dist/lib/schema.js +1 -19
- package/dist/lib/schema.js.map +1 -1
- package/dist/lib/slides.js +1 -1
- package/dist/lib/slides.js.map +1 -1
- package/dist/lib/spelling.js +1 -1
- package/dist/lib/spelling.js.map +1 -1
- package/dist/lib/tui.js +0 -1
- package/dist/lib/tui.js.map +1 -1
- package/dist/lib/utils.d.ts +14 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +41 -0
- package/dist/lib/utils.js.map +1 -1
- package/dist/lib/word-extraction.d.ts +5 -5
- package/dist/lib/word-extraction.d.ts.map +1 -1
- package/dist/lib/word-extraction.js +25 -106
- package/dist/lib/word-extraction.js.map +1 -1
- package/dist/lib/word.d.ts +14 -38
- package/dist/lib/word.d.ts.map +1 -1
- package/dist/lib/word.js +24 -179
- package/dist/lib/word.js.map +1 -1
- package/dist/lib/wordcomments.d.ts.map +1 -1
- package/dist/lib/wordcomments.js +9 -7
- package/dist/lib/wordcomments.js.map +1 -1
- package/package.json +17 -6
- package/.gitattributes +0 -1
- package/PLAN-tables-and-postprocess.md +0 -850
- package/bin/rev.ts +0 -145
- package/docs-src/build.py +0 -113
- package/docs-src/extra.css +0 -208
- package/docs-src/md-to-html.lua +0 -6
- package/docs-src/template.html +0 -116
- package/eslint.config.js +0 -27
- package/lib/anchor-match.ts +0 -307
- package/lib/annotations.ts +0 -695
- package/lib/build.ts +0 -2047
- package/lib/citations.ts +0 -160
- package/lib/commands/build.ts +0 -885
- package/lib/commands/citations.ts +0 -515
- package/lib/commands/comments.ts +0 -1077
- package/lib/commands/context.ts +0 -185
- package/lib/commands/core.ts +0 -328
- package/lib/commands/doi.ts +0 -451
- package/lib/commands/file-ops.ts +0 -372
- package/lib/commands/history.ts +0 -320
- package/lib/commands/index.ts +0 -87
- package/lib/commands/init.ts +0 -259
- package/lib/commands/merge-resolve.ts +0 -378
- package/lib/commands/preview.ts +0 -178
- package/lib/commands/project-info.ts +0 -244
- package/lib/commands/quality.ts +0 -517
- package/lib/commands/response.ts +0 -454
- package/lib/commands/section-boundaries.ts +0 -82
- package/lib/commands/sections.ts +0 -451
- package/lib/commands/sync.ts +0 -689
- package/lib/commands/text-ops.ts +0 -449
- package/lib/commands/utilities.ts +0 -448
- package/lib/commands/verify-anchors.ts +0 -272
- package/lib/commands/word-tools.ts +0 -340
- package/lib/comment-realign.ts +0 -99
- package/lib/config.ts +0 -84
- package/lib/crossref.ts +0 -781
- package/lib/csl.ts +0 -191
- package/lib/dependencies.ts +0 -132
- package/lib/diff-engine.ts +0 -465
- package/lib/doi-cache.ts +0 -115
- package/lib/doi.ts +0 -879
- package/lib/equations.ts +0 -506
- package/lib/errors.ts +0 -350
- package/lib/format.ts +0 -541
- package/lib/git.ts +0 -326
- package/lib/grammar.ts +0 -303
- package/lib/image-registry.ts +0 -180
- package/lib/import.ts +0 -932
- package/lib/input.ts +0 -174
- package/lib/journals.ts +0 -543
- package/lib/macro-filter.lua +0 -201
- package/lib/macros.ts +0 -273
- package/lib/merge.ts +0 -633
- package/lib/ooxml.ts +0 -768
- package/lib/orcid.ts +0 -144
- package/lib/pdf-comments.ts +0 -263
- package/lib/pdf-import.ts +0 -524
- package/lib/plugins.ts +0 -362
- package/lib/postprocess.ts +0 -188
- package/lib/pptx-color-filter.lua +0 -37
- package/lib/pptx-template.ts +0 -469
- package/lib/pptx-themes/academic.pptx +0 -0
- package/lib/pptx-themes/corporate.pptx +0 -0
- package/lib/pptx-themes/dark.pptx +0 -0
- package/lib/pptx-themes/default.pptx +0 -0
- package/lib/pptx-themes/minimal.pptx +0 -0
- package/lib/pptx-themes/plant.pptx +0 -0
- package/lib/pptx-themes.ts +0 -483
- package/lib/protect-restore.ts +0 -520
- package/lib/rate-limiter.ts +0 -127
- package/lib/response.ts +0 -200
- package/lib/restore-references.ts +0 -240
- package/lib/review.ts +0 -327
- package/lib/schema.ts +0 -494
- package/lib/scientific-words.ts +0 -73
- package/lib/sections.ts +0 -428
- package/lib/slides.ts +0 -756
- package/lib/spelling.ts +0 -334
- package/lib/templates.ts +0 -526
- package/lib/themes.ts +0 -742
- package/lib/trackchanges.ts +0 -166
- package/lib/tui.ts +0 -450
- package/lib/types.ts +0 -546
- package/lib/undo.ts +0 -250
- package/lib/utils.ts +0 -69
- package/lib/variables.ts +0 -179
- package/lib/word-extraction.ts +0 -525
- package/lib/word.ts +0 -526
- package/lib/wordcomments.ts +0 -789
- package/mkdocs.yml +0 -64
- package/scripts/postbuild.js +0 -47
- package/tsconfig.json +0 -26
- package/types/index.d.ts +0 -531
package/lib/orcid.ts
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ORCID integration for author metadata
|
|
3
|
-
*
|
|
4
|
-
* Fetches author information from ORCID public API
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export interface OrcidProfile {
|
|
8
|
-
orcid: string;
|
|
9
|
-
name: string;
|
|
10
|
-
affiliation: string;
|
|
11
|
-
email: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Validate ORCID format (0000-0000-0000-0000)
|
|
16
|
-
*/
|
|
17
|
-
export function isValidOrcid(orcid: string): boolean {
|
|
18
|
-
return /^(\d{4}-){3}\d{3}[\dX]$/i.test(orcid);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Clean ORCID input (removes URLs, whitespace)
|
|
23
|
-
*/
|
|
24
|
-
export function cleanOrcid(input: string): string {
|
|
25
|
-
if (!input) return '';
|
|
26
|
-
|
|
27
|
-
// Remove URL prefix if present
|
|
28
|
-
let clean = input.trim()
|
|
29
|
-
.replace(/^https?:\/\/(www\.)?orcid\.org\//i, '')
|
|
30
|
-
.replace(/^orcid\.org\//i, '')
|
|
31
|
-
.trim();
|
|
32
|
-
|
|
33
|
-
return clean;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Fetch author info from ORCID public API
|
|
38
|
-
*/
|
|
39
|
-
export async function fetchOrcidProfile(orcid: string): Promise<OrcidProfile> {
|
|
40
|
-
const cleanId = cleanOrcid(orcid);
|
|
41
|
-
|
|
42
|
-
if (!isValidOrcid(cleanId)) {
|
|
43
|
-
throw new Error(`Invalid ORCID format: ${orcid}`);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const url = `https://pub.orcid.org/v3.0/${cleanId}/person`;
|
|
47
|
-
|
|
48
|
-
const response = await fetch(url, {
|
|
49
|
-
headers: {
|
|
50
|
-
'Accept': 'application/json',
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
if (!response.ok) {
|
|
55
|
-
if (response.status === 404) {
|
|
56
|
-
throw new Error(`ORCID not found: ${cleanId}`);
|
|
57
|
-
}
|
|
58
|
-
throw new Error(`ORCID API error: ${response.status}`);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const data = await response.json() as any;
|
|
62
|
-
|
|
63
|
-
// Extract name
|
|
64
|
-
const nameData = data.name;
|
|
65
|
-
let name = '';
|
|
66
|
-
if (nameData) {
|
|
67
|
-
const given = nameData['given-names']?.value || '';
|
|
68
|
-
const family = nameData['family-name']?.value || '';
|
|
69
|
-
name = `${given} ${family}`.trim();
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Extract primary affiliation
|
|
73
|
-
let affiliation = '';
|
|
74
|
-
const affiliations = data.employments?.['affiliation-group'] || [];
|
|
75
|
-
if (affiliations.length > 0) {
|
|
76
|
-
const primary = affiliations[0]?.summaries?.[0]?.['employment-summary'];
|
|
77
|
-
affiliation = primary?.organization?.name || '';
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Extract email (if public)
|
|
81
|
-
let email = '';
|
|
82
|
-
const emails = data.emails?.email || [];
|
|
83
|
-
const primaryEmail = emails.find((e: any) => e.primary) || emails[0];
|
|
84
|
-
if (primaryEmail?.email) {
|
|
85
|
-
email = primaryEmail.email;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return {
|
|
89
|
-
orcid: cleanId,
|
|
90
|
-
name,
|
|
91
|
-
affiliation,
|
|
92
|
-
email,
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Fetch work count from ORCID
|
|
98
|
-
*/
|
|
99
|
-
export async function fetchOrcidWorkCount(orcid: string): Promise<number> {
|
|
100
|
-
const cleanId = cleanOrcid(orcid);
|
|
101
|
-
|
|
102
|
-
if (!isValidOrcid(cleanId)) {
|
|
103
|
-
throw new Error(`Invalid ORCID format: ${orcid}`);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const url = `https://pub.orcid.org/v3.0/${cleanId}/works`;
|
|
107
|
-
|
|
108
|
-
const response = await fetch(url, {
|
|
109
|
-
headers: {
|
|
110
|
-
'Accept': 'application/json',
|
|
111
|
-
},
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
if (!response.ok) {
|
|
115
|
-
return 0;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const data = await response.json() as any;
|
|
119
|
-
return data.group?.length || 0;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Format author for YAML
|
|
124
|
-
*/
|
|
125
|
-
export function formatAuthorYaml(profile: OrcidProfile): string {
|
|
126
|
-
const lines: string[] = [];
|
|
127
|
-
lines.push(` - name: ${profile.name}`);
|
|
128
|
-
if (profile.affiliation) {
|
|
129
|
-
lines.push(` affiliation: ${profile.affiliation}`);
|
|
130
|
-
}
|
|
131
|
-
if (profile.email) {
|
|
132
|
-
lines.push(` email: ${profile.email}`);
|
|
133
|
-
}
|
|
134
|
-
lines.push(` orcid: ${profile.orcid}`);
|
|
135
|
-
return lines.join('\n');
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Generate ORCID badge markdown
|
|
140
|
-
*/
|
|
141
|
-
export function getOrcidBadge(orcid: string): string {
|
|
142
|
-
const cleanId = cleanOrcid(orcid);
|
|
143
|
-
return `[](https://orcid.org/${cleanId})`;
|
|
144
|
-
}
|
package/lib/pdf-comments.ts
DELETED
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PDF comment rendering for dual export
|
|
3
|
-
*
|
|
4
|
-
* Converts CriticMarkup comments to LaTeX margin notes for PDF output
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { escapeLatex } from './utils.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* LaTeX preamble for margin comments
|
|
11
|
-
* Uses todonotes package with custom styling
|
|
12
|
-
*/
|
|
13
|
-
export const MARGIN_NOTES_PREAMBLE = `
|
|
14
|
-
% Margin notes for comments
|
|
15
|
-
\\usepackage[colorinlistoftodos,textsize=scriptsize]{todonotes}
|
|
16
|
-
\\usepackage{xcolor}
|
|
17
|
-
|
|
18
|
-
% Define comment colors by author
|
|
19
|
-
\\definecolor{commentblue}{RGB}{59, 130, 246}
|
|
20
|
-
\\definecolor{commentgreen}{RGB}{34, 197, 94}
|
|
21
|
-
\\definecolor{commentorange}{RGB}{249, 115, 22}
|
|
22
|
-
\\definecolor{commentpurple}{RGB}{168, 85, 247}
|
|
23
|
-
\\definecolor{commentgray}{RGB}{107, 114, 128}
|
|
24
|
-
|
|
25
|
-
% Custom margin note command
|
|
26
|
-
\\newcommand{\\margincomment}[2][]{%
|
|
27
|
-
\\todo[linecolor=commentblue,backgroundcolor=commentblue!10,bordercolor=commentblue,size=\\scriptsize,#1]{#2}%
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
% Author-specific commands
|
|
31
|
-
\\newcommand{\\reviewercomment}[2]{%
|
|
32
|
-
\\todo[linecolor=commentgreen,backgroundcolor=commentgreen!10,bordercolor=commentgreen,size=\\scriptsize]{\\textbf{#1:} #2}%
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
% Increase margin for notes (if needed)
|
|
36
|
-
% \\setlength{\\marginparwidth}{2.5cm}
|
|
37
|
-
`;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Simpler preamble using marginpar (no extra packages needed)
|
|
41
|
-
*/
|
|
42
|
-
export const SIMPLE_MARGIN_PREAMBLE = `
|
|
43
|
-
% Simple margin notes for comments
|
|
44
|
-
\\usepackage{xcolor}
|
|
45
|
-
\\definecolor{commentcolor}{RGB}{59, 130, 246}
|
|
46
|
-
|
|
47
|
-
\\newcommand{\\margincomment}[1]{%
|
|
48
|
-
\\marginpar{\\raggedright\\scriptsize\\textcolor{commentcolor}{#1}}%
|
|
49
|
-
}
|
|
50
|
-
`;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Options for converting comments to margin notes
|
|
54
|
-
*/
|
|
55
|
-
export interface CommentConversionOptions {
|
|
56
|
-
useTodonotes?: boolean;
|
|
57
|
-
stripResolved?: boolean;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Result of comment conversion
|
|
62
|
-
*/
|
|
63
|
-
export interface CommentConversionResult {
|
|
64
|
-
markdown: string;
|
|
65
|
-
commentCount: number;
|
|
66
|
-
preamble: string;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Convert CriticMarkup comments to LaTeX margin notes
|
|
71
|
-
* {>>Author: comment text<<} -> \margincomment{Author: comment text}
|
|
72
|
-
*
|
|
73
|
-
* @param markdown - Markdown with CriticMarkup comments
|
|
74
|
-
* @param options - { useTodonotes: boolean, stripResolved: boolean }
|
|
75
|
-
* @returns Converted markdown with comment count and preamble
|
|
76
|
-
*/
|
|
77
|
-
export function convertCommentsToMarginNotes(
|
|
78
|
-
markdown: string,
|
|
79
|
-
options: CommentConversionOptions = {}
|
|
80
|
-
): CommentConversionResult {
|
|
81
|
-
const { useTodonotes = true, stripResolved = true } = options;
|
|
82
|
-
|
|
83
|
-
let commentCount = 0;
|
|
84
|
-
|
|
85
|
-
// Pattern for CriticMarkup comments: {>>author: text<<} or {>>text<<}
|
|
86
|
-
// Also handle resolved comments: {>>✓ author: text<<}
|
|
87
|
-
const commentPattern = /\{>>(✓\s*)?([^<]+)<<\}/g;
|
|
88
|
-
|
|
89
|
-
const converted = markdown.replace(commentPattern, (match, resolved, content) => {
|
|
90
|
-
// Skip resolved comments if requested
|
|
91
|
-
if (resolved && stripResolved) {
|
|
92
|
-
return '';
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
commentCount++;
|
|
96
|
-
|
|
97
|
-
// Escape LaTeX special characters
|
|
98
|
-
const escaped = escapeLatex(content.trim());
|
|
99
|
-
|
|
100
|
-
if (useTodonotes) {
|
|
101
|
-
// Check if content has author prefix (Author: text)
|
|
102
|
-
const authorMatch = escaped.match(/^([^:]+):\s*([\s\S]+)$/);
|
|
103
|
-
if (authorMatch) {
|
|
104
|
-
const [, author, text] = authorMatch;
|
|
105
|
-
return `\\reviewercomment{${author}}{${text}}`;
|
|
106
|
-
}
|
|
107
|
-
return `\\margincomment{${escaped}}`;
|
|
108
|
-
} else {
|
|
109
|
-
return `\\margincomment{${escaped}}`;
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
const preamble = useTodonotes ? MARGIN_NOTES_PREAMBLE : SIMPLE_MARGIN_PREAMBLE;
|
|
114
|
-
|
|
115
|
-
return {
|
|
116
|
-
markdown: converted,
|
|
117
|
-
commentCount,
|
|
118
|
-
preamble,
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Result of track changes conversion
|
|
124
|
-
*/
|
|
125
|
-
export interface TrackChangesResult {
|
|
126
|
-
markdown: string;
|
|
127
|
-
preamble: string;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Convert track changes to visible LaTeX formatting
|
|
132
|
-
* {++inserted++} -> \textcolor{green}{inserted}
|
|
133
|
-
* {--deleted--} -> \textcolor{red}{\sout{deleted}}
|
|
134
|
-
* {~~old~>new~~} -> \textcolor{red}{\sout{old}}\textcolor{green}{new}
|
|
135
|
-
*
|
|
136
|
-
* @param markdown - Markdown with track changes
|
|
137
|
-
* @returns Converted markdown and preamble
|
|
138
|
-
*/
|
|
139
|
-
export function convertTrackChangesToLatex(markdown: string): TrackChangesResult {
|
|
140
|
-
let result = markdown;
|
|
141
|
-
|
|
142
|
-
// Insertions: {++text++} -> green text
|
|
143
|
-
result = result.replace(/\{\+\+([^+]+)\+\+\}/g, (match, text) => {
|
|
144
|
-
return `\\textcolor{green}{${escapeLatex(text)}}`;
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
// Deletions: {--text--} -> red strikethrough
|
|
148
|
-
result = result.replace(/\{--([^-]+)--\}/g, (match, text) => {
|
|
149
|
-
return `\\textcolor{red}{\\sout{${escapeLatex(text)}}}`;
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
// Substitutions: {~~old~>new~~} -> red strikethrough + green new
|
|
153
|
-
result = result.replace(/\{~~([^~]+)~>([^~]+)~~\}/g, (match, oldText, newText) => {
|
|
154
|
-
return `\\textcolor{red}{\\sout{${escapeLatex(oldText)}}}\\textcolor{green}{${escapeLatex(newText)}}`;
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
const preamble = `
|
|
158
|
-
% Track changes visualization
|
|
159
|
-
\\usepackage{xcolor}
|
|
160
|
-
\\usepackage[normalem]{ulem}
|
|
161
|
-
\\definecolor{green}{RGB}{34, 197, 94}
|
|
162
|
-
\\definecolor{red}{RGB}{239, 68, 68}
|
|
163
|
-
`;
|
|
164
|
-
|
|
165
|
-
return { markdown: result, preamble };
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Options for combined preamble
|
|
170
|
-
*/
|
|
171
|
-
export interface PreambleOptions {
|
|
172
|
-
comments?: boolean;
|
|
173
|
-
trackChanges?: boolean;
|
|
174
|
-
useTodonotes?: boolean;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Get combined preamble for comments and track changes
|
|
179
|
-
* @param options - { comments: boolean, trackChanges: boolean, useTodonotes: boolean }
|
|
180
|
-
* @returns Combined LaTeX preamble
|
|
181
|
-
*/
|
|
182
|
-
export function getCombinedPreamble(options: PreambleOptions = {}): string {
|
|
183
|
-
const { comments = true, trackChanges = false, useTodonotes = true } = options;
|
|
184
|
-
|
|
185
|
-
let preamble = '';
|
|
186
|
-
|
|
187
|
-
if (comments) {
|
|
188
|
-
preamble += useTodonotes ? MARGIN_NOTES_PREAMBLE : SIMPLE_MARGIN_PREAMBLE;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (trackChanges) {
|
|
192
|
-
preamble += `
|
|
193
|
-
% Track changes visualization
|
|
194
|
-
\\usepackage[normalem]{ulem}
|
|
195
|
-
`;
|
|
196
|
-
if (!comments) {
|
|
197
|
-
preamble += `\\usepackage{xcolor}\n`;
|
|
198
|
-
}
|
|
199
|
-
preamble += `
|
|
200
|
-
\\definecolor{insertgreen}{RGB}{34, 197, 94}
|
|
201
|
-
\\definecolor{deletered}{RGB}{239, 68, 68}
|
|
202
|
-
`;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
return preamble;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Options for preparing markdown for annotated PDF
|
|
210
|
-
*/
|
|
211
|
-
export interface AnnotatedPdfOptions {
|
|
212
|
-
showTrackChanges?: boolean;
|
|
213
|
-
useTodonotes?: boolean;
|
|
214
|
-
stripResolved?: boolean;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Result of preparing markdown for annotated PDF
|
|
219
|
-
*/
|
|
220
|
-
export interface AnnotatedPdfResult {
|
|
221
|
-
markdown: string;
|
|
222
|
-
preamble: string;
|
|
223
|
-
commentCount: number;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Prepare markdown for PDF with visible comments
|
|
228
|
-
* Converts comments to margin notes and optionally shows track changes
|
|
229
|
-
*
|
|
230
|
-
* @param markdown - Markdown content
|
|
231
|
-
* @param options - { showTrackChanges: boolean, useTodonotes: boolean }
|
|
232
|
-
* @returns Converted markdown with preamble and comment count
|
|
233
|
-
*/
|
|
234
|
-
export function prepareMarkdownForAnnotatedPdf(
|
|
235
|
-
markdown: string,
|
|
236
|
-
options: AnnotatedPdfOptions = {}
|
|
237
|
-
): AnnotatedPdfResult {
|
|
238
|
-
const { showTrackChanges = false, useTodonotes = true, stripResolved = true } = options;
|
|
239
|
-
|
|
240
|
-
let result = markdown;
|
|
241
|
-
let preamble = '';
|
|
242
|
-
let commentCount = 0;
|
|
243
|
-
|
|
244
|
-
// Convert comments to margin notes
|
|
245
|
-
const commentResult = convertCommentsToMarginNotes(result, { useTodonotes, stripResolved });
|
|
246
|
-
result = commentResult.markdown;
|
|
247
|
-
commentCount = commentResult.commentCount;
|
|
248
|
-
preamble += commentResult.preamble;
|
|
249
|
-
|
|
250
|
-
// Optionally show track changes
|
|
251
|
-
if (showTrackChanges) {
|
|
252
|
-
const trackResult = convertTrackChangesToLatex(result);
|
|
253
|
-
result = trackResult.markdown;
|
|
254
|
-
// Add ulem package if not already in todonotes preamble
|
|
255
|
-
if (!useTodonotes) {
|
|
256
|
-
preamble += trackResult.preamble;
|
|
257
|
-
} else {
|
|
258
|
-
preamble += `\\usepackage[normalem]{ulem}\n`;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
return { markdown: result, preamble, commentCount };
|
|
263
|
-
}
|