docrev 0.8.1 → 0.8.5
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/.claude/settings.local.json +9 -0
- package/PLAN-tables-and-postprocess.md +850 -0
- package/README.md +33 -0
- package/bin/rev.js +12 -131
- package/bin/rev.ts +145 -0
- package/dist/bin/rev.d.ts +9 -0
- package/dist/bin/rev.d.ts.map +1 -0
- package/dist/bin/rev.js +118 -0
- package/dist/bin/rev.js.map +1 -0
- package/dist/lib/annotations.d.ts +91 -0
- package/dist/lib/annotations.d.ts.map +1 -0
- package/dist/lib/annotations.js +554 -0
- package/dist/lib/annotations.js.map +1 -0
- package/dist/lib/build.d.ts +171 -0
- package/dist/lib/build.d.ts.map +1 -0
- package/dist/lib/build.js +755 -0
- package/dist/lib/build.js.map +1 -0
- package/dist/lib/citations.d.ts +34 -0
- package/dist/lib/citations.d.ts.map +1 -0
- package/dist/lib/citations.js +140 -0
- package/dist/lib/citations.js.map +1 -0
- package/dist/lib/commands/build.d.ts +13 -0
- package/dist/lib/commands/build.d.ts.map +1 -0
- package/dist/lib/commands/build.js +678 -0
- package/dist/lib/commands/build.js.map +1 -0
- package/dist/lib/commands/citations.d.ts +11 -0
- package/dist/lib/commands/citations.d.ts.map +1 -0
- package/dist/lib/commands/citations.js +428 -0
- package/dist/lib/commands/citations.js.map +1 -0
- package/dist/lib/commands/comments.d.ts +11 -0
- package/dist/lib/commands/comments.d.ts.map +1 -0
- package/dist/lib/commands/comments.js +883 -0
- package/dist/lib/commands/comments.js.map +1 -0
- package/dist/lib/commands/context.d.ts +35 -0
- package/dist/lib/commands/context.d.ts.map +1 -0
- package/dist/lib/commands/context.js +59 -0
- package/dist/lib/commands/context.js.map +1 -0
- package/dist/lib/commands/core.d.ts +11 -0
- package/dist/lib/commands/core.d.ts.map +1 -0
- package/dist/lib/commands/core.js +246 -0
- package/dist/lib/commands/core.js.map +1 -0
- package/dist/lib/commands/doi.d.ts +11 -0
- package/dist/lib/commands/doi.d.ts.map +1 -0
- package/dist/lib/commands/doi.js +373 -0
- package/dist/lib/commands/doi.js.map +1 -0
- package/dist/lib/commands/history.d.ts +11 -0
- package/dist/lib/commands/history.d.ts.map +1 -0
- package/dist/lib/commands/history.js +245 -0
- package/dist/lib/commands/history.js.map +1 -0
- package/dist/lib/commands/index.d.ts +28 -0
- package/dist/lib/commands/index.d.ts.map +1 -0
- package/dist/lib/commands/index.js +35 -0
- package/dist/lib/commands/index.js.map +1 -0
- package/dist/lib/commands/init.d.ts +11 -0
- package/dist/lib/commands/init.d.ts.map +1 -0
- package/dist/lib/commands/init.js +209 -0
- package/dist/lib/commands/init.js.map +1 -0
- package/dist/lib/commands/response.d.ts +11 -0
- package/dist/lib/commands/response.d.ts.map +1 -0
- package/dist/lib/commands/response.js +317 -0
- package/dist/lib/commands/response.js.map +1 -0
- package/dist/lib/commands/sections.d.ts +11 -0
- package/dist/lib/commands/sections.d.ts.map +1 -0
- package/dist/lib/commands/sections.js +1071 -0
- package/dist/lib/commands/sections.js.map +1 -0
- package/dist/lib/commands/utilities.d.ts +19 -0
- package/dist/lib/commands/utilities.d.ts.map +1 -0
- package/dist/lib/commands/utilities.js +2009 -0
- package/dist/lib/commands/utilities.js.map +1 -0
- package/dist/lib/comment-realign.d.ts +50 -0
- package/dist/lib/comment-realign.d.ts.map +1 -0
- package/dist/lib/comment-realign.js +372 -0
- package/dist/lib/comment-realign.js.map +1 -0
- package/dist/lib/config.d.ts +41 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +76 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/crossref.d.ts +108 -0
- package/dist/lib/crossref.d.ts.map +1 -0
- package/dist/lib/crossref.js +597 -0
- package/dist/lib/crossref.js.map +1 -0
- package/dist/lib/dependencies.d.ts +30 -0
- package/dist/lib/dependencies.d.ts.map +1 -0
- package/dist/lib/dependencies.js +95 -0
- package/dist/lib/dependencies.js.map +1 -0
- package/dist/lib/doi-cache.d.ts +29 -0
- package/dist/lib/doi-cache.d.ts.map +1 -0
- package/dist/lib/doi-cache.js +104 -0
- package/dist/lib/doi-cache.js.map +1 -0
- package/dist/lib/doi.d.ts +65 -0
- package/dist/lib/doi.d.ts.map +1 -0
- package/dist/lib/doi.js +710 -0
- package/dist/lib/doi.js.map +1 -0
- package/dist/lib/equations.d.ts +61 -0
- package/dist/lib/equations.d.ts.map +1 -0
- package/dist/lib/equations.js +445 -0
- package/dist/lib/equations.js.map +1 -0
- package/dist/lib/errors.d.ts +60 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +303 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/format.d.ts +104 -0
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/lib/format.js +416 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/lib/git.d.ts +88 -0
- package/dist/lib/git.d.ts.map +1 -0
- package/dist/lib/git.js +304 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/grammar.d.ts +62 -0
- package/dist/lib/grammar.d.ts.map +1 -0
- package/dist/lib/grammar.js +244 -0
- package/dist/lib/grammar.js.map +1 -0
- package/dist/lib/image-registry.d.ts +68 -0
- package/dist/lib/image-registry.d.ts.map +1 -0
- package/dist/lib/image-registry.js +112 -0
- package/dist/lib/image-registry.js.map +1 -0
- package/dist/lib/import.d.ts +184 -0
- package/dist/lib/import.d.ts.map +1 -0
- package/dist/lib/import.js +1581 -0
- package/dist/lib/import.js.map +1 -0
- package/dist/lib/journals.d.ts +55 -0
- package/dist/lib/journals.d.ts.map +1 -0
- package/dist/lib/journals.js +417 -0
- package/dist/lib/journals.js.map +1 -0
- package/dist/lib/merge.d.ts +138 -0
- package/dist/lib/merge.d.ts.map +1 -0
- package/dist/lib/merge.js +603 -0
- package/dist/lib/merge.js.map +1 -0
- package/dist/lib/orcid.d.ts +36 -0
- package/dist/lib/orcid.d.ts.map +1 -0
- package/dist/lib/orcid.js +117 -0
- package/dist/lib/orcid.js.map +1 -0
- package/dist/lib/pdf-comments.d.ts +95 -0
- package/dist/lib/pdf-comments.d.ts.map +1 -0
- package/dist/lib/pdf-comments.js +192 -0
- package/dist/lib/pdf-comments.js.map +1 -0
- package/dist/lib/pdf-import.d.ts +118 -0
- package/dist/lib/pdf-import.d.ts.map +1 -0
- package/dist/lib/pdf-import.js +397 -0
- package/dist/lib/pdf-import.js.map +1 -0
- package/dist/lib/plugins.d.ts +76 -0
- package/dist/lib/plugins.d.ts.map +1 -0
- package/dist/lib/plugins.js +235 -0
- package/dist/lib/plugins.js.map +1 -0
- package/dist/lib/postprocess.d.ts +42 -0
- package/dist/lib/postprocess.d.ts.map +1 -0
- package/dist/lib/postprocess.js +138 -0
- package/dist/lib/postprocess.js.map +1 -0
- package/dist/lib/pptx-template.d.ts +59 -0
- package/dist/lib/pptx-template.d.ts.map +1 -0
- package/dist/lib/pptx-template.js +613 -0
- package/dist/lib/pptx-template.js.map +1 -0
- package/dist/lib/pptx-themes.d.ts +80 -0
- package/dist/lib/pptx-themes.d.ts.map +1 -0
- package/dist/lib/pptx-themes.js +818 -0
- package/dist/lib/pptx-themes.js.map +1 -0
- package/dist/lib/protect-restore.d.ts +137 -0
- package/dist/lib/protect-restore.d.ts.map +1 -0
- package/dist/lib/protect-restore.js +394 -0
- package/dist/lib/protect-restore.js.map +1 -0
- package/dist/lib/rate-limiter.d.ts +27 -0
- package/dist/lib/rate-limiter.d.ts.map +1 -0
- package/dist/lib/rate-limiter.js +79 -0
- package/dist/lib/rate-limiter.js.map +1 -0
- package/dist/lib/response.d.ts +41 -0
- package/dist/lib/response.d.ts.map +1 -0
- package/dist/lib/response.js +150 -0
- package/dist/lib/response.js.map +1 -0
- package/dist/lib/review.d.ts +35 -0
- package/dist/lib/review.d.ts.map +1 -0
- package/dist/lib/review.js +263 -0
- package/dist/lib/review.js.map +1 -0
- package/dist/lib/schema.d.ts +66 -0
- package/dist/lib/schema.d.ts.map +1 -0
- package/dist/lib/schema.js +339 -0
- package/dist/lib/schema.js.map +1 -0
- package/dist/lib/scientific-words.d.ts +6 -0
- package/dist/lib/scientific-words.d.ts.map +1 -0
- package/dist/lib/scientific-words.js +66 -0
- package/dist/lib/scientific-words.js.map +1 -0
- package/dist/lib/sections.d.ts +40 -0
- package/dist/lib/sections.d.ts.map +1 -0
- package/dist/lib/sections.js +288 -0
- package/dist/lib/sections.js.map +1 -0
- package/dist/lib/slides.d.ts +86 -0
- package/dist/lib/slides.d.ts.map +1 -0
- package/dist/lib/slides.js +676 -0
- package/dist/lib/slides.js.map +1 -0
- package/dist/lib/spelling.d.ts +76 -0
- package/dist/lib/spelling.d.ts.map +1 -0
- package/dist/lib/spelling.js +272 -0
- package/dist/lib/spelling.js.map +1 -0
- package/dist/lib/templates.d.ts +30 -0
- package/dist/lib/templates.d.ts.map +1 -0
- package/dist/lib/templates.js +504 -0
- package/dist/lib/templates.js.map +1 -0
- package/dist/lib/themes.d.ts +85 -0
- package/dist/lib/themes.d.ts.map +1 -0
- package/dist/lib/themes.js +652 -0
- package/dist/lib/themes.js.map +1 -0
- package/dist/lib/trackchanges.d.ts +51 -0
- package/dist/lib/trackchanges.d.ts.map +1 -0
- package/dist/lib/trackchanges.js +202 -0
- package/dist/lib/trackchanges.js.map +1 -0
- package/dist/lib/tui.d.ts +76 -0
- package/dist/lib/tui.d.ts.map +1 -0
- package/dist/lib/tui.js +377 -0
- package/dist/lib/tui.js.map +1 -0
- package/dist/lib/types.d.ts +447 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +6 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/lib/undo.d.ts +57 -0
- package/dist/lib/undo.d.ts.map +1 -0
- package/dist/lib/undo.js +185 -0
- package/dist/lib/undo.js.map +1 -0
- package/dist/lib/utils.d.ts +16 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +40 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/lib/variables.d.ts +42 -0
- package/dist/lib/variables.d.ts.map +1 -0
- package/dist/lib/variables.js +141 -0
- package/dist/lib/variables.js.map +1 -0
- package/dist/lib/word.d.ts +80 -0
- package/dist/lib/word.d.ts.map +1 -0
- package/dist/lib/word.js +360 -0
- package/dist/lib/word.js.map +1 -0
- package/dist/lib/wordcomments.d.ts +51 -0
- package/dist/lib/wordcomments.d.ts.map +1 -0
- package/dist/lib/wordcomments.js +587 -0
- package/dist/lib/wordcomments.js.map +1 -0
- package/eslint.config.js +27 -0
- package/lib/annotations.ts +622 -0
- package/lib/apply-buildup-colors.py +88 -0
- package/lib/build.ts +1013 -0
- package/lib/{citations.js → citations.ts} +38 -27
- package/lib/commands/{build.js → build.ts} +80 -27
- package/lib/commands/{citations.js → citations.ts} +36 -18
- package/lib/commands/{comments.js → comments.ts} +187 -54
- package/lib/commands/{context.js → context.ts} +18 -8
- package/lib/commands/{core.js → core.ts} +34 -20
- package/lib/commands/{doi.js → doi.ts} +32 -16
- package/lib/commands/{history.js → history.ts} +25 -12
- package/lib/commands/{index.js → index.ts} +9 -5
- package/lib/commands/{init.js → init.ts} +20 -8
- package/lib/commands/{response.js → response.ts} +47 -20
- package/lib/commands/{sections.js → sections.ts} +273 -68
- package/lib/commands/{utilities.js → utilities.ts} +338 -158
- package/lib/{comment-realign.js → comment-realign.ts} +117 -45
- package/lib/config.ts +84 -0
- package/lib/{crossref.js → crossref.ts} +213 -138
- package/lib/dependencies.ts +106 -0
- package/lib/doi-cache.ts +115 -0
- package/lib/{doi.js → doi.ts} +115 -281
- package/lib/{equations.js → equations.ts} +60 -64
- package/lib/{errors.js → errors.ts} +56 -48
- package/lib/{format.js → format.ts} +137 -63
- package/lib/{git.js → git.ts} +66 -63
- package/lib/{grammar.js → grammar.ts} +45 -32
- package/lib/image-registry.ts +180 -0
- package/lib/import.ts +2060 -0
- package/lib/journals.ts +505 -0
- package/lib/{merge.js → merge.ts} +185 -135
- package/lib/{orcid.js → orcid.ts} +17 -22
- package/lib/{pdf-comments.js → pdf-comments.ts} +76 -18
- package/lib/{pdf-import.js → pdf-import.ts} +148 -70
- package/lib/{plugins.js → plugins.ts} +82 -39
- package/lib/postprocess.ts +188 -0
- package/lib/pptx-color-filter.lua +37 -0
- package/lib/pptx-template.ts +625 -0
- 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 +896 -0
- package/lib/protect-restore.ts +516 -0
- package/lib/rate-limiter.ts +94 -0
- package/lib/{response.js → response.ts} +36 -21
- package/lib/{review.js → review.ts} +53 -43
- package/lib/{schema.js → schema.ts} +70 -25
- package/lib/{sections.js → sections.ts} +71 -76
- package/lib/slides.ts +793 -0
- package/lib/{spelling.js → spelling.ts} +43 -59
- package/lib/{templates.js → templates.ts} +20 -17
- package/lib/themes.ts +742 -0
- package/lib/{trackchanges.js → trackchanges.ts} +52 -23
- package/lib/types.ts +509 -0
- package/lib/{undo.js → undo.ts} +75 -52
- package/lib/utils.ts +41 -0
- package/lib/{variables.js → variables.ts} +60 -54
- package/lib/word.ts +428 -0
- package/lib/{wordcomments.js → wordcomments.ts} +94 -40
- package/package.json +15 -5
- package/skill/REFERENCE.md +67 -0
- package/tsconfig.json +26 -0
- package/lib/annotations.js +0 -414
- package/lib/build.js +0 -639
- package/lib/config.js +0 -79
- package/lib/import.js +0 -1145
- package/lib/journals.js +0 -629
- package/lib/word.js +0 -225
- /package/lib/{scientific-words.js → scientific-words.ts} +0 -0
|
@@ -11,16 +11,71 @@ import * as path from 'path';
|
|
|
11
11
|
import * as os from 'os';
|
|
12
12
|
import * as yaml from 'yaml';
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Journal profile requirements
|
|
16
|
+
*/
|
|
17
|
+
interface ProfileRequirements {
|
|
18
|
+
wordLimit?: Record<string, number | null>;
|
|
19
|
+
references?: Record<string, unknown>;
|
|
20
|
+
figures?: Record<string, unknown>;
|
|
21
|
+
sections?: Record<string, unknown>;
|
|
22
|
+
authors?: Record<string, unknown>;
|
|
23
|
+
keywords?: { min?: number; max?: number } | null;
|
|
24
|
+
dataAvailability?: boolean;
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Journal profile
|
|
30
|
+
*/
|
|
31
|
+
interface Profile {
|
|
32
|
+
id?: string;
|
|
33
|
+
name: string;
|
|
34
|
+
url?: string | null;
|
|
35
|
+
custom?: boolean;
|
|
36
|
+
requirements?: ProfileRequirements;
|
|
37
|
+
[key: string]: unknown;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Normalized profile
|
|
42
|
+
*/
|
|
43
|
+
interface NormalizedProfile {
|
|
44
|
+
name: string;
|
|
45
|
+
url: string | null;
|
|
46
|
+
custom: boolean;
|
|
47
|
+
requirements: ProfileRequirements;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Profile list entry
|
|
52
|
+
*/
|
|
53
|
+
interface ProfileListEntry {
|
|
54
|
+
id: string;
|
|
55
|
+
name: string;
|
|
56
|
+
source: 'user' | 'project';
|
|
57
|
+
path: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Plugin directories info
|
|
62
|
+
*/
|
|
63
|
+
interface PluginDirsInfo {
|
|
64
|
+
user: string;
|
|
65
|
+
project: string;
|
|
66
|
+
userExists: boolean;
|
|
67
|
+
projectExists: boolean;
|
|
68
|
+
}
|
|
69
|
+
|
|
14
70
|
// Plugin directories
|
|
15
71
|
const USER_PLUGINS_DIR = path.join(os.homedir(), '.rev', 'profiles');
|
|
16
72
|
const PROJECT_PLUGINS_DIR = path.join(process.cwd(), '.rev', 'profiles');
|
|
17
73
|
|
|
18
74
|
/**
|
|
19
75
|
* Load all custom journal profiles
|
|
20
|
-
* @returns {Object<string, Object>}
|
|
21
76
|
*/
|
|
22
|
-
export function loadCustomProfiles() {
|
|
23
|
-
const profiles = {};
|
|
77
|
+
export function loadCustomProfiles(): Record<string, NormalizedProfile> {
|
|
78
|
+
const profiles: Record<string, NormalizedProfile> = {};
|
|
24
79
|
|
|
25
80
|
// Load user profiles first (lower priority)
|
|
26
81
|
const userProfiles = loadProfilesFromDir(USER_PLUGINS_DIR);
|
|
@@ -35,11 +90,9 @@ export function loadCustomProfiles() {
|
|
|
35
90
|
|
|
36
91
|
/**
|
|
37
92
|
* Load profiles from a directory
|
|
38
|
-
* @param {string} dir
|
|
39
|
-
* @returns {Object<string, Object>}
|
|
40
93
|
*/
|
|
41
|
-
function loadProfilesFromDir(dir) {
|
|
42
|
-
const profiles = {};
|
|
94
|
+
function loadProfilesFromDir(dir: string): Record<string, NormalizedProfile> {
|
|
95
|
+
const profiles: Record<string, NormalizedProfile> = {};
|
|
43
96
|
|
|
44
97
|
if (!fs.existsSync(dir)) {
|
|
45
98
|
return profiles;
|
|
@@ -62,8 +115,9 @@ function loadProfilesFromDir(dir) {
|
|
|
62
115
|
const id = profile.id || path.basename(file, path.extname(file));
|
|
63
116
|
profiles[id] = normalizeProfile(profile);
|
|
64
117
|
}
|
|
65
|
-
} catch (err) {
|
|
66
|
-
|
|
118
|
+
} catch (err: unknown) {
|
|
119
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
120
|
+
console.error(`Warning: Failed to load profile ${file}: ${message}`);
|
|
67
121
|
}
|
|
68
122
|
}
|
|
69
123
|
} catch {
|
|
@@ -75,21 +129,21 @@ function loadProfilesFromDir(dir) {
|
|
|
75
129
|
|
|
76
130
|
/**
|
|
77
131
|
* Validate a profile structure
|
|
78
|
-
* @param {Object} profile
|
|
79
|
-
* @returns {boolean}
|
|
80
132
|
*/
|
|
81
|
-
function validateProfile(profile) {
|
|
133
|
+
function validateProfile(profile: unknown): profile is Profile {
|
|
82
134
|
if (!profile || typeof profile !== 'object') {
|
|
83
135
|
return false;
|
|
84
136
|
}
|
|
85
137
|
|
|
138
|
+
const p = profile as Profile;
|
|
139
|
+
|
|
86
140
|
// Must have a name
|
|
87
|
-
if (!
|
|
141
|
+
if (!p.name || typeof p.name !== 'string') {
|
|
88
142
|
return false;
|
|
89
143
|
}
|
|
90
144
|
|
|
91
145
|
// Requirements must be an object if present
|
|
92
|
-
if (
|
|
146
|
+
if (p.requirements && typeof p.requirements !== 'object') {
|
|
93
147
|
return false;
|
|
94
148
|
}
|
|
95
149
|
|
|
@@ -98,22 +152,20 @@ function validateProfile(profile) {
|
|
|
98
152
|
|
|
99
153
|
/**
|
|
100
154
|
* Normalize profile to standard structure
|
|
101
|
-
* @param {Object} profile
|
|
102
|
-
* @returns {Object}
|
|
103
155
|
*/
|
|
104
|
-
function normalizeProfile(profile) {
|
|
156
|
+
function normalizeProfile(profile: Profile): NormalizedProfile {
|
|
105
157
|
return {
|
|
106
158
|
name: profile.name,
|
|
107
159
|
url: profile.url || null,
|
|
108
160
|
custom: true,
|
|
109
161
|
requirements: {
|
|
110
|
-
wordLimit: profile.requirements?.wordLimit || profile.wordLimit || {},
|
|
111
|
-
references: profile.requirements?.references || profile.references || {},
|
|
112
|
-
figures: profile.requirements?.figures || profile.figures || {},
|
|
113
|
-
sections: profile.requirements?.sections || profile.sections || {},
|
|
114
|
-
authors: profile.requirements?.authors || profile.authors || {},
|
|
115
|
-
keywords: profile.requirements?.keywords || profile.keywords || null,
|
|
116
|
-
dataAvailability: profile.requirements?.dataAvailability || profile.dataAvailability || false,
|
|
162
|
+
wordLimit: profile.requirements?.wordLimit || (profile as { wordLimit?: Record<string, number> }).wordLimit || {},
|
|
163
|
+
references: profile.requirements?.references || (profile as { references?: Record<string, unknown> }).references || {},
|
|
164
|
+
figures: profile.requirements?.figures || (profile as { figures?: Record<string, unknown> }).figures || {},
|
|
165
|
+
sections: profile.requirements?.sections || (profile as { sections?: Record<string, unknown> }).sections || {},
|
|
166
|
+
authors: profile.requirements?.authors || (profile as { authors?: Record<string, unknown> }).authors || {},
|
|
167
|
+
keywords: profile.requirements?.keywords || (profile as { keywords?: { min?: number; max?: number } }).keywords || null,
|
|
168
|
+
dataAvailability: profile.requirements?.dataAvailability || (profile as { dataAvailability?: boolean }).dataAvailability || false,
|
|
117
169
|
...profile.requirements,
|
|
118
170
|
},
|
|
119
171
|
};
|
|
@@ -121,10 +173,8 @@ function normalizeProfile(profile) {
|
|
|
121
173
|
|
|
122
174
|
/**
|
|
123
175
|
* Initialize plugin directories
|
|
124
|
-
* @param {boolean} project - Create project directory instead of user
|
|
125
|
-
* @returns {string} Created directory path
|
|
126
176
|
*/
|
|
127
|
-
export function initPluginDir(project = false) {
|
|
177
|
+
export function initPluginDir(project = false): string {
|
|
128
178
|
const dir = project ? PROJECT_PLUGINS_DIR : USER_PLUGINS_DIR;
|
|
129
179
|
|
|
130
180
|
if (!fs.existsSync(dir)) {
|
|
@@ -136,9 +186,8 @@ export function initPluginDir(project = false) {
|
|
|
136
186
|
|
|
137
187
|
/**
|
|
138
188
|
* Get plugin directories info
|
|
139
|
-
* @returns {{user: string, project: string, userExists: boolean, projectExists: boolean}}
|
|
140
189
|
*/
|
|
141
|
-
export function getPluginDirs() {
|
|
190
|
+
export function getPluginDirs(): PluginDirsInfo {
|
|
142
191
|
return {
|
|
143
192
|
user: USER_PLUGINS_DIR,
|
|
144
193
|
project: PROJECT_PLUGINS_DIR,
|
|
@@ -149,10 +198,8 @@ export function getPluginDirs() {
|
|
|
149
198
|
|
|
150
199
|
/**
|
|
151
200
|
* Create a sample profile template
|
|
152
|
-
* @param {string} journalName
|
|
153
|
-
* @returns {string} YAML content
|
|
154
201
|
*/
|
|
155
|
-
export function createProfileTemplate(journalName) {
|
|
202
|
+
export function createProfileTemplate(journalName: string): string {
|
|
156
203
|
const id = journalName.toLowerCase().replace(/\s+/g, '-');
|
|
157
204
|
|
|
158
205
|
return `# Custom journal profile for ${journalName}
|
|
@@ -203,11 +250,8 @@ graphicalAbstract: false
|
|
|
203
250
|
|
|
204
251
|
/**
|
|
205
252
|
* Save a profile template
|
|
206
|
-
* @param {string} journalName
|
|
207
|
-
* @param {boolean} project - Save to project directory
|
|
208
|
-
* @returns {string} Saved file path
|
|
209
253
|
*/
|
|
210
|
-
export function saveProfileTemplate(journalName, project = false) {
|
|
254
|
+
export function saveProfileTemplate(journalName: string, project = false): string {
|
|
211
255
|
const dir = initPluginDir(project);
|
|
212
256
|
const id = journalName.toLowerCase().replace(/\s+/g, '-');
|
|
213
257
|
const filePath = path.join(dir, `${id}.yaml`);
|
|
@@ -224,10 +268,9 @@ export function saveProfileTemplate(journalName, project = false) {
|
|
|
224
268
|
|
|
225
269
|
/**
|
|
226
270
|
* List all custom profiles
|
|
227
|
-
* @returns {Array<{id: string, name: string, source: string, path: string}>}
|
|
228
271
|
*/
|
|
229
|
-
export function listCustomProfiles() {
|
|
230
|
-
const result = [];
|
|
272
|
+
export function listCustomProfiles(): ProfileListEntry[] {
|
|
273
|
+
const result: ProfileListEntry[] = [];
|
|
231
274
|
|
|
232
275
|
// User profiles
|
|
233
276
|
if (fs.existsSync(USER_PLUGINS_DIR)) {
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Postprocess scripting for docrev
|
|
3
|
+
*
|
|
4
|
+
* Allows users to run custom scripts after output generation.
|
|
5
|
+
* Supports shell scripts, PowerShell, Python, and Node.js.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as fs from 'fs';
|
|
9
|
+
import * as path from 'path';
|
|
10
|
+
import { spawn } from 'child_process';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Script execution result
|
|
14
|
+
*/
|
|
15
|
+
interface ExecutionResult {
|
|
16
|
+
success: boolean;
|
|
17
|
+
stdout: string;
|
|
18
|
+
stderr: string;
|
|
19
|
+
error?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Execution options
|
|
24
|
+
*/
|
|
25
|
+
interface ExecutionOptions {
|
|
26
|
+
verbose?: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Postprocess result
|
|
31
|
+
*/
|
|
32
|
+
interface PostprocessResult {
|
|
33
|
+
success: boolean;
|
|
34
|
+
error?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Execute a script with environment variables
|
|
39
|
+
*/
|
|
40
|
+
export async function executeScript(
|
|
41
|
+
scriptPath: string,
|
|
42
|
+
env: Record<string, string>,
|
|
43
|
+
options: ExecutionOptions = {}
|
|
44
|
+
): Promise<ExecutionResult> {
|
|
45
|
+
return new Promise((resolve) => {
|
|
46
|
+
const ext = path.extname(scriptPath).toLowerCase();
|
|
47
|
+
const isWindows = process.platform === 'win32';
|
|
48
|
+
let command: string;
|
|
49
|
+
let args: string[];
|
|
50
|
+
let useShell: boolean;
|
|
51
|
+
|
|
52
|
+
// Determine how to run based on extension
|
|
53
|
+
if (ext === '.ps1') {
|
|
54
|
+
command = 'powershell';
|
|
55
|
+
args = ['-ExecutionPolicy', 'Bypass', '-File', scriptPath];
|
|
56
|
+
useShell = false;
|
|
57
|
+
} else if (ext === '.py') {
|
|
58
|
+
// Python needs shell on Windows for PATH resolution
|
|
59
|
+
command = isWindows ? 'python' : 'python3';
|
|
60
|
+
// On Windows, wrap path in quotes to handle spaces
|
|
61
|
+
args = [isWindows ? `"${scriptPath}"` : scriptPath];
|
|
62
|
+
useShell = isWindows;
|
|
63
|
+
} else if (ext === '.js' || ext === '.mjs') {
|
|
64
|
+
// Node.js is typically in PATH and works without shell
|
|
65
|
+
command = process.execPath; // Use the same Node that's running this script
|
|
66
|
+
args = [scriptPath];
|
|
67
|
+
useShell = false;
|
|
68
|
+
} else {
|
|
69
|
+
// Assume shell script (.sh or no extension)
|
|
70
|
+
command = isWindows ? 'bash' : '/bin/bash';
|
|
71
|
+
args = [scriptPath];
|
|
72
|
+
useShell = false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const proc = spawn(command, args, {
|
|
76
|
+
env: { ...process.env, ...env },
|
|
77
|
+
cwd: path.dirname(scriptPath),
|
|
78
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
79
|
+
shell: useShell,
|
|
80
|
+
// On Windows with shell, use windowsVerbatimArguments to preserve paths with spaces
|
|
81
|
+
windowsVerbatimArguments: isWindows && useShell,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
let stdout = '';
|
|
85
|
+
let stderr = '';
|
|
86
|
+
|
|
87
|
+
proc.stdout.on('data', (data) => {
|
|
88
|
+
stdout += data.toString();
|
|
89
|
+
if (options.verbose) {
|
|
90
|
+
process.stdout.write(data);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
proc.stderr.on('data', (data) => {
|
|
95
|
+
stderr += data.toString();
|
|
96
|
+
if (options.verbose) {
|
|
97
|
+
process.stderr.write(data);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
proc.on('error', (err) => {
|
|
102
|
+
resolve({ success: false, stdout, stderr, error: err.message });
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
proc.on('close', (code) => {
|
|
106
|
+
if (code === 0) {
|
|
107
|
+
resolve({ success: true, stdout, stderr });
|
|
108
|
+
} else {
|
|
109
|
+
resolve({
|
|
110
|
+
success: false,
|
|
111
|
+
stdout,
|
|
112
|
+
stderr,
|
|
113
|
+
error: `Exit code ${code}: ${stderr.trim() || 'Unknown error'}`,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Run postprocess scripts for a given format
|
|
122
|
+
*/
|
|
123
|
+
export async function runPostprocess(
|
|
124
|
+
outputPath: string,
|
|
125
|
+
format: string,
|
|
126
|
+
config: { postprocess?: Record<string, string>; _configPath?: string; [key: string]: unknown },
|
|
127
|
+
options: ExecutionOptions = {}
|
|
128
|
+
): Promise<PostprocessResult> {
|
|
129
|
+
const postprocessConfig = config.postprocess || {};
|
|
130
|
+
|
|
131
|
+
// Collect scripts to run (format-specific + all)
|
|
132
|
+
const scripts: string[] = [];
|
|
133
|
+
if (postprocessConfig[format]) {
|
|
134
|
+
scripts.push(postprocessConfig[format]);
|
|
135
|
+
}
|
|
136
|
+
if (postprocessConfig.all) {
|
|
137
|
+
scripts.push(postprocessConfig.all);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (scripts.length === 0) {
|
|
141
|
+
return { success: true };
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const directory = path.dirname(outputPath);
|
|
145
|
+
const errors: string[] = [];
|
|
146
|
+
|
|
147
|
+
for (const scriptPath of scripts) {
|
|
148
|
+
const absoluteScript = path.isAbsolute(scriptPath)
|
|
149
|
+
? scriptPath
|
|
150
|
+
: path.join(directory, scriptPath);
|
|
151
|
+
|
|
152
|
+
if (!fs.existsSync(absoluteScript)) {
|
|
153
|
+
errors.push(`Postprocess script not found: ${scriptPath}`);
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
if (options.verbose) {
|
|
159
|
+
console.log(`Running postprocess script: ${scriptPath}`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const result = await executeScript(
|
|
163
|
+
absoluteScript,
|
|
164
|
+
{
|
|
165
|
+
OUTPUT_FILE: outputPath,
|
|
166
|
+
OUTPUT_FORMAT: format,
|
|
167
|
+
PROJECT_DIR: directory,
|
|
168
|
+
CONFIG_PATH: config._configPath || '',
|
|
169
|
+
},
|
|
170
|
+
options
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
if (!result.success) {
|
|
174
|
+
errors.push(`Script ${scriptPath} failed: ${result.error}`);
|
|
175
|
+
} else if (options.verbose) {
|
|
176
|
+
console.log(`Postprocess script completed: ${scriptPath}`);
|
|
177
|
+
}
|
|
178
|
+
} catch (err: unknown) {
|
|
179
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
180
|
+
errors.push(`Script ${scriptPath} error: ${message}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
success: errors.length === 0,
|
|
186
|
+
error: errors.length > 0 ? errors.join('\n') : undefined,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
-- Pandoc Lua filter to add color support for PPTX
|
|
2
|
+
-- Handles [text]{color=#RRGGBB} syntax
|
|
3
|
+
|
|
4
|
+
function Span(elem)
|
|
5
|
+
local color = elem.attributes['color']
|
|
6
|
+
if color then
|
|
7
|
+
-- Remove # if present
|
|
8
|
+
color = color:gsub('^#', '')
|
|
9
|
+
|
|
10
|
+
-- Create raw OpenXML for colored text
|
|
11
|
+
local content_text = pandoc.utils.stringify(elem.content)
|
|
12
|
+
|
|
13
|
+
-- Check if content has bold
|
|
14
|
+
local is_bold = false
|
|
15
|
+
for _, item in ipairs(elem.content) do
|
|
16
|
+
if item.t == 'Strong' then
|
|
17
|
+
is_bold = true
|
|
18
|
+
content_text = pandoc.utils.stringify(item.content)
|
|
19
|
+
break
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
local bold_attr = ''
|
|
24
|
+
if is_bold then
|
|
25
|
+
bold_attr = ' b="1"'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
-- Return raw OOXML span with color
|
|
29
|
+
local ooxml = string.format(
|
|
30
|
+
'<a:r><a:rPr%s><a:solidFill><a:srgbClr val="%s"/></a:solidFill></a:rPr><a:t>%s</a:t></a:r>',
|
|
31
|
+
bold_attr, color, content_text
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
return pandoc.RawInline('openxml', ooxml)
|
|
35
|
+
end
|
|
36
|
+
return elem
|
|
37
|
+
end
|