gutterpress 0.11.23-alpha.2 → 0.11.23-alpha.4
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/README.md +10 -13
- package/dist/{README-8ef336pp.md → README-syg2hn83.md} +13 -19
- package/dist/api/index.d.ts +1 -1
- package/dist/api/index.js +5 -5
- package/dist/{build-encgnv0c.js → build-c48eer6f.js} +8 -8
- package/dist/checks/asset/extensions.d.ts +1 -1
- package/dist/checks/asset/index.d.ts +0 -1
- package/dist/checks/policy.d.ts +5 -4
- package/dist/checks/source/config-file.d.ts +9 -6
- package/dist/checks/source/dangling-links.d.ts +1 -1
- package/dist/checks/types.d.ts +2 -2
- package/dist/{cli-pz4bn98t.js → cli-54xt7pjg.js} +19 -13
- package/dist/{index-2ppw6q9v.js → cli-5crpmz42.js} +80 -1
- package/dist/{cli-xq6djqbj.js → cli-93mkaw6v.js} +166 -308
- package/dist/{cli-evg8sbht.js → cli-d9mm3vvh.js} +7 -2
- package/dist/{cli-kh8v4vvw.js → cli-gnpea9dx.js} +1 -1
- package/dist/{cli-aqh6brew.js → cli-pspjxnc8.js} +1 -1
- package/dist/{cli-pwwfxdgb.js → cli-rqh295j9.js} +15 -21
- package/dist/{index-x3ema2w3.js → cli-y6d1arem.js} +321 -272
- package/dist/cli.js +12 -12
- package/dist/{doctor-5gtpgpd1.js → doctor-ptb346k8.js} +4 -3
- package/dist/engine/shared/gcpm-extract.d.ts +8 -0
- package/dist/engine/shared/print-area.d.ts +16 -4
- package/dist/{engine-mc5br8g8.js → engine-4rzdx6af.js} +1 -1
- package/dist/{engine-tn13gk0b.js → engine-6txhxmmv.js} +2 -2
- package/dist/{ext-wn2a5afq.js → ext-gy8szg3x.js} +8 -8
- package/dist/{extension-restore-s3x1618g.js → extension-restore-dymzcasz.js} +2 -2
- package/dist/{extension-restore-g8jnmmzq.js → extension-restore-m8tj43e7.js} +4 -4
- package/dist/{gutterpress-viewer-701vf4qp.js → gutterpress-viewer-mafsby5k.js} +9 -2
- package/dist/{cli-2ppw6q9v.js → index-5crpmz42.js} +80 -1
- package/dist/{index-0skhjx3e.js → index-5kh4c78h.js} +19 -13
- package/dist/{index-2bjcghze.js → index-8ywkd2sv.js} +15 -21
- package/dist/{index-j5z86r4a.js → index-ea94zbq4.js} +329 -488
- package/dist/{cli-sdmv4bba.js → index-kaks3mm2.js} +448 -156
- package/dist/{index-4x6y8krm.js → index-yc3xj266.js} +1 -1
- package/dist/index.js +6 -6
- package/dist/lib/build-preflight.d.ts +4 -10
- package/dist/lib/build-runner.d.ts +1 -1
- package/dist/lib/extension-manager.d.ts +8 -7
- package/dist/lib/extension-manifest.d.ts +1 -13
- package/dist/lib/ghostscript.d.ts +5 -2
- package/dist/lib/lint-rules.d.ts +5 -1
- package/dist/lib/manifest-config.d.ts +3 -2
- package/dist/lib/manifest-old-spellings.d.ts +64 -0
- package/dist/lib/manifest.d.ts +15 -1
- package/dist/lib/markdown/assemble.d.ts +4 -3
- package/dist/lib/markdown/chapter-id.d.ts +1 -1
- package/dist/lib/markdown/index.d.ts +1 -1
- package/dist/lib/markdown/table.d.ts +5 -3
- package/dist/lib/page-size.d.ts +45 -33
- package/dist/lib/pdf-inspect.d.ts +27 -0
- package/dist/lib/presets.d.ts +10 -8
- package/dist/lib/printsafe.d.ts +2 -1
- package/dist/lib/project-scaffold.d.ts +1 -1
- package/dist/lib/project-templates.d.ts +9 -0
- package/dist/lib/remote-auth/sync-messages.d.ts +2 -2
- package/dist/lib/targets.d.ts +4 -4
- package/dist/lib/validation-exec.d.ts +4 -4
- package/dist/manifest-2kc56wvw.yaml +22 -0
- package/dist/manifest-41ddzm13.yaml +18 -0
- package/dist/manifest-79zsgkpn.yaml +26 -0
- package/dist/manifest-sqzm4681.yaml +22 -0
- package/dist/{manifest.schema-t7nx2stg.json → manifest.schema-w86c1xw1.json} +30 -308
- package/dist/{new-mhs46pw3.js → new-t2t28ccb.js} +9 -15
- package/dist/{package-aenwjew3.json → package-awwkt7sa.json} +0 -1
- package/dist/{page-rules-nsj3aw42.css → page-rules-ytj9p04v.css} +12 -40
- package/dist/{pdf-inspect-wnw4za71.js → pdf-inspect-b3mf81ex.js} +3 -1
- package/dist/{plugin.test.js-xgxrd8hf.tpl → plugin.test.js-gxzqqfdh.tpl} +0 -1
- package/dist/{plugins-2cek4mz1.js → plugins-fec8t2bh.js} +1 -1
- package/dist/{plugins-1sxe0dkz.js → plugins-sqa4msdk.js} +3 -3
- package/dist/{preflight-3k2b1x8e.js → preflight-srq8fktp.js} +8 -8
- package/dist/preview/file-watcher.d.ts +1 -3
- package/dist/{preview-6p9v6rht.js → preview-zsp9hstd.js} +8 -8
- package/dist/{publish-qgsngy8s.js → publish-hhy31gr9.js} +8 -8
- package/dist/render.js +30 -562
- package/dist/schema/manifest.types.d.ts +60 -105
- package/dist/{tokens-7984461t.css → tokens-n82t4k9h.css} +12 -12
- package/dist/{validate-0v7xw6wa.js → validate-r9jdz85h.js} +8 -8
- package/package.json +1 -1
- package/dist/checks/asset/approved-fonts.d.ts +0 -3
- package/dist/manifest-eagfhba6.yaml +0 -19
- package/dist/manifest-n1gh3qw5.yaml +0 -9
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
BUNDLED_EXTENSIONS,
|
|
3
2
|
EXTENSION_MANIFEST_FILENAME,
|
|
4
3
|
TWO_VERSIONS_OPEN,
|
|
5
4
|
bundledExtension,
|
|
@@ -7,18 +6,22 @@ import {
|
|
|
7
6
|
extensionStyleList,
|
|
8
7
|
isPathSpecifier,
|
|
9
8
|
loadPlugin,
|
|
10
|
-
log,
|
|
11
9
|
parseExtensionSpecifier,
|
|
12
10
|
pinnedNpmSpecifier,
|
|
13
11
|
prettify,
|
|
14
12
|
readExtensionMeta,
|
|
15
|
-
resolveExtension,
|
|
16
13
|
slugify
|
|
17
|
-
} from "./
|
|
14
|
+
} from "./cli-rqh295j9.js";
|
|
15
|
+
import {
|
|
16
|
+
log
|
|
17
|
+
} from "./cli-pspjxnc8.js";
|
|
18
|
+
import {
|
|
19
|
+
UsageError
|
|
20
|
+
} from "./cli-d8xjns66.js";
|
|
18
21
|
import {
|
|
19
22
|
BuildError,
|
|
20
23
|
EXIT_CODES
|
|
21
|
-
} from "./
|
|
24
|
+
} from "./cli-46ycxe6r.js";
|
|
22
25
|
import {
|
|
23
26
|
EXTENSIONS_DIR,
|
|
24
27
|
VENDORED_NPM_DIR,
|
|
@@ -31,10 +34,10 @@ import {
|
|
|
31
34
|
vendoredNpmPluginRoot,
|
|
32
35
|
vendoredNpmPluginRoots,
|
|
33
36
|
windowsPathKey
|
|
34
|
-
} from "./
|
|
37
|
+
} from "./cli-y28j019d.js";
|
|
35
38
|
import {
|
|
36
39
|
__require
|
|
37
|
-
} from "./
|
|
40
|
+
} from "./cli-37x76zdn.js";
|
|
38
41
|
|
|
39
42
|
// src/lib/extension-restore.ts
|
|
40
43
|
import path5 from "node:path";
|
|
@@ -91,34 +94,85 @@ import { existsSync, statSync } from "node:fs";
|
|
|
91
94
|
import { resolve, dirname } from "node:path";
|
|
92
95
|
import { parse as parseYaml, YAMLParseError } from "yaml";
|
|
93
96
|
|
|
94
|
-
// src/
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
97
|
+
// src/engine/shared/print-area.ts
|
|
98
|
+
function isPositivePoints(value) {
|
|
99
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
100
|
+
}
|
|
101
|
+
function isNonNegativePoints(value) {
|
|
102
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
103
|
+
}
|
|
104
|
+
var round3 = (n) => Math.round(n * 1000) / 1000;
|
|
105
|
+
function cssLength(pt) {
|
|
106
|
+
const inches = round3(pt / 72);
|
|
107
|
+
return Math.abs(inches * 72 - pt) < 0.000001 ? `${inches}in` : `${round3(pt)}pt`;
|
|
108
|
+
}
|
|
109
|
+
function formatPageSize(page) {
|
|
110
|
+
return `${cssLength(page.width)} ${cssLength(page.height)}`;
|
|
111
|
+
}
|
|
112
|
+
function printAreaMeta(page) {
|
|
113
|
+
const area = JSON.stringify({
|
|
114
|
+
width: page.width,
|
|
115
|
+
height: page.height,
|
|
116
|
+
bleed: page.bleed ?? 0,
|
|
117
|
+
safe: page.safe ?? 0,
|
|
118
|
+
artSafe: page.artSafe,
|
|
119
|
+
gutter: page.gutter,
|
|
120
|
+
preset: page.preset,
|
|
121
|
+
spec: page.spec
|
|
122
|
+
});
|
|
123
|
+
return `<meta name="gp-print-area" content='${area.replace(/&/g, "&").replace(/'/g, "'")}'>`;
|
|
124
|
+
}
|
|
125
|
+
function pageBoxes(area, side, scale = 1) {
|
|
126
|
+
const w = area.width * scale;
|
|
127
|
+
const h = area.height * scale;
|
|
128
|
+
const b = Math.max(0, area.bleed) * scale;
|
|
129
|
+
const s = Math.max(0, area.safe) * scale;
|
|
130
|
+
const a = Math.max(0, area.artSafe) * scale;
|
|
131
|
+
const g = Math.max(0, area.gutter) * scale;
|
|
132
|
+
const [textLeft, textRight] = side === "verso" ? [s, g] : [g, s];
|
|
133
|
+
const [artLeft, artRight] = side === "verso" ? [a, g] : [g, a];
|
|
134
|
+
const trim = { x: side === "verso" ? b : 0, y: b, w: Math.max(0, w - b), h: Math.max(0, h - 2 * b) };
|
|
135
|
+
return {
|
|
136
|
+
sheet: { x: 0, y: 0, w, h },
|
|
137
|
+
trim,
|
|
138
|
+
safe: {
|
|
139
|
+
x: trim.x + textLeft,
|
|
140
|
+
y: trim.y + s,
|
|
141
|
+
w: Math.max(0, trim.w - textLeft - textRight),
|
|
142
|
+
h: Math.max(0, trim.h - 2 * s)
|
|
143
|
+
},
|
|
144
|
+
safeArt: {
|
|
145
|
+
x: trim.x + artLeft,
|
|
146
|
+
y: trim.y + a,
|
|
147
|
+
w: Math.max(0, trim.w - artLeft - artRight),
|
|
148
|
+
h: Math.max(0, trim.h - 2 * a)
|
|
149
|
+
},
|
|
150
|
+
bleed: b
|
|
151
|
+
};
|
|
110
152
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
153
|
+
var SEVERITY = { inside: 0, unsafe: 1, bleed: 2, "off-page": 3 };
|
|
154
|
+
function judgeRect(r, boxes, rule, tol = 0) {
|
|
155
|
+
const { sheet, trim } = boxes;
|
|
156
|
+
const safe = rule === "art" ? boxes.safeArt : boxes.safe;
|
|
157
|
+
const sides = [
|
|
158
|
+
["left", -r.x, -safe.x, -trim.x, -sheet.x],
|
|
159
|
+
["right", r.x + r.w, safe.x + safe.w, trim.x + trim.w, sheet.x + sheet.w],
|
|
160
|
+
["top", -r.y, -safe.y, -trim.y, -sheet.y],
|
|
161
|
+
["bottom", r.y + r.h, safe.y + safe.h, trim.y + trim.h, sheet.y + sheet.h]
|
|
162
|
+
];
|
|
163
|
+
let worst = { kind: "inside", gap: 0, need: 0, edge: null };
|
|
164
|
+
let beyond = 0;
|
|
165
|
+
for (const [edge, ink, limit, trimEdge, sheetEdge] of sides) {
|
|
166
|
+
const past = ink - limit;
|
|
167
|
+
if (past <= tol || rule === "art" && ink >= sheetEdge - tol)
|
|
168
|
+
continue;
|
|
169
|
+
const kind = ink > sheetEdge + tol ? "off-page" : ink > trimEdge + tol ? "bleed" : "unsafe";
|
|
170
|
+
if (SEVERITY[kind] > SEVERITY[worst.kind] || kind === worst.kind && past > beyond) {
|
|
171
|
+
worst = { kind, gap: trimEdge - ink, need: trimEdge - limit, edge };
|
|
172
|
+
beyond = past;
|
|
173
|
+
}
|
|
120
174
|
}
|
|
121
|
-
return
|
|
175
|
+
return worst;
|
|
122
176
|
}
|
|
123
177
|
|
|
124
178
|
// src/lib/presets.ts
|
|
@@ -131,9 +185,7 @@ var DTRPG_PRESET = {
|
|
|
131
185
|
},
|
|
132
186
|
defaultTargets: ["dtrpg"],
|
|
133
187
|
extensions: [],
|
|
134
|
-
|
|
135
|
-
files: null
|
|
136
|
-
},
|
|
188
|
+
chapters: null,
|
|
137
189
|
print: { signature: 4, reserveLastPage: true, lastPage: undefined },
|
|
138
190
|
pdfx: {
|
|
139
191
|
flavor: "x1a",
|
|
@@ -151,59 +203,30 @@ var DTRPG_PRESET = {
|
|
|
151
203
|
bleed: 9,
|
|
152
204
|
safe: 36,
|
|
153
205
|
artSafe: 18,
|
|
154
|
-
gutter: 36
|
|
206
|
+
gutter: 36,
|
|
207
|
+
margin: undefined
|
|
155
208
|
},
|
|
156
209
|
ink: {
|
|
157
210
|
maxTac: 240,
|
|
158
211
|
tacTolerance: 0.5
|
|
159
212
|
},
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
213
|
+
checks: {
|
|
214
|
+
"pdf.structure.qpdf": "error",
|
|
215
|
+
"pdf.print.pdfx-markers": "error",
|
|
216
|
+
"pdf.print.pdfx-metadata": "error",
|
|
217
|
+
"pdf.print.embedded-fonts": "error",
|
|
218
|
+
"pdf.print.safe-margins": "error",
|
|
219
|
+
"pdf.print.bleed": "off",
|
|
220
|
+
"pdf.nav.bookmarks": "off",
|
|
221
|
+
"pdf.nav.toc-links": "off",
|
|
222
|
+
"asset.font.license": "off"
|
|
164
223
|
},
|
|
165
224
|
validate: {
|
|
166
|
-
enabled: true,
|
|
167
|
-
checks: {
|
|
168
|
-
"pdf.structure.qpdf": {
|
|
169
|
-
enabled: true,
|
|
170
|
-
severity: "error"
|
|
171
|
-
},
|
|
172
|
-
"pdf.print.pdfx-markers": {
|
|
173
|
-
enabled: true,
|
|
174
|
-
severity: "error"
|
|
175
|
-
},
|
|
176
|
-
"pdf.print.pdfx-metadata": {
|
|
177
|
-
enabled: true,
|
|
178
|
-
severity: "error"
|
|
179
|
-
},
|
|
180
|
-
"pdf.print.embedded-fonts": {
|
|
181
|
-
enabled: true,
|
|
182
|
-
severity: "error"
|
|
183
|
-
},
|
|
184
|
-
"pdf.print.safe-margins": {
|
|
185
|
-
enabled: true,
|
|
186
|
-
severity: "error"
|
|
187
|
-
}
|
|
188
|
-
},
|
|
189
|
-
source: {
|
|
190
|
-
markdownlint: null,
|
|
191
|
-
htmlhint: null,
|
|
192
|
-
stylelint: null,
|
|
193
|
-
cssOwnership: null
|
|
194
|
-
},
|
|
195
225
|
assets: {
|
|
196
|
-
maxImageSize: 1e7
|
|
197
|
-
allowAlpha: false,
|
|
198
|
-
approvedFontFiles: [],
|
|
199
|
-
requireFontLicense: false
|
|
226
|
+
maxImageSize: 1e7
|
|
200
227
|
},
|
|
201
228
|
pdf: {
|
|
202
|
-
requireBookmarks: false,
|
|
203
|
-
requireTocLinks: false,
|
|
204
229
|
minImageResolution: 300,
|
|
205
|
-
forbidTransparency: true,
|
|
206
|
-
requireBleed: false,
|
|
207
230
|
bleedSize: 9
|
|
208
231
|
},
|
|
209
232
|
heuristics: {
|
|
@@ -217,9 +240,7 @@ var BOOK_PRESET = {
|
|
|
217
240
|
id: "book",
|
|
218
241
|
defaultTargets: [],
|
|
219
242
|
extensions: [],
|
|
220
|
-
|
|
221
|
-
files: null
|
|
222
|
-
},
|
|
243
|
+
chapters: null,
|
|
223
244
|
print: { signature: 1, reserveLastPage: false, lastPage: undefined },
|
|
224
245
|
pdfx: {
|
|
225
246
|
flavor: "x1a",
|
|
@@ -237,53 +258,32 @@ var BOOK_PRESET = {
|
|
|
237
258
|
bleed: undefined,
|
|
238
259
|
safe: 18,
|
|
239
260
|
artSafe: undefined,
|
|
240
|
-
gutter: undefined
|
|
261
|
+
gutter: undefined,
|
|
262
|
+
margin: undefined
|
|
241
263
|
},
|
|
242
264
|
ink: {
|
|
243
265
|
maxTac: 400,
|
|
244
266
|
tacTolerance: 0.5
|
|
245
267
|
},
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
268
|
+
checks: {
|
|
269
|
+
"pdf.structure.qpdf": "error",
|
|
270
|
+
"pdf.print.embedded-fonts": "error",
|
|
271
|
+
"pdf.print.safe-margins": "warning",
|
|
272
|
+
"pdf.print.pdfx-markers": "off",
|
|
273
|
+
"pdf.print.pdfx-metadata": "off",
|
|
274
|
+
"pdf.print.transparency": "off",
|
|
275
|
+
"asset.image.alpha-channel": "off",
|
|
276
|
+
"pdf.print.bleed": "off",
|
|
277
|
+
"pdf.nav.bookmarks": "off",
|
|
278
|
+
"pdf.nav.toc-links": "off",
|
|
279
|
+
"asset.font.license": "off"
|
|
250
280
|
},
|
|
251
281
|
validate: {
|
|
252
|
-
enabled: true,
|
|
253
|
-
checks: {
|
|
254
|
-
"pdf.structure.qpdf": {
|
|
255
|
-
enabled: true,
|
|
256
|
-
severity: "error"
|
|
257
|
-
},
|
|
258
|
-
"pdf.print.embedded-fonts": {
|
|
259
|
-
enabled: true,
|
|
260
|
-
severity: "error"
|
|
261
|
-
},
|
|
262
|
-
"pdf.print.safe-margins": {
|
|
263
|
-
enabled: true,
|
|
264
|
-
severity: "warning"
|
|
265
|
-
},
|
|
266
|
-
"pdf.print.pdfx-markers": false,
|
|
267
|
-
"pdf.print.pdfx-metadata": false
|
|
268
|
-
},
|
|
269
|
-
source: {
|
|
270
|
-
markdownlint: null,
|
|
271
|
-
htmlhint: null,
|
|
272
|
-
stylelint: null,
|
|
273
|
-
cssOwnership: null
|
|
274
|
-
},
|
|
275
282
|
assets: {
|
|
276
|
-
maxImageSize: 1e7
|
|
277
|
-
allowAlpha: true,
|
|
278
|
-
approvedFontFiles: [],
|
|
279
|
-
requireFontLicense: false
|
|
283
|
+
maxImageSize: 1e7
|
|
280
284
|
},
|
|
281
285
|
pdf: {
|
|
282
|
-
requireBookmarks: false,
|
|
283
|
-
requireTocLinks: false,
|
|
284
286
|
minImageResolution: 300,
|
|
285
|
-
forbidTransparency: false,
|
|
286
|
-
requireBleed: false,
|
|
287
287
|
bleedSize: 9
|
|
288
288
|
},
|
|
289
289
|
heuristics: {
|
|
@@ -336,16 +336,16 @@ var DTRPG_TARGET = {
|
|
|
336
336
|
maxTac: DTRPG_PRESET.ink.maxTac,
|
|
337
337
|
tacTolerance: DTRPG_PRESET.ink.tacTolerance
|
|
338
338
|
},
|
|
339
|
+
checks: {
|
|
340
|
+
"pdf.structure.qpdf": "error",
|
|
341
|
+
"pdf.print.pdfx-markers": "error",
|
|
342
|
+
"pdf.print.pdfx-metadata": "error",
|
|
343
|
+
"pdf.print.embedded-fonts": "error",
|
|
344
|
+
"pdf.print.safe-margins": "error",
|
|
345
|
+
"pdf.print.transparency": "on"
|
|
346
|
+
},
|
|
339
347
|
validate: {
|
|
340
|
-
checks: {
|
|
341
|
-
"pdf.structure.qpdf": { enabled: true, severity: "error" },
|
|
342
|
-
"pdf.print.pdfx-markers": { enabled: true, severity: "error" },
|
|
343
|
-
"pdf.print.pdfx-metadata": { enabled: true, severity: "error" },
|
|
344
|
-
"pdf.print.embedded-fonts": { enabled: true, severity: "error" },
|
|
345
|
-
"pdf.print.safe-margins": { enabled: true, severity: "error" }
|
|
346
|
-
},
|
|
347
348
|
pdf: {
|
|
348
|
-
forbidTransparency: DTRPG_PRESET.validate.pdf.forbidTransparency,
|
|
349
349
|
minImageResolution: DTRPG_PRESET.validate.pdf.minImageResolution
|
|
350
350
|
}
|
|
351
351
|
}
|
|
@@ -363,22 +363,22 @@ var ITCH_TARGET = {
|
|
|
363
363
|
id: "itch",
|
|
364
364
|
label: "itch.io",
|
|
365
365
|
overlay: {
|
|
366
|
+
checks: {
|
|
367
|
+
"pdf.structure.qpdf": "error",
|
|
368
|
+
"pdf.print.embedded-fonts": "error",
|
|
369
|
+
"pdf.print.pdfx-markers": "off",
|
|
370
|
+
"pdf.print.pdfx-metadata": "off",
|
|
371
|
+
"pdf.print.ink-coverage": "off",
|
|
372
|
+
"pdf.print.safe-margins": "off",
|
|
373
|
+
"pdf.print.transparency": "off",
|
|
374
|
+
"pdf.print.bleed": "off",
|
|
375
|
+
"asset.image.alpha-channel": "off"
|
|
376
|
+
},
|
|
366
377
|
validate: {
|
|
367
|
-
checks: {
|
|
368
|
-
"pdf.structure.qpdf": { enabled: true, severity: "error" },
|
|
369
|
-
"pdf.print.embedded-fonts": { enabled: true, severity: "error" },
|
|
370
|
-
"pdf.print.pdfx-markers": false,
|
|
371
|
-
"pdf.print.pdfx-metadata": false,
|
|
372
|
-
"pdf.print.ink-coverage": false,
|
|
373
|
-
"pdf.print.safe-margins": false
|
|
374
|
-
},
|
|
375
378
|
assets: {
|
|
376
|
-
allowAlpha: true,
|
|
377
379
|
maxImageSize: 0
|
|
378
380
|
},
|
|
379
381
|
pdf: {
|
|
380
|
-
forbidTransparency: false,
|
|
381
|
-
requireBleed: false,
|
|
382
382
|
minImageResolution: 0
|
|
383
383
|
}
|
|
384
384
|
}
|
|
@@ -417,9 +417,9 @@ function overlayPreset(preset, target) {
|
|
|
417
417
|
...preset,
|
|
418
418
|
pdfx: { ...preset.pdfx, ...o.pdfx },
|
|
419
419
|
ink: { ...preset.ink, ...o.ink },
|
|
420
|
+
checks: { ...preset.checks, ...o.checks },
|
|
420
421
|
validate: {
|
|
421
422
|
...preset.validate,
|
|
422
|
-
checks: { ...preset.validate.checks, ...o.validate?.checks },
|
|
423
423
|
assets: { ...preset.validate.assets, ...o.validate?.assets },
|
|
424
424
|
pdf: { ...preset.validate.pdf, ...o.validate?.pdf }
|
|
425
425
|
}
|
|
@@ -434,27 +434,124 @@ var DEFAULT_STRICT_PDF_CHECKS = [
|
|
|
434
434
|
function applyDefaultPdfStrictChecks(config) {
|
|
435
435
|
const next = structuredClone(config);
|
|
436
436
|
for (const checkId of DEFAULT_STRICT_PDF_CHECKS) {
|
|
437
|
-
if (next.
|
|
438
|
-
next.
|
|
439
|
-
}
|
|
437
|
+
if (next.checks[checkId] === undefined)
|
|
438
|
+
next.checks[checkId] = "error";
|
|
440
439
|
}
|
|
441
440
|
return next;
|
|
442
441
|
}
|
|
443
442
|
|
|
443
|
+
// src/lib/manifest-old-spellings.ts
|
|
444
|
+
var SOURCE_TOOL_CHECKS = {
|
|
445
|
+
markdownlint: "source.markdownlint",
|
|
446
|
+
htmlhint: "source.htmlhint",
|
|
447
|
+
stylelint: "source.stylelint",
|
|
448
|
+
cssOwnership: "source.css-ownership"
|
|
449
|
+
};
|
|
450
|
+
var FLAG_CHECKS = {
|
|
451
|
+
"assets.allowAlpha": { check: "asset.image.alpha-channel", trueMeansOn: false },
|
|
452
|
+
"assets.requireFontLicense": { check: "asset.font.license", trueMeansOn: true },
|
|
453
|
+
"pdf.requireBookmarks": { check: "pdf.nav.bookmarks", trueMeansOn: true },
|
|
454
|
+
"pdf.requireTocLinks": { check: "pdf.nav.toc-links", trueMeansOn: true },
|
|
455
|
+
"pdf.requireBleed": { check: "pdf.print.bleed", trueMeansOn: true },
|
|
456
|
+
"pdf.forbidTransparency": { check: "pdf.print.transparency", trueMeansOn: true }
|
|
457
|
+
};
|
|
458
|
+
function isObject(v) {
|
|
459
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
460
|
+
}
|
|
461
|
+
function readOldSpellings(raw) {
|
|
462
|
+
const { source, lint, validate, ink, ...manifest } = raw;
|
|
463
|
+
const tolerance = isObject(raw.page) && "tolerance" in raw.page;
|
|
464
|
+
if (source === undefined && lint === undefined && validate === undefined && ink === undefined && !tolerance) {
|
|
465
|
+
return raw;
|
|
466
|
+
}
|
|
467
|
+
if (isObject(source) && source.assets !== undefined) {
|
|
468
|
+
throw new UsageError("Manifest field `source.assets` is no longer supported — remove it.\n" + " Assets are discovered from what your book actually references, so no list is needed.");
|
|
469
|
+
}
|
|
470
|
+
const renamed = [];
|
|
471
|
+
const dropped = [];
|
|
472
|
+
const checks = {};
|
|
473
|
+
if (isObject(source) && "files" in source) {
|
|
474
|
+
renamed.push("source.files -> chapters");
|
|
475
|
+
if (manifest.chapters === undefined)
|
|
476
|
+
manifest.chapters = source.files ?? null;
|
|
477
|
+
}
|
|
478
|
+
if (isObject(validate)) {
|
|
479
|
+
for (const [id, entry] of Object.entries(validate.checks ?? {})) {
|
|
480
|
+
if (entry === false || isObject(entry) && entry.enabled === false)
|
|
481
|
+
checks[id] = "off";
|
|
482
|
+
else if (isObject(entry) && typeof entry.severity === "string")
|
|
483
|
+
checks[id] = entry.severity;
|
|
484
|
+
else
|
|
485
|
+
checks[id] = "on";
|
|
486
|
+
}
|
|
487
|
+
if (validate.checks !== undefined)
|
|
488
|
+
renamed.push("validate.checks -> checks");
|
|
489
|
+
for (const [tool, value] of Object.entries(validate.source ?? {})) {
|
|
490
|
+
const id = SOURCE_TOOL_CHECKS[tool];
|
|
491
|
+
if (id && value === false) {
|
|
492
|
+
checks[id] = "off";
|
|
493
|
+
renamed.push(`validate.source.${tool}: false -> checks: { ${id}: off }`);
|
|
494
|
+
} else if (id && tool !== "stylelint" && typeof value === "string") {
|
|
495
|
+
dropped.push(`validate.source.${tool} (the config file is found by its usual name in the book's folder or a folder above it)`);
|
|
496
|
+
} else {
|
|
497
|
+
dropped.push(`validate.source.${tool}`);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
for (const block of ["assets", "pdf", "heuristics"]) {
|
|
501
|
+
for (const [key, value] of Object.entries(validate[block] ?? {})) {
|
|
502
|
+
const flag = FLAG_CHECKS[`${block}.${key}`];
|
|
503
|
+
if (flag && typeof value === "boolean") {
|
|
504
|
+
const level = value === flag.trueMeansOn ? "on" : "off";
|
|
505
|
+
checks[flag.check] = level;
|
|
506
|
+
renamed.push(`validate.${block}.${key}: ${value} -> checks: { ${flag.check}: ${level} }`);
|
|
507
|
+
} else {
|
|
508
|
+
dropped.push(`validate.${block}.${key} (the preset and the publish target set it)`);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
if (validate.enabled !== undefined) {
|
|
513
|
+
dropped.push("validate.enabled (`gutterpress build --skip-pre-validate --skip-post-validate` skips validation for one build)");
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
if (isObject(lint)) {
|
|
517
|
+
for (const [id, level] of Object.entries(lint.rules ?? {}))
|
|
518
|
+
checks[id] = level;
|
|
519
|
+
if (lint.rules !== undefined)
|
|
520
|
+
renamed.push("lint.rules -> checks");
|
|
521
|
+
if (lint.enabled === false) {
|
|
522
|
+
checks["source.stylelint"] = "off";
|
|
523
|
+
renamed.push("lint.enabled: false -> checks: { source.stylelint: off }");
|
|
524
|
+
} else if (lint.enabled !== undefined) {
|
|
525
|
+
dropped.push("lint.enabled");
|
|
526
|
+
}
|
|
527
|
+
if (lint.configPath !== undefined)
|
|
528
|
+
dropped.push("lint.configPath");
|
|
529
|
+
}
|
|
530
|
+
if (ink !== undefined)
|
|
531
|
+
dropped.push("ink (the preset and the publish target set it)");
|
|
532
|
+
if (tolerance) {
|
|
533
|
+
const { tolerance: _, ...page } = raw.page;
|
|
534
|
+
manifest.page = page;
|
|
535
|
+
dropped.push("page.tolerance (the preset sets it)");
|
|
536
|
+
}
|
|
537
|
+
if (Object.keys(checks).length > 0)
|
|
538
|
+
manifest.checks = { ...checks, ...manifest.checks };
|
|
539
|
+
const lines = [
|
|
540
|
+
...renamed.map((r) => ` ${r}`),
|
|
541
|
+
...dropped.map((d) => ` ${d} — no longer a setting, ignored`)
|
|
542
|
+
];
|
|
543
|
+
if (lines.length > 0) {
|
|
544
|
+
warnOnce(`old-manifest-spellings:${lines.join("|")}`, "[gutterpress] manifest.yaml uses spellings 0.11.23 replaced. They still work in this " + `release; rewrite them before the next one:
|
|
545
|
+
` + lines.join(`
|
|
546
|
+
`));
|
|
547
|
+
}
|
|
548
|
+
return manifest;
|
|
549
|
+
}
|
|
550
|
+
|
|
444
551
|
// src/lib/manifest.ts
|
|
445
552
|
var MANIFEST_FILENAMES = [
|
|
446
553
|
"manifest.yaml"
|
|
447
554
|
];
|
|
448
|
-
function hasProjectManifest(dir) {
|
|
449
|
-
return MANIFEST_FILENAMES.some((name) => {
|
|
450
|
-
const candidate = resolve(dir, name);
|
|
451
|
-
try {
|
|
452
|
-
return statSync(candidate).isFile();
|
|
453
|
-
} catch {
|
|
454
|
-
return false;
|
|
455
|
-
}
|
|
456
|
-
});
|
|
457
|
-
}
|
|
458
555
|
async function loadManifest(pathOrDir) {
|
|
459
556
|
const { manifest } = await loadManifestWithPath(pathOrDir);
|
|
460
557
|
return manifest;
|
|
@@ -468,8 +565,8 @@ async function loadManifestWithPath(pathOrDir, opts) {
|
|
|
468
565
|
throw new UsageError(`"${p}" has two versions of a setting — yours and the online version — left by a sync. Open it, keep the one you want and delete the marker lines.`);
|
|
469
566
|
}
|
|
470
567
|
try {
|
|
471
|
-
const
|
|
472
|
-
return { manifest, manifestDir: dirname(p), manifestPath: p };
|
|
568
|
+
const parsed = parseYaml(raw) ?? {};
|
|
569
|
+
return { manifest: readOldSpellings(parsed), manifestDir: dirname(p), manifestPath: p };
|
|
473
570
|
} catch (error) {
|
|
474
571
|
if (!(error instanceof YAMLParseError))
|
|
475
572
|
throw error;
|
|
@@ -605,32 +702,37 @@ function resolveCustomPage(c, m) {
|
|
|
605
702
|
return {
|
|
606
703
|
width,
|
|
607
704
|
height,
|
|
608
|
-
tolerance:
|
|
705
|
+
tolerance: 0.5,
|
|
609
706
|
bleed: c.page?.bleed ?? m.page?.bleed,
|
|
610
707
|
safe: c.page?.safe ?? m.page?.safe,
|
|
611
708
|
artSafe: c.page?.artSafe ?? m.page?.artSafe,
|
|
612
|
-
gutter: c.page?.gutter ?? m.page?.gutter
|
|
709
|
+
gutter: c.page?.gutter ?? m.page?.gutter,
|
|
710
|
+
margin: c.page?.margin ?? m.page?.margin
|
|
613
711
|
};
|
|
614
712
|
}
|
|
713
|
+
var MARGIN_EDGES = ["top", "bottom", "inside", "outside"];
|
|
714
|
+
function validatePageMargin(margin, size) {
|
|
715
|
+
const edges = isPlainObject(margin) && Object.keys(margin).every((k) => MARGIN_EDGES.includes(k)) && MARGIN_EDGES.every((e) => isNonNegativePoints(margin[e]));
|
|
716
|
+
if (!edges) {
|
|
717
|
+
throw new UsageError("Manifest field `page.margin` must set all four edges in points (72pt = 1in), for example\n" + ` page:
|
|
718
|
+
margin:
|
|
719
|
+
top: 54
|
|
720
|
+
bottom: 54
|
|
721
|
+
inside: 54
|
|
722
|
+
outside: 54
|
|
723
|
+
` + `got ${JSON.stringify(margin)}.`);
|
|
724
|
+
}
|
|
725
|
+
const m = margin;
|
|
726
|
+
if (m.inside + m.outside >= size.width || m.top + m.bottom >= size.height) {
|
|
727
|
+
throw new UsageError(`Manifest field \`page.margin\` leaves no room for text on a ${size.width} x ${size.height}pt page ` + `(inside ${m.inside} + outside ${m.outside} across, top ${m.top} + bottom ${m.bottom} down).`);
|
|
728
|
+
}
|
|
729
|
+
return m;
|
|
730
|
+
}
|
|
615
731
|
function resolveWithPreset(cliOverrides, manifest, preset) {
|
|
616
732
|
const m = manifest;
|
|
617
733
|
const c = cliOverrides;
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
const stale = [
|
|
621
|
-
legacy.output !== undefined ? "`output`" : null,
|
|
622
|
-
legacy.source?.assets !== undefined ? "`source.assets`" : null
|
|
623
|
-
].filter(Boolean);
|
|
624
|
-
throw new UsageError(`Manifest field(s) ${stale.join(" and ")} are no longer supported — remove them.
|
|
625
|
-
` + " Output goes to `dist/<title-slug>/` automatically (use `--out` for a one-off location).\n" + " Assets are discovered from what your book actually references, so no list is needed.");
|
|
626
|
-
}
|
|
627
|
-
if ((m.validate?.source?.allowedCallouts?.length ?? 0) > 0 || (c.validate?.source?.allowedCallouts?.length ?? 0) > 0) {
|
|
628
|
-
warnOnce("allowed-callouts-deprecated", "[gutterpress] manifest field `validate.source.allowedCallouts` is " + "deprecated and ignored. The `:::` container syntax it gated was " + "removed 2026-05-17. See docs/migrations/2026-05-removing-container-syntax.md.");
|
|
629
|
-
}
|
|
630
|
-
for (const key of ["minImageDpi", "allowedColorSpaces"]) {
|
|
631
|
-
if (m.validate?.assets?.[key] !== undefined || c.validate?.assets?.[key] !== undefined) {
|
|
632
|
-
warnOnce(`assets-${key}-deprecated`, `[gutterpress] manifest field \`validate.assets.${key}\` is deprecated and ` + "ignored. The source-image check it configured was removed; the build " + "and the PDF checks measure what actually prints.");
|
|
633
|
-
}
|
|
734
|
+
if (m.output !== undefined) {
|
|
735
|
+
throw new UsageError("Manifest field `output` is no longer supported — remove it.\n" + " Output goes to `dist/<title-slug>/` automatically (use `--out` for a one-off location).");
|
|
634
736
|
}
|
|
635
737
|
const removed = m;
|
|
636
738
|
if (removed.engine !== undefined) {
|
|
@@ -664,6 +766,9 @@ function resolveWithPreset(cliOverrides, manifest, preset) {
|
|
|
664
766
|
throw new UsageError("Manifest field `extensions` must be a list of specifiers.");
|
|
665
767
|
}
|
|
666
768
|
const extensions = rawExtensions.map((entry, index) => ({ entry, index })).filter(({ entry }) => typeof entry === "string" || entry?.enabled !== false).map(({ entry, index }) => normalizeExtensionEntry(entry, index));
|
|
769
|
+
const page = preset.page ? mergeShape(c.page, m.page, preset.page) : resolveCustomPage(c, m);
|
|
770
|
+
if (page.margin !== undefined && page.margin !== null)
|
|
771
|
+
validatePageMargin(page.margin, page);
|
|
667
772
|
return {
|
|
668
773
|
title: c.title ?? m.title ?? "Document",
|
|
669
774
|
authors: c.authors ?? m.authors ?? [],
|
|
@@ -673,25 +778,37 @@ function resolveWithPreset(cliOverrides, manifest, preset) {
|
|
|
673
778
|
styles: c.styles ?? m.styles,
|
|
674
779
|
extensions,
|
|
675
780
|
targets: resolveTargets(c.targets ?? m.targets, preset.defaultTargets),
|
|
676
|
-
|
|
781
|
+
chapters: c.chapters ?? m.chapters ?? preset.chapters,
|
|
782
|
+
checks: { ...preset.checks, ...resolveCheckLevels(m.checks), ...resolveCheckLevels(c.checks) },
|
|
677
783
|
pdfx: mergeShape(c.pdfx, m.pdfx, preset.pdfx),
|
|
678
784
|
print: mergeShape(c.print, m.print, preset.print),
|
|
679
|
-
page
|
|
680
|
-
ink:
|
|
681
|
-
|
|
682
|
-
...mergeShape(c.lint, m.lint, preset.lint),
|
|
683
|
-
rules: { ...preset.lint.rules, ...m.lint?.rules, ...c.lint?.rules }
|
|
684
|
-
},
|
|
685
|
-
validate: {
|
|
686
|
-
enabled: c.validate?.enabled ?? m.validate?.enabled ?? preset.validate.enabled,
|
|
687
|
-
checks: { ...preset.validate.checks, ...m.validate?.checks, ...c.validate?.checks },
|
|
688
|
-
source: mergeShape(c.validate?.source, m.validate?.source, preset.validate.source),
|
|
689
|
-
assets: mergeShape(c.validate?.assets, m.validate?.assets, preset.validate.assets),
|
|
690
|
-
pdf: mergeShape(c.validate?.pdf, m.validate?.pdf, preset.validate.pdf),
|
|
691
|
-
heuristics: mergeShape(c.validate?.heuristics, m.validate?.heuristics, preset.validate.heuristics)
|
|
692
|
-
}
|
|
785
|
+
page,
|
|
786
|
+
ink: structuredClone(preset.ink),
|
|
787
|
+
validate: structuredClone(preset.validate)
|
|
693
788
|
};
|
|
694
789
|
}
|
|
790
|
+
function resolveCheckLevels(input) {
|
|
791
|
+
if (input === undefined || input === null)
|
|
792
|
+
return {};
|
|
793
|
+
if (!isPlainObject(input)) {
|
|
794
|
+
throw new UsageError("Manifest field `checks` must map check ids to off, on, info, warn or error.");
|
|
795
|
+
}
|
|
796
|
+
const out = {};
|
|
797
|
+
for (const [id, value] of Object.entries(input)) {
|
|
798
|
+
if (value === false || value === "off")
|
|
799
|
+
out[id] = "off";
|
|
800
|
+
else if (value === true || value === "on")
|
|
801
|
+
out[id] = "on";
|
|
802
|
+
else if (value === "warn" || value === "warning")
|
|
803
|
+
out[id] = "warning";
|
|
804
|
+
else if (value === "info" || value === "error")
|
|
805
|
+
out[id] = value;
|
|
806
|
+
else {
|
|
807
|
+
throw new UsageError(`Manifest field \`checks.${id}\` must be off, on, info, warn or error, got ${JSON.stringify(value)}.`);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
return out;
|
|
811
|
+
}
|
|
695
812
|
|
|
696
813
|
// src/lib/manifest-doc.ts
|
|
697
814
|
function resolveManifestPath(projectDir) {
|
|
@@ -740,13 +857,6 @@ function ensureSeq(doc, key) {
|
|
|
740
857
|
}
|
|
741
858
|
return seq;
|
|
742
859
|
}
|
|
743
|
-
function scalarString(item) {
|
|
744
|
-
if (item && typeof item === "object" && "value" in item) {
|
|
745
|
-
const v = item.value;
|
|
746
|
-
return typeof v === "string" ? v : null;
|
|
747
|
-
}
|
|
748
|
-
return typeof item === "string" ? item : null;
|
|
749
|
-
}
|
|
750
860
|
|
|
751
861
|
// src/lib/npm-plugin-installer.ts
|
|
752
862
|
import { createHash, randomUUID as randomUUID2, timingSafeEqual } from "node:crypto";
|
|
@@ -1417,6 +1527,7 @@ function ignoreStatus(gitignore, entry) {
|
|
|
1417
1527
|
return dir.unignored || file.unignored ? "negated" : "open";
|
|
1418
1528
|
}
|
|
1419
1529
|
var PROJECT_GITIGNORE_ENTRIES = ["dist/", "extensions/npm/"];
|
|
1530
|
+
var LEGACY_NPM_LINE = /^\/?plugins\/npm\/?[ \t]*\r?\n?/gm;
|
|
1420
1531
|
async function ensureProjectGitignore(projectDir) {
|
|
1421
1532
|
const gitignorePath = path3.join(projectDir, ".gitignore");
|
|
1422
1533
|
let existing = null;
|
|
@@ -1433,10 +1544,11 @@ async function ensureProjectGitignore(projectDir) {
|
|
|
1433
1544
|
negated.push(entry);
|
|
1434
1545
|
}
|
|
1435
1546
|
if (missing.length > 0) {
|
|
1436
|
-
const
|
|
1547
|
+
const kept = missing.includes("extensions/npm/") ? (existing ?? "").replace(LEGACY_NPM_LINE, "") : existing ?? "";
|
|
1548
|
+
const lead = kept.length > 0 && !kept.endsWith(`
|
|
1437
1549
|
`) ? `
|
|
1438
1550
|
` : "";
|
|
1439
|
-
await writeFile(gitignorePath, `${
|
|
1551
|
+
await writeFile(gitignorePath, `${kept}${lead}${missing.join(`
|
|
1440
1552
|
`)}
|
|
1441
1553
|
`, "utf8");
|
|
1442
1554
|
}
|
|
@@ -1535,7 +1647,6 @@ async function describeFolder(dir, base, fallbackLabel, labelFrom = prettify) {
|
|
|
1535
1647
|
...meta.description?.trim() ? { description: meta.description.trim() } : {},
|
|
1536
1648
|
...meta.author?.trim() ? { author: meta.author.trim() } : {},
|
|
1537
1649
|
...meta.preview !== undefined ? { preview: meta.preview } : {},
|
|
1538
|
-
...meta.tokensFile?.trim() ? { tokensFile: meta.tokensFile.trim() } : {},
|
|
1539
1650
|
...styles.length > 0 ? { styles } : {},
|
|
1540
1651
|
carries: extensionCarries(meta),
|
|
1541
1652
|
dir
|
|
@@ -1669,29 +1780,6 @@ async function setExtensionEnabled(projectDir, use, enabled) {
|
|
|
1669
1780
|
await writeManifestDoc(file, doc);
|
|
1670
1781
|
});
|
|
1671
1782
|
}
|
|
1672
|
-
async function reorderExtensions(projectDir, order) {
|
|
1673
|
-
return withMutationLock(projectDir, async () => {
|
|
1674
|
-
const { doc, file } = await loadManifestDoc(projectDir);
|
|
1675
|
-
const seq = doc.get("extensions", true);
|
|
1676
|
-
if (!isSeq2(seq))
|
|
1677
|
-
throw new Error(`No extensions are configured in ${path4.basename(file)}.`);
|
|
1678
|
-
const items = seq.items;
|
|
1679
|
-
const current = items.map((item) => entryUse(item));
|
|
1680
|
-
const wanted = order.map((u) => u.trim());
|
|
1681
|
-
const sameSet = current.length === wanted.length && [...current].sort().join(`
|
|
1682
|
-
`) === [...wanted].sort().join(`
|
|
1683
|
-
`);
|
|
1684
|
-
if (!sameSet) {
|
|
1685
|
-
throw new Error("The new order must list every configured extension exactly once — reload the list and try again.");
|
|
1686
|
-
}
|
|
1687
|
-
const remaining = [...items];
|
|
1688
|
-
seq.items = wanted.map((u) => {
|
|
1689
|
-
const i = remaining.findIndex((item) => entryUse(item) === u);
|
|
1690
|
-
return remaining.splice(i, 1)[0];
|
|
1691
|
-
});
|
|
1692
|
-
await writeManifestDoc(file, doc);
|
|
1693
|
-
});
|
|
1694
|
-
}
|
|
1695
1783
|
async function removeExtension(projectDir, use) {
|
|
1696
1784
|
return withMutationLock(projectDir, async () => {
|
|
1697
1785
|
const { doc, file } = await loadManifestDoc(projectDir);
|
|
@@ -1830,6 +1918,7 @@ async function vendorNpmExtension(projectDir, input, exportName, options, commit
|
|
|
1830
1918
|
await finalizeNpmPluginInstall(installed).catch((error) => {
|
|
1831
1919
|
warnings.push(`The extension was installed, but an old backup could not be removed: ` + `${error instanceof Error ? error.message : String(error)}`);
|
|
1832
1920
|
});
|
|
1921
|
+
warnings.push(...await retireLegacyCopies(projectDir, installed.name));
|
|
1833
1922
|
try {
|
|
1834
1923
|
const { negated } = await ensureProjectGitignore(projectDir);
|
|
1835
1924
|
if (negated.includes("extensions/npm/")) {
|
|
@@ -1840,6 +1929,19 @@ async function vendorNpmExtension(projectDir, input, exportName, options, commit
|
|
|
1840
1929
|
}
|
|
1841
1930
|
return { name: installed.name, version: installed.version, use, warnings };
|
|
1842
1931
|
}
|
|
1932
|
+
async function retireLegacyCopies(projectDir, name) {
|
|
1933
|
+
const legacyPackageDir = path4.dirname(vendoredNpmPluginRoots(projectDir, name, "0.0.0")[1]);
|
|
1934
|
+
const legacyNpmDir = path4.dirname(legacyPackageDir);
|
|
1935
|
+
try {
|
|
1936
|
+
await rm3(legacyPackageDir, { recursive: true, force: true });
|
|
1937
|
+
await removeEmptyDirs([path4.dirname(legacyNpmDir), legacyNpmDir]);
|
|
1938
|
+
} catch (error) {
|
|
1939
|
+
return [
|
|
1940
|
+
`The extension was installed, but the copy an older version of Gutterpress kept under plugins/npm/ ` + `could not be removed: ${error instanceof Error ? error.message : String(error)}`
|
|
1941
|
+
];
|
|
1942
|
+
}
|
|
1943
|
+
return [];
|
|
1944
|
+
}
|
|
1843
1945
|
async function pinnedVersionsOf(projectDir, name) {
|
|
1844
1946
|
const { doc } = await loadManifestDoc(projectDir);
|
|
1845
1947
|
const seq = doc.get("extensions", true);
|
|
@@ -1937,9 +2039,6 @@ async function latestNpmVersion(name, options) {
|
|
|
1937
2039
|
}
|
|
1938
2040
|
return latest;
|
|
1939
2041
|
}
|
|
1940
|
-
async function listNpmVersions(name, options = {}) {
|
|
1941
|
-
return (await fetchNpmVersions(name, options)).versions.sort(semverRcompare);
|
|
1942
|
-
}
|
|
1943
2042
|
async function checkExtensionUpdates(projectDir, options = {}) {
|
|
1944
2043
|
const entries = await listProjectExtensions(projectDir);
|
|
1945
2044
|
const pinned = entries.filter((e) => e.kind === "npm" && e.version);
|
|
@@ -1970,14 +2069,6 @@ async function updateExtensions(projectDir, options = {}) {
|
|
|
1970
2069
|
}
|
|
1971
2070
|
return updated;
|
|
1972
2071
|
}
|
|
1973
|
-
function listBundledExtensions() {
|
|
1974
|
-
return BUNDLED_EXTENSIONS.map((b) => ({
|
|
1975
|
-
use: b.name,
|
|
1976
|
-
label: b.label,
|
|
1977
|
-
description: b.description,
|
|
1978
|
-
look: b.css !== undefined
|
|
1979
|
-
}));
|
|
1980
|
-
}
|
|
1981
2072
|
async function uniqueExtensionId(projectDir, base) {
|
|
1982
2073
|
const slug = slugify(base) || "extension";
|
|
1983
2074
|
let candidate = slug;
|
|
@@ -1986,48 +2077,6 @@ async function uniqueExtensionId(projectDir, base) {
|
|
|
1986
2077
|
}
|
|
1987
2078
|
return candidate;
|
|
1988
2079
|
}
|
|
1989
|
-
async function validateProjectExtensions(projectDir) {
|
|
1990
|
-
const out = [];
|
|
1991
|
-
for (const entry of await listProjectExtensions(projectDir)) {
|
|
1992
|
-
if (!entry.enabled) {
|
|
1993
|
-
out.push({ use: entry.use, kind: entry.kind, enabled: false, ok: true });
|
|
1994
|
-
continue;
|
|
1995
|
-
}
|
|
1996
|
-
try {
|
|
1997
|
-
await loadPlugin(extensionConfigFor(entry), projectDir);
|
|
1998
|
-
out.push({ use: entry.use, kind: entry.kind, enabled: true, ok: true });
|
|
1999
|
-
} catch (e) {
|
|
2000
|
-
out.push({
|
|
2001
|
-
use: entry.use,
|
|
2002
|
-
kind: entry.kind,
|
|
2003
|
-
enabled: true,
|
|
2004
|
-
ok: false,
|
|
2005
|
-
error: e instanceof Error ? e.message : String(e)
|
|
2006
|
-
});
|
|
2007
|
-
}
|
|
2008
|
-
}
|
|
2009
|
-
return out;
|
|
2010
|
-
}
|
|
2011
|
-
async function readExtensionCss(projectDir, use) {
|
|
2012
|
-
const entry = await describeExtension(projectDir, use);
|
|
2013
|
-
if (!entry)
|
|
2014
|
-
throw new Error(`Extension "${use}" is not in the manifest.`);
|
|
2015
|
-
const bundledCss = entry.kind === "bundled" ? bundledExtension(entry.name)?.css : undefined;
|
|
2016
|
-
if (bundledCss !== undefined)
|
|
2017
|
-
return bundledCss;
|
|
2018
|
-
if (!entry.dir)
|
|
2019
|
-
throw new Error(`Extension "${use}" has no stylesheets to preview.`);
|
|
2020
|
-
const meta = await readExtensionMeta(entry.dir);
|
|
2021
|
-
const sheets = resolveExtension(entry.dir, meta, `Extension "${use}"`).styles ?? [];
|
|
2022
|
-
if (sheets.length === 0)
|
|
2023
|
-
throw new Error(`Extension "${use}" declares no stylesheets.`);
|
|
2024
|
-
const parts = [];
|
|
2025
|
-
for (const sheet of sheets)
|
|
2026
|
-
parts.push(await readFile5(sheet, "utf8"));
|
|
2027
|
-
return parts.join(`
|
|
2028
|
-
|
|
2029
|
-
`);
|
|
2030
|
-
}
|
|
2031
2080
|
|
|
2032
2081
|
// src/lib/extension-restore.ts
|
|
2033
2082
|
var OFFLINE_REASON = "you appear to be offline (npm can't be reached)";
|
|
@@ -2146,4 +2195,4 @@ async function restoreForCommand(dir, options) {
|
|
|
2146
2195
|
log.warn(problem);
|
|
2147
2196
|
}
|
|
2148
2197
|
|
|
2149
|
-
export {
|
|
2198
|
+
export { isPositivePoints, cssLength, formatPageSize, printAreaMeta, pageBoxes, judgeRect, PRESET_IDS, PRESETS, TARGETS, TARGET_IDS, publishTargetFor, resolveTargets, applyDefaultPdfStrictChecks, MANIFEST_FILENAMES, loadManifest, loadManifestWithPath, resolveConfig, resolveConfigForTarget, FriendlyHttpError, withFetchTimeout, loadManifestDoc, writeManifestDoc, npmRegistryUrl, ensureProjectGitignore, listProjectExtensions, setExtensionEnabled, removeExtension, addExtension, checkExtensionUpdates, updateExtensions, uniqueExtensionId, restorePinnedExtensions, restoreFailureMessage, restoreOfflineMessage, restoreForCommand };
|