gutterpress 0.11.23-alpha.2 → 0.11.23-alpha.3
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 +6 -7
- package/dist/{README-8ef336pp.md → README-8db7btxb.md} +13 -19
- package/dist/api/index.d.ts +1 -1
- package/dist/api/index.js +4 -4
- package/dist/{build-encgnv0c.js → build-m78jcpf7.js} +7 -7
- package/dist/{cli-xq6djqbj.js → cli-1h17ktsg.js} +84 -113
- package/dist/{cli-kh8v4vvw.js → cli-5jzyw06s.js} +1 -1
- package/dist/{cli-sdmv4bba.js → cli-h4x81x97.js} +112 -8
- package/dist/{cli-evg8sbht.js → cli-n2tsxqpn.js} +1 -1
- package/dist/{cli-aqh6brew.js → cli-s6djx4ma.js} +1 -1
- package/dist/{cli-pwwfxdgb.js → cli-t8be9yeb.js} +9 -20
- package/dist/{cli-pz4bn98t.js → cli-xsrffqzt.js} +19 -13
- package/dist/cli.js +12 -12
- package/dist/{doctor-5gtpgpd1.js → doctor-j71jqce3.js} +3 -3
- package/dist/engine/shared/gcpm-extract.d.ts +8 -0
- package/dist/engine/shared/print-area.d.ts +16 -4
- package/dist/{engine-tn13gk0b.js → engine-1r6q80tq.js} +2 -2
- package/dist/{engine-mc5br8g8.js → engine-m4y10shc.js} +1 -1
- package/dist/{ext-wn2a5afq.js → ext-fq2hg9va.js} +7 -7
- package/dist/{extension-restore-s3x1618g.js → extension-restore-9dh7c4tp.js} +2 -2
- package/dist/{extension-restore-g8jnmmzq.js → extension-restore-tmxtzkm0.js} +4 -4
- package/dist/{gutterpress-viewer-701vf4qp.js → gutterpress-viewer-mafsby5k.js} +9 -2
- package/dist/{index-2bjcghze.js → index-0wee4408.js} +9 -20
- package/dist/{index-x3ema2w3.js → index-7pck1q9c.js} +124 -17
- package/dist/{index-0skhjx3e.js → index-nedd07bk.js} +19 -13
- package/dist/{index-4x6y8krm.js → index-nvmf22rt.js} +1 -1
- package/dist/{index-j5z86r4a.js → index-prqvz3xm.js} +213 -276
- package/dist/index.js +5 -5
- package/dist/lib/extension-manager.d.ts +8 -7
- package/dist/lib/extension-manifest.d.ts +1 -13
- package/dist/lib/manifest.d.ts +15 -1
- package/dist/lib/markdown/assemble.d.ts +4 -3
- package/dist/lib/page-size.d.ts +34 -27
- package/dist/lib/printsafe.d.ts +1 -0
- package/dist/lib/project-templates.d.ts +9 -0
- package/dist/manifest-8afhrk30.yaml +19 -0
- package/dist/manifest-d4f9q79e.yaml +23 -0
- package/dist/{manifest-eagfhba6.yaml → manifest-gf13sjp8.yaml} +10 -2
- package/dist/manifest-my7mdv8j.yaml +23 -0
- package/dist/{manifest.schema-t7nx2stg.json → manifest.schema-650pe0d1.json} +15 -3
- package/dist/{new-mhs46pw3.js → new-s4zcaepg.js} +7 -7
- package/dist/{package-aenwjew3.json → package-awwkt7sa.json} +0 -1
- package/dist/{page-rules-nsj3aw42.css → page-rules-fj09xct5.css} +12 -40
- package/dist/{plugin.test.js-xgxrd8hf.tpl → plugin.test.js-gxzqqfdh.tpl} +0 -1
- package/dist/{plugins-1sxe0dkz.js → plugins-4vaf27n9.js} +3 -3
- package/dist/{plugins-2cek4mz1.js → plugins-80emnf31.js} +1 -1
- package/dist/{preflight-3k2b1x8e.js → preflight-c7w1xdn3.js} +7 -7
- package/dist/{preview-6p9v6rht.js → preview-mzytcwyk.js} +7 -7
- package/dist/{publish-qgsngy8s.js → publish-fez14ad4.js} +7 -7
- package/dist/render.js +24 -561
- package/dist/schema/manifest.types.d.ts +22 -0
- package/dist/{tokens-7984461t.css → tokens-ye64p899.css} +5 -12
- package/dist/{validate-0v7xw6wa.js → validate-p2chr6hr.js} +7 -7
- package/package.json +1 -1
- package/dist/manifest-n1gh3qw5.yaml +0 -9
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
DEBOUNCE,
|
|
3
3
|
FriendlyHttpError,
|
|
4
4
|
MANIFEST_FILENAMES,
|
|
5
|
+
MARGIN_EDGES,
|
|
5
6
|
PRESETS,
|
|
6
7
|
PRESET_IDS,
|
|
7
8
|
TARGETS,
|
|
@@ -9,25 +10,34 @@ import {
|
|
|
9
10
|
UsageError,
|
|
10
11
|
addExtension,
|
|
11
12
|
applyDefaultPdfStrictChecks,
|
|
13
|
+
cssLength,
|
|
12
14
|
ensureProjectGitignore,
|
|
13
|
-
ensureSeq,
|
|
14
15
|
extensionConfigFor,
|
|
16
|
+
formatPageSize,
|
|
17
|
+
isNonNegativePoints,
|
|
18
|
+
isPositivePoints,
|
|
19
|
+
judgeRect,
|
|
15
20
|
listProjectExtensions,
|
|
16
21
|
loadManifest,
|
|
17
22
|
loadManifestDoc,
|
|
18
23
|
loadManifestWithPath,
|
|
19
24
|
npmRegistryUrl,
|
|
25
|
+
pageBoxes,
|
|
26
|
+
printAreaMeta,
|
|
20
27
|
publishTargetFor,
|
|
28
|
+
readEntryCss,
|
|
21
29
|
resolveConfig,
|
|
22
30
|
resolveConfigForTarget,
|
|
23
31
|
resolvePort,
|
|
24
32
|
resolveTargets,
|
|
25
33
|
restoreForCommand,
|
|
34
|
+
round3,
|
|
26
35
|
scalarString,
|
|
27
36
|
uniqueExtensionId,
|
|
37
|
+
validatePageMargin,
|
|
28
38
|
withFetchTimeout,
|
|
29
39
|
writeManifestDoc
|
|
30
|
-
} from "./index-
|
|
40
|
+
} from "./index-7pck1q9c.js";
|
|
31
41
|
import {
|
|
32
42
|
EXTENSION_MANIFEST_FILENAME,
|
|
33
43
|
GUTTERPRESS_CSS,
|
|
@@ -63,18 +73,18 @@ import {
|
|
|
63
73
|
setLogLevel,
|
|
64
74
|
slugify,
|
|
65
75
|
warn
|
|
66
|
-
} from "./index-
|
|
76
|
+
} from "./index-0wee4408.js";
|
|
67
77
|
import {
|
|
68
78
|
blackTextToGray
|
|
69
79
|
} from "./index-ht1bcqdd.js";
|
|
70
80
|
import {
|
|
81
|
+
DEFAULT_PAGE_MARGIN_PT,
|
|
71
82
|
MARGIN_BOX_IGNORED_PROPERTIES,
|
|
72
83
|
extract,
|
|
73
84
|
getAssetPath,
|
|
74
85
|
lastPageMode,
|
|
75
|
-
parseSize,
|
|
76
86
|
resolvePage
|
|
77
|
-
} from "./index-
|
|
87
|
+
} from "./index-nedd07bk.js";
|
|
78
88
|
import {
|
|
79
89
|
BuildError
|
|
80
90
|
} from "./index-46ycxe6r.js";
|
|
@@ -185,95 +195,26 @@ function canonicalChapterId(p) {
|
|
|
185
195
|
return s;
|
|
186
196
|
}
|
|
187
197
|
|
|
188
|
-
// src/engine/shared/print-area.ts
|
|
189
|
-
function isPositivePoints(value) {
|
|
190
|
-
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
191
|
-
}
|
|
192
|
-
var round3 = (n) => Math.round(n * 1000) / 1000;
|
|
193
|
-
function cssLength(pt) {
|
|
194
|
-
const inches = round3(pt / 72);
|
|
195
|
-
return Math.abs(inches * 72 - pt) < 0.000001 ? `${inches}in` : `${round3(pt)}pt`;
|
|
196
|
-
}
|
|
197
|
-
function formatPageSize(page) {
|
|
198
|
-
return `${cssLength(page.width)} ${cssLength(page.height)}`;
|
|
199
|
-
}
|
|
200
|
-
function printAreaMeta(page) {
|
|
201
|
-
const area = JSON.stringify({
|
|
202
|
-
width: page.width,
|
|
203
|
-
height: page.height,
|
|
204
|
-
bleed: page.bleed ?? 0,
|
|
205
|
-
safe: page.safe ?? 0,
|
|
206
|
-
artSafe: page.artSafe,
|
|
207
|
-
gutter: page.gutter,
|
|
208
|
-
preset: page.preset,
|
|
209
|
-
spec: page.spec
|
|
210
|
-
});
|
|
211
|
-
return `<meta name="gp-print-area" content='${area.replace(/&/g, "&").replace(/'/g, "'")}'>`;
|
|
212
|
-
}
|
|
213
|
-
function pageBoxes(area, side, scale = 1) {
|
|
214
|
-
const w = area.width * scale;
|
|
215
|
-
const h = area.height * scale;
|
|
216
|
-
const b = Math.max(0, area.bleed) * scale;
|
|
217
|
-
const s = Math.max(0, area.safe) * scale;
|
|
218
|
-
const a = Math.max(0, area.artSafe) * scale;
|
|
219
|
-
const g = Math.max(0, area.gutter) * scale;
|
|
220
|
-
const [textLeft, textRight] = side === "verso" ? [s, g] : [g, s];
|
|
221
|
-
const [artLeft, artRight] = side === "verso" ? [a, g] : [g, a];
|
|
222
|
-
const trim = { x: side === "verso" ? b : 0, y: b, w: Math.max(0, w - b), h: Math.max(0, h - 2 * b) };
|
|
223
|
-
return {
|
|
224
|
-
sheet: { x: 0, y: 0, w, h },
|
|
225
|
-
trim,
|
|
226
|
-
safe: {
|
|
227
|
-
x: trim.x + textLeft,
|
|
228
|
-
y: trim.y + s,
|
|
229
|
-
w: Math.max(0, trim.w - textLeft - textRight),
|
|
230
|
-
h: Math.max(0, trim.h - 2 * s)
|
|
231
|
-
},
|
|
232
|
-
safeArt: {
|
|
233
|
-
x: trim.x + artLeft,
|
|
234
|
-
y: trim.y + a,
|
|
235
|
-
w: Math.max(0, trim.w - artLeft - artRight),
|
|
236
|
-
h: Math.max(0, trim.h - 2 * a)
|
|
237
|
-
},
|
|
238
|
-
bleed: b
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
var SEVERITY = { inside: 0, unsafe: 1, bleed: 2, "off-page": 3 };
|
|
242
|
-
function judgeRect(r, boxes, rule, tol = 0) {
|
|
243
|
-
const { sheet, trim } = boxes;
|
|
244
|
-
const safe = rule === "art" ? boxes.safeArt : boxes.safe;
|
|
245
|
-
const sides = [
|
|
246
|
-
["left", -r.x, -safe.x, -trim.x, -sheet.x],
|
|
247
|
-
["right", r.x + r.w, safe.x + safe.w, trim.x + trim.w, sheet.x + sheet.w],
|
|
248
|
-
["top", -r.y, -safe.y, -trim.y, -sheet.y],
|
|
249
|
-
["bottom", r.y + r.h, safe.y + safe.h, trim.y + trim.h, sheet.y + sheet.h]
|
|
250
|
-
];
|
|
251
|
-
let worst = { kind: "inside", gap: 0, need: 0, edge: null };
|
|
252
|
-
let beyond = 0;
|
|
253
|
-
for (const [edge, ink, limit, trimEdge, sheetEdge] of sides) {
|
|
254
|
-
const past = ink - limit;
|
|
255
|
-
if (past <= tol || rule === "art" && ink >= sheetEdge - tol)
|
|
256
|
-
continue;
|
|
257
|
-
const kind = ink > sheetEdge + tol ? "off-page" : ink > trimEdge + tol ? "bleed" : "unsafe";
|
|
258
|
-
if (SEVERITY[kind] > SEVERITY[worst.kind] || kind === worst.kind && past > beyond) {
|
|
259
|
-
worst = { kind, gap: trimEdge - ink, need: trimEdge - limit, edge };
|
|
260
|
-
beyond = past;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
return worst;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
198
|
// src/lib/markdown/assemble.ts
|
|
267
|
-
function
|
|
199
|
+
function pageGeometryCss(page) {
|
|
268
200
|
if (!page || !isPositivePoints(page.width) || !isPositivePoints(page.height))
|
|
269
201
|
return null;
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
202
|
+
const size = `size: ${formatPageSize(page)};`;
|
|
203
|
+
const m = page.margin;
|
|
204
|
+
if (!m)
|
|
205
|
+
return `@page { ${size} }`;
|
|
206
|
+
const [top, bottom, inside, outside] = [m.top, m.bottom, m.inside, m.outside].map(cssLength);
|
|
207
|
+
const recto = `margin: ${top} ${outside} ${bottom} ${inside};`;
|
|
208
|
+
const verso = `margin: ${top} ${inside} ${bottom} ${outside};`;
|
|
209
|
+
return [`@page { ${size} ${recto} }`, `@page :left { ${verso} }`, `@page :right { ${recto} }`].join(`
|
|
210
|
+
`);
|
|
211
|
+
}
|
|
212
|
+
function defaultPageMarginCss(page) {
|
|
213
|
+
if (!page || page.margin)
|
|
274
214
|
return null;
|
|
275
|
-
|
|
276
|
-
|
|
215
|
+
return `@layer gp.vocab {
|
|
216
|
+
@page { margin: ${cssLength(DEFAULT_PAGE_MARGIN_PT)}; }
|
|
217
|
+
}`;
|
|
277
218
|
}
|
|
278
219
|
async function assembleBookHtml(opts) {
|
|
279
220
|
const title = opts.title ?? "Document";
|
|
@@ -313,8 +254,8 @@ async function assembleBookHtml(opts) {
|
|
|
313
254
|
imageRefs.add(ref);
|
|
314
255
|
opts.onImageRefs([...imageRefs]);
|
|
315
256
|
}
|
|
316
|
-
const
|
|
317
|
-
|
|
257
|
+
const pageGeometry = pageGeometryCss(opts.printArea);
|
|
258
|
+
const defaultMargin = defaultPageMarginCss(opts.printArea);
|
|
318
259
|
const inlineCss = [
|
|
319
260
|
"@layer gp.marker, gp.vocab;",
|
|
320
261
|
`/* gutterpress markers */
|
|
@@ -326,14 +267,16 @@ ${TWO_VERSIONS_CSS.trim()}
|
|
|
326
267
|
@layer gp.vocab {
|
|
327
268
|
${GUTTERPRESS_CSS.trim()}
|
|
328
269
|
}`,
|
|
329
|
-
|
|
330
|
-
${
|
|
270
|
+
defaultMargin ? `/* page margins (default) */
|
|
271
|
+
${defaultMargin}` : null,
|
|
331
272
|
pluginCss ? `/* extension css */
|
|
332
273
|
${pluginCss.trim()}` : null,
|
|
333
274
|
`/* column alignment */
|
|
334
275
|
${TABLE_ALIGN_CSS.trim()}`,
|
|
335
276
|
projectCss ? `/* project css */
|
|
336
|
-
${projectCss.trim()}` : null
|
|
277
|
+
${projectCss.trim()}` : null,
|
|
278
|
+
pageGeometry ? `/* page geometry (manifest) */
|
|
279
|
+
${pageGeometry}` : null
|
|
337
280
|
].filter(Boolean).join(`
|
|
338
281
|
|
|
339
282
|
`);
|
|
@@ -2833,6 +2776,7 @@ var ruleRiskyProps = "printsafe/no-risky-print-effects";
|
|
|
2833
2776
|
var ruleSyntax = "printsafe/syntax-error";
|
|
2834
2777
|
var rulePageContainment = "printsafe/page-containment";
|
|
2835
2778
|
var rulePreviewCannotFollow = "printsafe/preview-cannot-follow";
|
|
2779
|
+
var rulePageSizeInStylesheet = "printsafe/page-size-in-stylesheet";
|
|
2836
2780
|
function extractUrls(value) {
|
|
2837
2781
|
const urls = [];
|
|
2838
2782
|
const re = /url\(\s*(['"]?)(.*?)\1\s*\)/gi;
|
|
@@ -2881,6 +2825,12 @@ function isInPageBox(decl) {
|
|
|
2881
2825
|
const page = decl.parent;
|
|
2882
2826
|
return !!page && page.type === "atrule" && page.name.toLowerCase() === "page";
|
|
2883
2827
|
}
|
|
2828
|
+
function isInBookPageRule(decl) {
|
|
2829
|
+
if (!isInPageBox(decl))
|
|
2830
|
+
return false;
|
|
2831
|
+
const params = decl.parent.params.trim();
|
|
2832
|
+
return params === "" || /^(:[a-z-]+\s*)+$/i.test(params);
|
|
2833
|
+
}
|
|
2884
2834
|
function isDroppedPageGradient(decl) {
|
|
2885
2835
|
const prop = decl.prop.toLowerCase();
|
|
2886
2836
|
if (prop !== "background" && prop !== "background-image")
|
|
@@ -3120,6 +3070,15 @@ function checkCssRaw(css, from) {
|
|
|
3120
3070
|
root.walkAtRules((at) => reportRemoteUrls(at.params || "", at));
|
|
3121
3071
|
root.walkDecls((decl) => {
|
|
3122
3072
|
const prop = decl.prop.toLowerCase();
|
|
3073
|
+
if (prop === "size" && isInBookPageRule(decl)) {
|
|
3074
|
+
warnings.push({
|
|
3075
|
+
rule: rulePageSizeInStylesheet,
|
|
3076
|
+
severity: "warning",
|
|
3077
|
+
message: `"size" in a stylesheet's @page rule is ignored: the page size comes from the manifest (preset:, or page: width and height — Setup > Details in the app), which is written after every stylesheet. Remove this declaration; to print at another size, change the manifest.`,
|
|
3078
|
+
...nodeLoc(decl)
|
|
3079
|
+
});
|
|
3080
|
+
return;
|
|
3081
|
+
}
|
|
3123
3082
|
if (isInertValue(prop, decl.value))
|
|
3124
3083
|
return;
|
|
3125
3084
|
if (marginBoxIgnoredProperties.has(prop) && isInPageMarginBox(decl)) {
|
|
@@ -5669,7 +5628,7 @@ class PdfOutput {
|
|
|
5669
5628
|
const rawPdf = pdfxMode ? path7.join(stage, "raw.pdf") : path7.resolve(pdfFile);
|
|
5670
5629
|
await fsp2.mkdir(path7.dirname(path7.resolve(pdfFile)), { recursive: true });
|
|
5671
5630
|
log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
|
|
5672
|
-
const { buildNativePdf } = await import("./engine-
|
|
5631
|
+
const { buildNativePdf } = await import("./engine-1r6q80tq.js");
|
|
5673
5632
|
const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
|
|
5674
5633
|
title: config.title,
|
|
5675
5634
|
author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
|
|
@@ -7206,20 +7165,18 @@ async function getSystemDiagnostics() {
|
|
|
7206
7165
|
};
|
|
7207
7166
|
}
|
|
7208
7167
|
// src/lib/project-scaffold.ts
|
|
7209
|
-
import { access, copyFile, cp, mkdir as
|
|
7168
|
+
import { access, copyFile, cp, mkdir as mkdir5, readdir as readdir6, readFile as readFile25, stat as stat4, writeFile as writeFile7 } from "node:fs/promises";
|
|
7210
7169
|
import { constants as FS, existsSync as existsSync9 } from "node:fs";
|
|
7211
7170
|
import path14 from "node:path";
|
|
7212
7171
|
|
|
7213
7172
|
// src/lib/page-size.ts
|
|
7214
7173
|
import { existsSync as existsSync8 } from "node:fs";
|
|
7215
|
-
import {
|
|
7174
|
+
import { readFile as readFile24 } from "node:fs/promises";
|
|
7216
7175
|
import path13 from "node:path";
|
|
7217
|
-
import
|
|
7218
|
-
import { isMap, Scalar } from "yaml";
|
|
7176
|
+
import { isMap } from "yaml";
|
|
7219
7177
|
function writePageBounds(doc, page) {
|
|
7220
7178
|
const tolerance = page.tolerance ?? numberAt(doc, ["page", "tolerance"]);
|
|
7221
|
-
|
|
7222
|
-
doc.set("page", doc.createNode({}));
|
|
7179
|
+
ensurePageMap(doc);
|
|
7223
7180
|
doc.setIn(["page", "width"], page.width);
|
|
7224
7181
|
doc.setIn(["page", "height"], page.height);
|
|
7225
7182
|
if (tolerance !== undefined)
|
|
@@ -7236,6 +7193,17 @@ function deletePageBounds(doc) {
|
|
|
7236
7193
|
if (block.items.length === 0)
|
|
7237
7194
|
doc.delete("page");
|
|
7238
7195
|
}
|
|
7196
|
+
function writePageMargin(doc, margin) {
|
|
7197
|
+
ensurePageMap(doc);
|
|
7198
|
+
if (!isMap(doc.getIn(["page", "margin"], true)))
|
|
7199
|
+
doc.setIn(["page", "margin"], doc.createNode({}));
|
|
7200
|
+
for (const edge of MARGIN_EDGES)
|
|
7201
|
+
doc.setIn(["page", "margin", edge], margin[edge]);
|
|
7202
|
+
}
|
|
7203
|
+
function ensurePageMap(doc) {
|
|
7204
|
+
if (!isMap(doc.get("page", true)))
|
|
7205
|
+
doc.set("page", doc.createNode({}));
|
|
7206
|
+
}
|
|
7239
7207
|
function numberAt(doc, keyPath) {
|
|
7240
7208
|
const v = doc.getIn(keyPath);
|
|
7241
7209
|
return isPositivePoints(v) ? v : undefined;
|
|
@@ -7254,132 +7222,95 @@ function pageSizeForChoice(choice) {
|
|
|
7254
7222
|
const base = PRESETS[choice.preset].page;
|
|
7255
7223
|
return { width: base.width, height: base.height };
|
|
7256
7224
|
}
|
|
7257
|
-
|
|
7258
|
-
function sameSize(a, b) {
|
|
7259
|
-
return Math.abs(a.width - b.width) < SAME_SIZE_PT && Math.abs(a.height - b.height) < SAME_SIZE_PT;
|
|
7260
|
-
}
|
|
7261
|
-
function plainPageRules(root) {
|
|
7262
|
-
const rules = [];
|
|
7263
|
-
root.walkAtRules("page", (rule) => {
|
|
7264
|
-
if (rule.params.trim() === "")
|
|
7265
|
-
rules.push(rule);
|
|
7266
|
-
});
|
|
7267
|
-
return rules;
|
|
7268
|
-
}
|
|
7269
|
-
function sizeDeclsOf(rule) {
|
|
7270
|
-
const decls = [];
|
|
7271
|
-
rule.each((node) => {
|
|
7272
|
-
if (node.type === "decl" && node.prop.toLowerCase() === "size")
|
|
7273
|
-
decls.push(node);
|
|
7274
|
-
});
|
|
7275
|
-
return decls;
|
|
7276
|
-
}
|
|
7277
|
-
function readPageSizeFromCss(css) {
|
|
7278
|
-
let root;
|
|
7279
|
-
try {
|
|
7280
|
-
root = postcss5.parse(css);
|
|
7281
|
-
} catch {
|
|
7282
|
-
return null;
|
|
7283
|
-
}
|
|
7284
|
-
const decls = plainPageRules(root).flatMap(sizeDeclsOf);
|
|
7285
|
-
const last = decls[decls.length - 1];
|
|
7286
|
-
return last ? parseSize(last.value) ?? null : null;
|
|
7287
|
-
}
|
|
7288
|
-
function setPageSizeInCss(css, page) {
|
|
7289
|
-
const root = postcss5.parse(css);
|
|
7290
|
-
const decls = plainPageRules(root).flatMap(sizeDeclsOf);
|
|
7291
|
-
const last = decls[decls.length - 1];
|
|
7292
|
-
const value = formatPageSize(page);
|
|
7293
|
-
if (last) {
|
|
7294
|
-
const current = parseSize(last.value);
|
|
7295
|
-
if (current && sameSize(current, page))
|
|
7296
|
-
return css;
|
|
7297
|
-
last.value = value;
|
|
7298
|
-
return root.toString();
|
|
7299
|
-
}
|
|
7300
|
-
const rule = `@page {
|
|
7301
|
-
size: ${value};
|
|
7302
|
-
}
|
|
7303
|
-
`;
|
|
7304
|
-
if (css.trim() === "")
|
|
7305
|
-
return css + rule;
|
|
7306
|
-
return `${css}${css.endsWith(`
|
|
7307
|
-
`) ? "" : `
|
|
7308
|
-
`}
|
|
7309
|
-
${rule}`;
|
|
7310
|
-
}
|
|
7311
|
-
async function ownStylesheets(projectDir) {
|
|
7312
|
-
const rels = await resolveActiveStyles(projectDir).catch(() => []);
|
|
7313
|
-
return rels.map((rel) => path13.resolve(projectDir, rel)).filter((abs) => {
|
|
7314
|
-
const inside = path13.relative(projectDir, abs);
|
|
7315
|
-
return !inside.startsWith("..") && !path13.isAbsolute(inside) && existsSync8(abs);
|
|
7316
|
-
});
|
|
7317
|
-
}
|
|
7318
|
-
var relDisplay2 = (projectDir, abs) => path13.relative(projectDir, abs).split(path13.sep).join("/");
|
|
7319
|
-
async function findCssSize(projectDir, sheets) {
|
|
7320
|
-
let found = null;
|
|
7321
|
-
for (const file of sheets) {
|
|
7322
|
-
const size2 = readPageSizeFromCss(await readFile24(file, "utf8"));
|
|
7323
|
-
if (size2)
|
|
7324
|
-
found = { file, size: size2 };
|
|
7325
|
-
}
|
|
7326
|
-
return found;
|
|
7327
|
-
}
|
|
7328
|
-
async function readPageSetup(projectDir) {
|
|
7329
|
-
const { doc } = await loadManifestDoc(projectDir);
|
|
7225
|
+
function manifestGeometry(doc) {
|
|
7330
7226
|
const declared = doc.get("preset");
|
|
7331
7227
|
const preset = declared === undefined || declared === null ? "dtrpg" : PRESET_IDS.includes(String(declared)) ? declared : null;
|
|
7332
7228
|
const base = preset ? PRESETS[preset].page : null;
|
|
7333
7229
|
const width = numberAt(doc, ["page", "width"]) ?? base?.width;
|
|
7334
7230
|
const height = numberAt(doc, ["page", "height"]) ?? base?.height;
|
|
7335
7231
|
const tolerance = numberAt(doc, ["page", "tolerance"]) ?? base?.tolerance ?? 0.5;
|
|
7336
|
-
const
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
|
|
7232
|
+
const bounds = width !== undefined && height !== undefined ? { width, height, tolerance } : null;
|
|
7233
|
+
const at = (edge) => doc.getIn(["page", "margin", edge]);
|
|
7234
|
+
const margins = MARGIN_EDGES.every((edge) => isNonNegativePoints(at(edge))) ? { top: at("top"), bottom: at("bottom"), inside: at("inside"), outside: at("outside") } : undefined;
|
|
7235
|
+
return { preset, bounds, ...margins ? { margins } : {} };
|
|
7236
|
+
}
|
|
7237
|
+
async function stylesheetMargins(projectDir, manifestStyles) {
|
|
7238
|
+
const d = DEFAULT_PAGE_MARGIN_PT;
|
|
7239
|
+
const fallback = {
|
|
7240
|
+
margins: { top: d, bottom: d, inside: d, outside: d },
|
|
7241
|
+
marginsFrom: "default"
|
|
7341
7242
|
};
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
const
|
|
7347
|
-
const
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7243
|
+
const [entries, rels] = await Promise.all([
|
|
7244
|
+
listProjectExtensions(projectDir).catch(() => []),
|
|
7245
|
+
resolveActiveStyles(projectDir, manifestStyles).catch(() => [])
|
|
7246
|
+
]);
|
|
7247
|
+
const sheets = rels.map((rel) => path13.resolve(projectDir, rel)).filter((abs) => existsSync8(abs));
|
|
7248
|
+
const parts = await Promise.all([
|
|
7249
|
+
...entries.filter((e) => e.enabled && e.carries.styles).map((e) => readEntryCss(e).catch(() => "")),
|
|
7250
|
+
...sheets.map((file) => readFile24(file, "utf8").catch(() => ""))
|
|
7251
|
+
]);
|
|
7351
7252
|
try {
|
|
7352
|
-
|
|
7353
|
-
|
|
7354
|
-
|
|
7253
|
+
const page = resolvePage(extract(parts.join(`
|
|
7254
|
+
|
|
7255
|
+
`)), { pseudos: ["right"] });
|
|
7256
|
+
const declared = Object.keys(page.decls).some((prop) => prop === "margin" || prop.startsWith("margin-"));
|
|
7257
|
+
if (!declared)
|
|
7258
|
+
return fallback;
|
|
7259
|
+
const m = page.geometry.margin;
|
|
7260
|
+
return {
|
|
7261
|
+
margins: { top: round3(m.top), bottom: round3(m.bottom), inside: round3(m.left), outside: round3(m.right) },
|
|
7262
|
+
marginsFrom: "stylesheet"
|
|
7263
|
+
};
|
|
7264
|
+
} catch {
|
|
7265
|
+
return fallback;
|
|
7355
7266
|
}
|
|
7267
|
+
}
|
|
7268
|
+
async function setupOf(projectDir, doc) {
|
|
7269
|
+
const { margins, ...geometry } = manifestGeometry(doc);
|
|
7270
|
+
if (margins)
|
|
7271
|
+
return { ...geometry, margins, marginsFrom: "manifest" };
|
|
7272
|
+
const styles = doc.toJS()?.styles;
|
|
7273
|
+
return { ...geometry, ...await stylesheetMargins(projectDir, Array.isArray(styles) ? styles : undefined) };
|
|
7274
|
+
}
|
|
7275
|
+
async function readPageSetup(projectDir) {
|
|
7276
|
+
const { doc } = await loadManifestDoc(projectDir);
|
|
7277
|
+
return setupOf(projectDir, doc);
|
|
7278
|
+
}
|
|
7279
|
+
async function setPageSetup(projectDir, change) {
|
|
7356
7280
|
const { doc, file } = await loadManifestDoc(projectDir);
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
7361
|
-
|
|
7362
|
-
|
|
7363
|
-
|
|
7281
|
+
const size2 = change.size ? pageSizeForChoice(change.size) : null;
|
|
7282
|
+
let margins;
|
|
7283
|
+
if (change.margins !== undefined) {
|
|
7284
|
+
const against = size2 ?? manifestGeometry(doc).bounds;
|
|
7285
|
+
if (!against)
|
|
7286
|
+
throw new UsageError("Choose a page size before setting margins: the manifest records none.");
|
|
7287
|
+
margins = validatePageMargin(change.margins, against);
|
|
7288
|
+
}
|
|
7289
|
+
if (change.size && size2) {
|
|
7290
|
+
doc.set("preset", change.size.preset);
|
|
7291
|
+
if (change.size.preset === "custom")
|
|
7292
|
+
writePageBounds(doc, size2);
|
|
7293
|
+
else
|
|
7294
|
+
deletePageBounds(doc);
|
|
7364
7295
|
}
|
|
7296
|
+
if (margins)
|
|
7297
|
+
writePageMargin(doc, margins);
|
|
7365
7298
|
await writeManifestDoc(file, doc);
|
|
7366
|
-
|
|
7367
|
-
await mkdir5(path13.dirname(target), { recursive: true });
|
|
7368
|
-
await writeFile7(target, after, "utf8");
|
|
7369
|
-
}
|
|
7370
|
-
return readPageSetup(projectDir);
|
|
7299
|
+
return setupOf(projectDir, doc);
|
|
7371
7300
|
}
|
|
7372
7301
|
|
|
7373
7302
|
// src/lib/project-scaffold.ts
|
|
7374
7303
|
function starterOverridesCss() {
|
|
7375
7304
|
return `/**
|
|
7376
|
-
* Your book's own styles.
|
|
7305
|
+
* Your book's own styles. Rules here win over your look's.
|
|
7377
7306
|
*
|
|
7378
|
-
*
|
|
7379
|
-
*
|
|
7380
|
-
*
|
|
7381
|
-
*
|
|
7382
|
-
*
|
|
7307
|
+
* In the app you rarely need this file: Setup > Looks & features adds a
|
|
7308
|
+
* look, Setup > Design changes its fonts, colors and sizes (those changes
|
|
7309
|
+
* are saved here as :root custom properties), and Setup > Details sets the
|
|
7310
|
+
* page size and margins (in the manifest).
|
|
7311
|
+
*
|
|
7312
|
+
* To change the look from the command line: gutterpress ext remove <old>
|
|
7313
|
+
* <book>, then gutterpress ext add <look> <book>.
|
|
7383
7314
|
*/
|
|
7384
7315
|
`;
|
|
7385
7316
|
}
|
|
@@ -7462,7 +7393,7 @@ async function scaffoldProject(options) {
|
|
|
7462
7393
|
const preset = options.preset === undefined ? undefined : requirePreset(options.preset, options.customPage);
|
|
7463
7394
|
const targets = preset ? resolveScaffoldTargets(options.targets, preset) : undefined;
|
|
7464
7395
|
try {
|
|
7465
|
-
await
|
|
7396
|
+
await mkdir5(projectDir, { recursive: true });
|
|
7466
7397
|
if (customTemplateDir) {
|
|
7467
7398
|
const entries = await readdir6(customTemplateDir, { withFileTypes: true });
|
|
7468
7399
|
for (const entry of entries) {
|
|
@@ -7470,15 +7401,15 @@ async function scaffoldProject(options) {
|
|
|
7470
7401
|
continue;
|
|
7471
7402
|
await cp(path14.join(customTemplateDir, entry.name), path14.join(projectDir, entry.name), { recursive: true });
|
|
7472
7403
|
}
|
|
7473
|
-
await
|
|
7404
|
+
await mkdir5(path14.join(projectDir, "assets"), { recursive: true });
|
|
7474
7405
|
} else {
|
|
7475
7406
|
const tplManifest = await getAssetPath(`templates/${template}/manifest.yaml`);
|
|
7476
7407
|
const tplChapter = await getAssetPath(`templates/${template}/chapter-01.md`);
|
|
7477
|
-
await
|
|
7408
|
+
await mkdir5(path14.join(projectDir, "assets"), { recursive: true });
|
|
7478
7409
|
await copyFile(tplManifest, path14.join(projectDir, MANIFEST_FILENAMES[0]));
|
|
7479
7410
|
await copyFile(tplChapter, path14.join(projectDir, "chapter-01.md"));
|
|
7480
|
-
await
|
|
7481
|
-
await
|
|
7411
|
+
await mkdir5(path14.join(projectDir, "styles"), { recursive: true });
|
|
7412
|
+
await writeFile7(path14.join(projectDir, "styles", "book.css"), starterOverridesCss(), "utf8");
|
|
7482
7413
|
}
|
|
7483
7414
|
} catch (e) {
|
|
7484
7415
|
throw new CreateProjectErrorImpl("scaffold-io", `Could not create the book files: ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -7502,6 +7433,8 @@ async function scaffoldProject(options) {
|
|
|
7502
7433
|
if (preset) {
|
|
7503
7434
|
doc.set("preset", preset);
|
|
7504
7435
|
doc.set("targets", doc.createNode(targets ?? []));
|
|
7436
|
+
if (preset !== "custom")
|
|
7437
|
+
deletePageBounds(doc);
|
|
7505
7438
|
}
|
|
7506
7439
|
if (options.customPage)
|
|
7507
7440
|
writePageBounds(doc, options.customPage);
|
|
@@ -7579,10 +7512,10 @@ async function adoptFolder(options) {
|
|
|
7579
7512
|
await fillTemplateFile(path14.join(dir, "chapter-01.md"), { "{{TITLE}}": title }).catch(() => {});
|
|
7580
7513
|
mdFiles = ["chapter-01.md"];
|
|
7581
7514
|
}
|
|
7582
|
-
await
|
|
7515
|
+
await mkdir5(path14.join(dir, "styles"), { recursive: true });
|
|
7583
7516
|
const bookCssPath = path14.join(dir, "styles", "book.css");
|
|
7584
7517
|
if (!existsSync9(bookCssPath)) {
|
|
7585
|
-
await
|
|
7518
|
+
await writeFile7(bookCssPath, starterOverridesCss(), "utf8");
|
|
7586
7519
|
}
|
|
7587
7520
|
const filesYaml = mdFiles.map((f) => ` - "${escapeYamlScalar(f)}"`).join(`
|
|
7588
7521
|
`);
|
|
@@ -7598,8 +7531,8 @@ ${filesYaml}
|
|
|
7598
7531
|
styles:
|
|
7599
7532
|
- styles/book.css
|
|
7600
7533
|
`;
|
|
7601
|
-
await
|
|
7602
|
-
await
|
|
7534
|
+
await writeFile7(path14.join(dir, MANIFEST_FILENAMES[0]), manifest, "utf8");
|
|
7535
|
+
await mkdir5(path14.join(dir, "assets"), { recursive: true });
|
|
7603
7536
|
await ensureProjectGitignore(dir);
|
|
7604
7537
|
} catch (e) {
|
|
7605
7538
|
if (e instanceof CreateProjectErrorImpl)
|
|
@@ -7653,10 +7586,10 @@ async function fillTemplateFile(filePath, substitutions) {
|
|
|
7653
7586
|
for (const [token, value] of Object.entries(substitutions)) {
|
|
7654
7587
|
text = text.split(token).join(value);
|
|
7655
7588
|
}
|
|
7656
|
-
await
|
|
7589
|
+
await writeFile7(filePath, text, "utf8");
|
|
7657
7590
|
}
|
|
7658
7591
|
// src/lib/extension-scaffold.ts
|
|
7659
|
-
import { access as access2, mkdir as
|
|
7592
|
+
import { access as access2, mkdir as mkdir6, readFile as readFile26, writeFile as writeFile8 } from "node:fs/promises";
|
|
7660
7593
|
import { constants as FS2 } from "node:fs";
|
|
7661
7594
|
import path15 from "node:path";
|
|
7662
7595
|
var EXTENSION_KINDS = ["plugin", "look"];
|
|
@@ -7768,14 +7701,14 @@ async function scaffoldExtension(options) {
|
|
|
7768
7701
|
const entries = TEMPLATE_FILES[kind];
|
|
7769
7702
|
const written = [];
|
|
7770
7703
|
try {
|
|
7771
|
-
await
|
|
7704
|
+
await mkdir6(extensionDir, { recursive: true });
|
|
7772
7705
|
for (const [assetName, relDest] of entries) {
|
|
7773
7706
|
const src = await getAssetPath(`extension-templates/${kind}/${assetName}`);
|
|
7774
7707
|
const dest = path15.join(extensionDir, relDest);
|
|
7775
|
-
await
|
|
7708
|
+
await mkdir6(path15.dirname(dest), { recursive: true });
|
|
7776
7709
|
const text = await readFile26(src, "utf8");
|
|
7777
7710
|
const table = relDest.endsWith(".json") ? jsonSafe : plain;
|
|
7778
|
-
await
|
|
7711
|
+
await writeFile8(dest, substitute(text, table), "utf8");
|
|
7779
7712
|
written.push(relDest);
|
|
7780
7713
|
}
|
|
7781
7714
|
} catch (e) {
|
|
@@ -7799,7 +7732,7 @@ function substitute(text, table) {
|
|
|
7799
7732
|
return out;
|
|
7800
7733
|
}
|
|
7801
7734
|
// src/lib/project-templates.ts
|
|
7802
|
-
import { cp as cp2, mkdir as
|
|
7735
|
+
import { cp as cp2, mkdir as mkdir7, readFile as readFile27, readdir as readdir7, stat as stat5, writeFile as writeFile9 } from "node:fs/promises";
|
|
7803
7736
|
import { constants as FS3, existsSync as existsSync10 } from "node:fs";
|
|
7804
7737
|
import { access as access3 } from "node:fs/promises";
|
|
7805
7738
|
import path16 from "node:path";
|
|
@@ -7822,6 +7755,10 @@ async function readTemplateChoices(manifestPath) {
|
|
|
7822
7755
|
if (isSeq(targets)) {
|
|
7823
7756
|
out.targets = targets.items.map((i) => scalarString(i)).filter((s) => s !== null);
|
|
7824
7757
|
}
|
|
7758
|
+
const width = numberAt(doc, ["page", "width"]);
|
|
7759
|
+
const height = numberAt(doc, ["page", "height"]);
|
|
7760
|
+
if (width !== undefined && height !== undefined)
|
|
7761
|
+
out.page = { width, height };
|
|
7825
7762
|
return out;
|
|
7826
7763
|
} catch {
|
|
7827
7764
|
return {};
|
|
@@ -7830,19 +7767,19 @@ async function readTemplateChoices(manifestPath) {
|
|
|
7830
7767
|
var BUILT_IN_META = {
|
|
7831
7768
|
book: {
|
|
7832
7769
|
label: "Book",
|
|
7833
|
-
description: "A clean starting point for a novel, memoir, or any long-form book."
|
|
7770
|
+
description: "A clean starting point for a novel, memoir, or any long-form book. Uses the Clean book look."
|
|
7834
7771
|
},
|
|
7835
7772
|
zine: {
|
|
7836
7773
|
label: "Zine",
|
|
7837
|
-
description: "A short, personal zine made to be printed, folded, and shared."
|
|
7774
|
+
description: "A short, personal zine made to be printed, folded, and shared. Uses the Zine look."
|
|
7838
7775
|
},
|
|
7839
7776
|
technical: {
|
|
7840
7777
|
label: "Technical document",
|
|
7841
|
-
description: "A manual or guide with steps, reference tables, and code examples."
|
|
7778
|
+
description: "A manual or guide with steps, reference tables, and code examples. Uses the Technical doc look."
|
|
7842
7779
|
},
|
|
7843
7780
|
paper: {
|
|
7844
7781
|
label: "Academic paper",
|
|
7845
|
-
description: "A journal-style article with LaTeX math, numbered equations, figures, tables, notes and references."
|
|
7782
|
+
description: "A journal-style article with LaTeX math, numbered equations, figures, tables, notes and references. Uses the Academic look."
|
|
7846
7783
|
}
|
|
7847
7784
|
};
|
|
7848
7785
|
async function listBuiltInTemplates() {
|
|
@@ -7939,7 +7876,7 @@ async function reconcileSharedRefs(templateDir, sourceProjectDir, mode) {
|
|
|
7939
7876
|
const vendorDir = pickVendorDir(templateDir, base);
|
|
7940
7877
|
await Promise.all(externalFiles.filter((abs) => existsSync10(abs)).map(async (abs) => {
|
|
7941
7878
|
const dest = path16.join(templateDir, vendorDir, path16.relative(base, abs));
|
|
7942
|
-
await
|
|
7879
|
+
await mkdir7(path16.dirname(dest), { recursive: true });
|
|
7943
7880
|
await cp2(abs, dest, { recursive: true });
|
|
7944
7881
|
}));
|
|
7945
7882
|
const bookLocal = (value) => toPosixPath(path16.join(vendorDir, path16.relative(base, path16.resolve(sourceProjectDir, value))));
|
|
@@ -7972,7 +7909,7 @@ async function saveProjectAsTemplate(options) {
|
|
|
7972
7909
|
if (exists) {
|
|
7973
7910
|
throw new Error(`A template named "${name}" already exists. Choose a different name.`);
|
|
7974
7911
|
}
|
|
7975
|
-
await
|
|
7912
|
+
await mkdir7(dir, { recursive: true });
|
|
7976
7913
|
const entries = await readdir7(projectDir, { withFileTypes: true });
|
|
7977
7914
|
for (const entry of entries) {
|
|
7978
7915
|
if (SKIP_ENTRIES.has(entry.name))
|
|
@@ -7985,7 +7922,7 @@ async function saveProjectAsTemplate(options) {
|
|
|
7985
7922
|
const shared = manifestName ? await reconcileSharedRefs(dir, projectDir, options.sharedRefs ?? "vendor") : { vendoredRefs: [], excludedRefs: [] };
|
|
7986
7923
|
if (manifestName)
|
|
7987
7924
|
await retokeniseManifest(path16.join(dir, manifestName));
|
|
7988
|
-
await
|
|
7925
|
+
await writeFile9(path16.join(dir, TEMPLATE_META_FILE), JSON.stringify({ label: name }, null, 2), "utf8");
|
|
7989
7926
|
return {
|
|
7990
7927
|
id,
|
|
7991
7928
|
label: name,
|
|
@@ -8003,7 +7940,7 @@ async function retokeniseManifest(manifestPath) {
|
|
|
8003
7940
|
return;
|
|
8004
7941
|
}
|
|
8005
7942
|
text = text.replace(/^title:\s*.*$/m, 'title: "{{TITLE}}"').replace(/^(authors:[^\n]*\n[ \t]*-[ \t]*).*$/m, '$1"{{AUTHOR}}"');
|
|
8006
|
-
await
|
|
7943
|
+
await writeFile9(manifestPath, text, "utf8");
|
|
8007
7944
|
}
|
|
8008
7945
|
async function listCustomTemplates(templatesRoot) {
|
|
8009
7946
|
let entries;
|
|
@@ -8045,7 +7982,7 @@ async function importTemplateFromFolder(options) {
|
|
|
8045
7982
|
return saveProjectAsTemplate({ projectDir: sourceDir, name, templatesRoot });
|
|
8046
7983
|
}
|
|
8047
7984
|
// src/lib/snippets.ts
|
|
8048
|
-
import { readdir as readdir8, readFile as readFile28, writeFile as
|
|
7985
|
+
import { readdir as readdir8, readFile as readFile28, writeFile as writeFile10, mkdir as mkdir8, rm } from "node:fs/promises";
|
|
8049
7986
|
import path17 from "node:path";
|
|
8050
7987
|
var SNIPPETS_DIR = "snippets";
|
|
8051
7988
|
var LEVEL_RANK = { project: 0, extension: 1, core: 2 };
|
|
@@ -8110,8 +8047,8 @@ async function saveSnippet(projectDir, name, body) {
|
|
|
8110
8047
|
throw new Error(`Could not derive a filename from "${name}".`);
|
|
8111
8048
|
const fileName = `${stem}.md`;
|
|
8112
8049
|
const dir = path17.join(projectDir, SNIPPETS_DIR);
|
|
8113
|
-
await
|
|
8114
|
-
await
|
|
8050
|
+
await mkdir8(dir, { recursive: true });
|
|
8051
|
+
await writeFile10(resolveSnippetPath(projectDir, fileName), body, "utf8");
|
|
8115
8052
|
return { name, fileName, variables: extractVariables(body), body, source: { kind: "project" } };
|
|
8116
8053
|
}
|
|
8117
8054
|
async function deleteSnippet(projectDir, fileName) {
|
|
@@ -8244,7 +8181,7 @@ async function listLocationVariants(projectDir) {
|
|
|
8244
8181
|
}
|
|
8245
8182
|
// src/lib/extension-import.ts
|
|
8246
8183
|
import { existsSync as existsSync11 } from "node:fs";
|
|
8247
|
-
import { cp as cp3, mkdir as
|
|
8184
|
+
import { cp as cp3, mkdir as mkdir9, mkdtemp, readFile as readFile29, rm as rm2, writeFile as writeFile11 } from "node:fs/promises";
|
|
8248
8185
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
8249
8186
|
import path18 from "node:path";
|
|
8250
8187
|
import { unzipSync } from "fflate";
|
|
@@ -8365,7 +8302,7 @@ async function finalizeExtensionImport(projectDir, sourceDir, relPaths, fallback
|
|
|
8365
8302
|
}
|
|
8366
8303
|
const id = await uniqueExtensionId(projectDir, meta.name?.trim() || fallbackName);
|
|
8367
8304
|
const dest = path18.join(projectDir, EXTENSIONS_DIR, id);
|
|
8368
|
-
await
|
|
8305
|
+
await mkdir9(path18.dirname(dest), { recursive: true });
|
|
8369
8306
|
await cp3(sourceDir, dest, { recursive: true });
|
|
8370
8307
|
await completeLandedManifest(dest, id, meta, metaExists);
|
|
8371
8308
|
const entry = await addExtension(projectDir, `./${EXTENSIONS_DIR}/${id}`);
|
|
@@ -8385,7 +8322,7 @@ async function completeLandedManifest(dest, id, meta, metaExists) {
|
|
|
8385
8322
|
} catch {}
|
|
8386
8323
|
}
|
|
8387
8324
|
const gutterpress = pkg.gutterpress && typeof pkg.gutterpress === "object" && !Array.isArray(pkg.gutterpress) ? pkg.gutterpress : {};
|
|
8388
|
-
await
|
|
8325
|
+
await writeFile11(file, JSON.stringify({
|
|
8389
8326
|
...pkg,
|
|
8390
8327
|
name: typeof pkg.name === "string" && pkg.name.trim() ? pkg.name : id,
|
|
8391
8328
|
gutterpress: { ...gutterpress, styles: ["theme.css"] }
|
|
@@ -8449,8 +8386,8 @@ async function importExtensionFromZip(projectDir, archive) {
|
|
|
8449
8386
|
throw new Error(`The package contains an unsafe path and was rejected: ${name}`);
|
|
8450
8387
|
}
|
|
8451
8388
|
relPaths.push(rel);
|
|
8452
|
-
await
|
|
8453
|
-
await
|
|
8389
|
+
await mkdir9(path18.dirname(dest), { recursive: true });
|
|
8390
|
+
await writeFile11(dest, data);
|
|
8454
8391
|
}
|
|
8455
8392
|
return await finalizeExtensionImport(projectDir, tmp, relPaths, root || "imported-look");
|
|
8456
8393
|
} finally {
|
|
@@ -8465,8 +8402,8 @@ async function importExtensionFromCssText(projectDir, css, name) {
|
|
|
8465
8402
|
const displayName = name.trim() || "Imported theme";
|
|
8466
8403
|
const tmp = await mkdtemp(path18.join(tmpdir2(), "gutterpress-theme-"));
|
|
8467
8404
|
try {
|
|
8468
|
-
await
|
|
8469
|
-
await
|
|
8405
|
+
await writeFile11(path18.join(tmp, "theme.css"), css, "utf8");
|
|
8406
|
+
await writeFile11(path18.join(tmp, EXTENSION_MANIFEST_FILENAME), JSON.stringify({ name: slugify(displayName, "look"), gutterpress: { styles: ["theme.css"] } }, null, 2), "utf8");
|
|
8470
8407
|
const result = await finalizeExtensionImport(projectDir, tmp, ["theme.css", EXTENSION_MANIFEST_FILENAME], displayName);
|
|
8471
8408
|
result.warnings.unshift({
|
|
8472
8409
|
code: "no-theme-json",
|
|
@@ -8549,7 +8486,7 @@ async function importExtensionFromUrl(projectDir, url) {
|
|
|
8549
8486
|
assertLooksLikeCss(css, trimmed);
|
|
8550
8487
|
const tmp = await mkdtemp(path18.join(tmpdir2(), "gutterpress-ext-"));
|
|
8551
8488
|
try {
|
|
8552
|
-
await
|
|
8489
|
+
await writeFile11(path18.join(tmp, "theme.css"), css, "utf8");
|
|
8553
8490
|
const gp = meta.gutterpress && typeof meta.gutterpress === "object" && !Array.isArray(meta.gutterpress) ? meta.gutterpress : {};
|
|
8554
8491
|
const finalMeta = {
|
|
8555
8492
|
name: typeof meta.name === "string" && meta.name || slugify(baseName, "look"),
|
|
@@ -8561,7 +8498,7 @@ async function importExtensionFromUrl(projectDir, url) {
|
|
|
8561
8498
|
preview: typeof gp.preview === "string" ? gp.preview : null
|
|
8562
8499
|
}
|
|
8563
8500
|
};
|
|
8564
|
-
await
|
|
8501
|
+
await writeFile11(path18.join(tmp, EXTENSION_MANIFEST_FILENAME), JSON.stringify(finalMeta, null, 2), "utf8");
|
|
8565
8502
|
return await finalizeExtensionImport(projectDir, tmp, ["theme.css", EXTENSION_MANIFEST_FILENAME], baseName);
|
|
8566
8503
|
} finally {
|
|
8567
8504
|
await rm2(tmp, { recursive: true, force: true });
|
|
@@ -8682,7 +8619,7 @@ async function searchNpmExtensions(query, options = {}) {
|
|
|
8682
8619
|
return { matches, total: pages.reduce((sum, page) => sum + page.total, 0) };
|
|
8683
8620
|
}
|
|
8684
8621
|
// src/lib/manifest-config.ts
|
|
8685
|
-
import { isSeq as isSeq2, isMap as isMap3, YAMLSeq, Scalar
|
|
8622
|
+
import { isSeq as isSeq2, isMap as isMap3, YAMLSeq, Scalar } from "yaml";
|
|
8686
8623
|
function hasKey(obj, key) {
|
|
8687
8624
|
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
8688
8625
|
}
|
|
@@ -8765,7 +8702,7 @@ async function setActiveStyles(projectDir, paths) {
|
|
|
8765
8702
|
} else {
|
|
8766
8703
|
const seq = new YAMLSeq(doc.schema);
|
|
8767
8704
|
for (const p of paths)
|
|
8768
|
-
seq.add(new
|
|
8705
|
+
seq.add(new Scalar(p));
|
|
8769
8706
|
doc.set("styles", seq);
|
|
8770
8707
|
}
|
|
8771
8708
|
await writeManifestDoc(file, doc);
|
|
@@ -8773,9 +8710,9 @@ async function setActiveStyles(projectDir, paths) {
|
|
|
8773
8710
|
}
|
|
8774
8711
|
// src/lib/version-changes.ts
|
|
8775
8712
|
import path19 from "node:path";
|
|
8776
|
-
import { mkdir as
|
|
8713
|
+
import { mkdir as mkdir10, readFile as readFile30, writeFile as writeFile12 } from "node:fs/promises";
|
|
8777
8714
|
import git3 from "isomorphic-git";
|
|
8778
|
-
import
|
|
8715
|
+
import postcss5 from "postcss";
|
|
8779
8716
|
|
|
8780
8717
|
// src/lib/remote-auth/transport.ts
|
|
8781
8718
|
import git2 from "isomorphic-git";
|
|
@@ -9228,7 +9165,7 @@ function paragraphs(text) {
|
|
|
9228
9165
|
}
|
|
9229
9166
|
function cssRules(text) {
|
|
9230
9167
|
try {
|
|
9231
|
-
return
|
|
9168
|
+
return postcss5.parse(text).nodes.map((node) => node.toString().trim()).filter((rule) => rule.length > 0);
|
|
9232
9169
|
} catch {
|
|
9233
9170
|
return textLines(text);
|
|
9234
9171
|
}
|
|
@@ -9467,8 +9404,8 @@ async function exportVersionTree(projectDir, id, destDir) {
|
|
|
9467
9404
|
if (!content)
|
|
9468
9405
|
return null;
|
|
9469
9406
|
const abs = path19.join(destDir, filepath);
|
|
9470
|
-
await
|
|
9471
|
-
await
|
|
9407
|
+
await mkdir10(path19.dirname(abs), { recursive: true });
|
|
9408
|
+
await writeFile12(abs, content);
|
|
9472
9409
|
return null;
|
|
9473
9410
|
}
|
|
9474
9411
|
});
|
|
@@ -10084,7 +10021,7 @@ import git5 from "isomorphic-git";
|
|
|
10084
10021
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
10085
10022
|
|
|
10086
10023
|
// src/lib/remote-auth/converge-merge.ts
|
|
10087
|
-
import { mkdir as
|
|
10024
|
+
import { mkdir as mkdir11, unlink as unlink2, writeFile as writeFile13 } from "node:fs/promises";
|
|
10088
10025
|
import path20 from "node:path";
|
|
10089
10026
|
import git4 from "isomorphic-git";
|
|
10090
10027
|
import diff3Merge from "diff3";
|
|
@@ -10134,8 +10071,8 @@ async function readBlob(dir, cache2, oid, filepath) {
|
|
|
10134
10071
|
}
|
|
10135
10072
|
async function writeTreeFile(dir, filepath, content) {
|
|
10136
10073
|
const abs = path20.join(dir, filepath);
|
|
10137
|
-
await
|
|
10138
|
-
await
|
|
10074
|
+
await mkdir11(path20.dirname(abs), { recursive: true });
|
|
10075
|
+
await writeFile13(abs, content);
|
|
10139
10076
|
}
|
|
10140
10077
|
async function bothAddedPaths(dir, cache2, ourTip, theirTip, allowUnrelated) {
|
|
10141
10078
|
const bases = await git4.findMergeBase({ fs: gitFs, dir, cache: cache2, oids: [ourTip, theirTip] });
|
|
@@ -10791,7 +10728,7 @@ async function setUpOnlineBackup(options) {
|
|
|
10791
10728
|
}
|
|
10792
10729
|
}
|
|
10793
10730
|
// src/lib/remote-auth/clone.ts
|
|
10794
|
-
import { mkdir as
|
|
10731
|
+
import { mkdir as mkdir12, readdir as readdir9, rm as rm3 } from "node:fs/promises";
|
|
10795
10732
|
import path21 from "node:path";
|
|
10796
10733
|
import git7 from "isomorphic-git";
|
|
10797
10734
|
function sanitizeCloneFolderName(name) {
|
|
@@ -10850,7 +10787,7 @@ async function cloneRepository(options) {
|
|
|
10850
10787
|
return withRepoLock(dir, async () => {
|
|
10851
10788
|
await assertCloneTarget(dir);
|
|
10852
10789
|
const dirExistedBefore = gitFs.existsSync(dir);
|
|
10853
|
-
await
|
|
10790
|
+
await mkdir12(dir, { recursive: true });
|
|
10854
10791
|
try {
|
|
10855
10792
|
await git7.clone({
|
|
10856
10793
|
fs: gitFs,
|
|
@@ -11140,11 +11077,11 @@ async function diagnoseProjectRemote(projectDir, options = {}) {
|
|
|
11140
11077
|
}
|
|
11141
11078
|
// src/lib/remote-auth/repair.ts
|
|
11142
11079
|
import git9 from "isomorphic-git";
|
|
11143
|
-
import { cp as cp4, mkdir as
|
|
11080
|
+
import { cp as cp4, mkdir as mkdir13, rename as rename3, rm as rm4 } from "node:fs/promises";
|
|
11144
11081
|
import path22 from "node:path";
|
|
11145
11082
|
var REPAIR_SNAPSHOT_MESSAGE = "Repaired online backup";
|
|
11146
11083
|
async function moveDir(from, to) {
|
|
11147
|
-
await
|
|
11084
|
+
await mkdir13(path22.dirname(to), { recursive: true });
|
|
11148
11085
|
try {
|
|
11149
11086
|
await rename3(from, to);
|
|
11150
11087
|
} catch (e) {
|
|
@@ -11221,7 +11158,7 @@ async function repairOnlineBackup(options) {
|
|
|
11221
11158
|
}
|
|
11222
11159
|
// src/lib/remote-auth/scorched-earth.ts
|
|
11223
11160
|
import git10 from "isomorphic-git";
|
|
11224
|
-
import { cp as cp5, mkdir as
|
|
11161
|
+
import { cp as cp5, mkdir as mkdir14, readdir as readdir10, rm as rm5 } from "node:fs/promises";
|
|
11225
11162
|
import path23 from "node:path";
|
|
11226
11163
|
async function emptyDir(dir) {
|
|
11227
11164
|
for (const entry of await readdir10(dir)) {
|
|
@@ -11251,7 +11188,7 @@ async function scorchedEarth(options) {
|
|
|
11251
11188
|
branch2 = undefined;
|
|
11252
11189
|
}
|
|
11253
11190
|
logger.info("backup", "copying folder", { to: backupDir });
|
|
11254
|
-
await
|
|
11191
|
+
await mkdir14(backupDir, { recursive: true });
|
|
11255
11192
|
await cp5(dir, backupDir, { recursive: true });
|
|
11256
11193
|
logger.info("delete", "emptying folder", { dir });
|
|
11257
11194
|
await emptyDir(dir);
|
|
@@ -11437,11 +11374,11 @@ ${tail}` : ""}`);
|
|
|
11437
11374
|
};
|
|
11438
11375
|
|
|
11439
11376
|
// src/lib/publish/providers/guided.ts
|
|
11440
|
-
import { copyFile as copyFile2, mkdir as
|
|
11377
|
+
import { copyFile as copyFile2, mkdir as mkdir15, writeFile as writeFile14 } from "node:fs/promises";
|
|
11441
11378
|
import path24 from "node:path";
|
|
11442
11379
|
async function stageGuidedPackage(req, providerId, listingLines) {
|
|
11443
11380
|
const packageDir = path24.join(path24.dirname(req.artifact.path), "publish", providerId);
|
|
11444
|
-
await
|
|
11381
|
+
await mkdir15(packageDir, { recursive: true });
|
|
11445
11382
|
await copyFile2(req.artifact.path, path24.join(packageDir, path24.basename(req.artifact.path)));
|
|
11446
11383
|
const { title, authors } = req.project;
|
|
11447
11384
|
const sheet = [
|
|
@@ -11455,7 +11392,7 @@ async function stageGuidedPackage(req, providerId, listingLines) {
|
|
|
11455
11392
|
""
|
|
11456
11393
|
].join(`
|
|
11457
11394
|
`);
|
|
11458
|
-
await
|
|
11395
|
+
await writeFile14(path24.join(packageDir, "LISTING.md"), sheet, "utf8");
|
|
11459
11396
|
return packageDir;
|
|
11460
11397
|
}
|
|
11461
11398
|
|
|
@@ -11518,7 +11455,7 @@ var drivethrurpgProvider = {
|
|
|
11518
11455
|
};
|
|
11519
11456
|
|
|
11520
11457
|
// src/lib/publish/providers/gdrive.ts
|
|
11521
|
-
import { mkdtemp as mkdtemp2, readFile as readFile31, readdir as readdir11, rm as rm6, stat as stat7, writeFile as
|
|
11458
|
+
import { mkdtemp as mkdtemp2, readFile as readFile31, readdir as readdir11, rm as rm6, stat as stat7, writeFile as writeFile15 } from "node:fs/promises";
|
|
11522
11459
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
11523
11460
|
import path25 from "node:path";
|
|
11524
11461
|
import { Zip, ZipDeflate } from "fflate";
|
|
@@ -11926,7 +11863,7 @@ async function collectZipEntries(root, dir, out, onWarn) {
|
|
|
11926
11863
|
}
|
|
11927
11864
|
}
|
|
11928
11865
|
}
|
|
11929
|
-
async function zipHtmlExport(exportDir, title, onWarn, writeArchiveImpl =
|
|
11866
|
+
async function zipHtmlExport(exportDir, title, onWarn, writeArchiveImpl = writeFile15) {
|
|
11930
11867
|
const entries = {};
|
|
11931
11868
|
await collectZipEntries(exportDir, exportDir, entries, onWarn);
|
|
11932
11869
|
const fileName = `${bookSlug(title)}-website.zip`;
|
|
@@ -12030,7 +11967,7 @@ var gdriveProvider = {
|
|
|
12030
11967
|
};
|
|
12031
11968
|
|
|
12032
11969
|
// src/lib/publish/butler.ts
|
|
12033
|
-
import { chmod as chmod2, mkdir as
|
|
11970
|
+
import { chmod as chmod2, mkdir as mkdir16, stat as stat8, writeFile as writeFile16 } from "node:fs/promises";
|
|
12034
11971
|
import path26 from "node:path";
|
|
12035
11972
|
import { unzipSync as unzipSync2 } from "fflate";
|
|
12036
11973
|
var BUTLER_DOWNLOAD_TIMEOUT_MS = 300000;
|
|
@@ -12091,13 +12028,13 @@ async function ensureButler(deps) {
|
|
|
12091
12028
|
return new Uint8Array(await response.arrayBuffer());
|
|
12092
12029
|
});
|
|
12093
12030
|
const files = unzipSync2(archive);
|
|
12094
|
-
await
|
|
12031
|
+
await mkdir16(cacheDir, { recursive: true });
|
|
12095
12032
|
let foundBinary = false;
|
|
12096
12033
|
for (const [name, data] of Object.entries(files)) {
|
|
12097
12034
|
if (name.endsWith("/"))
|
|
12098
12035
|
continue;
|
|
12099
12036
|
const target = path26.join(cacheDir, path26.basename(name));
|
|
12100
|
-
await
|
|
12037
|
+
await writeFile16(target, data);
|
|
12101
12038
|
if (path26.basename(name) === butlerBinaryName()) {
|
|
12102
12039
|
await chmod2(target, 493).catch(() => {});
|
|
12103
12040
|
foundBinary = true;
|
|
@@ -12294,7 +12231,7 @@ var kdpProvider = {
|
|
|
12294
12231
|
};
|
|
12295
12232
|
|
|
12296
12233
|
// src/lib/publish/providers/local-folder.ts
|
|
12297
|
-
import { cp as cp6, mkdir as
|
|
12234
|
+
import { cp as cp6, mkdir as mkdir17, stat as stat9 } from "node:fs/promises";
|
|
12298
12235
|
import path27 from "node:path";
|
|
12299
12236
|
var LOCAL_PUBLISH_DEFAULT_DIR = "dist";
|
|
12300
12237
|
var info8 = {
|
|
@@ -12332,7 +12269,7 @@ var localFolderProvider = {
|
|
|
12332
12269
|
},
|
|
12333
12270
|
async upload(req) {
|
|
12334
12271
|
const dir = localPublishDir(req);
|
|
12335
|
-
await
|
|
12272
|
+
await mkdir17(dir, { recursive: true });
|
|
12336
12273
|
const dest = req.artifact.format === "html" ? dir : path27.join(dir, path27.basename(req.artifact.path));
|
|
12337
12274
|
if (path27.resolve(dest) !== path27.resolve(req.artifact.path)) {
|
|
12338
12275
|
await cp6(req.artifact.path, dest, { recursive: true });
|
|
@@ -12632,7 +12569,7 @@ async function resolvePublishProvider(id, book) {
|
|
|
12632
12569
|
const ext = await bookExtensions(book);
|
|
12633
12570
|
const npmEntry = ext.extensions.some((c) => !c.path && c.name === id);
|
|
12634
12571
|
if (npmEntry) {
|
|
12635
|
-
const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-
|
|
12572
|
+
const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-9dh7c4tp.js");
|
|
12636
12573
|
await restoreForCommand2(book.projectDir, { manifestPath: book.manifestPath, failFast: true });
|
|
12637
12574
|
}
|
|
12638
12575
|
const publishers = await discover(ext);
|
|
@@ -12670,7 +12607,7 @@ function infoFor(p) {
|
|
|
12670
12607
|
}
|
|
12671
12608
|
function pluginProvider(p) {
|
|
12672
12609
|
let loading;
|
|
12673
|
-
const load = () => loading ??= import("./plugins-
|
|
12610
|
+
const load = () => loading ??= import("./plugins-80emnf31.js").then((m) => m.loadPublishFunction(p));
|
|
12674
12611
|
return {
|
|
12675
12612
|
info: infoFor(p),
|
|
12676
12613
|
async authenticate() {
|
|
@@ -12941,7 +12878,7 @@ async function disconnectPublishCredential(key, deps, options = {}) {
|
|
|
12941
12878
|
}
|
|
12942
12879
|
}
|
|
12943
12880
|
// src/lib/publish/selections.ts
|
|
12944
|
-
import { chmod as chmod3, mkdir as
|
|
12881
|
+
import { chmod as chmod3, mkdir as mkdir18, readFile as readFile32, writeFile as writeFile17 } from "node:fs/promises";
|
|
12945
12882
|
import path30 from "node:path";
|
|
12946
12883
|
class PublishSelectionsStore {
|
|
12947
12884
|
filePath;
|
|
@@ -12964,8 +12901,8 @@ class PublishSelectionsStore {
|
|
|
12964
12901
|
return { version: 1, global: {}, projects: {} };
|
|
12965
12902
|
}
|
|
12966
12903
|
async write(data) {
|
|
12967
|
-
await
|
|
12968
|
-
await
|
|
12904
|
+
await mkdir18(path30.dirname(this.filePath), { recursive: true });
|
|
12905
|
+
await writeFile17(this.filePath, JSON.stringify(data, null, 2), {
|
|
12969
12906
|
encoding: "utf8",
|
|
12970
12907
|
mode: 384
|
|
12971
12908
|
});
|