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.
Files changed (82) hide show
  1. package/README.md +10 -13
  2. package/dist/{README-8ef336pp.md → README-syg2hn83.md} +13 -19
  3. package/dist/api/index.d.ts +1 -1
  4. package/dist/api/index.js +5 -5
  5. package/dist/{build-encgnv0c.js → build-c48eer6f.js} +8 -8
  6. package/dist/checks/asset/extensions.d.ts +1 -1
  7. package/dist/checks/asset/index.d.ts +0 -1
  8. package/dist/checks/policy.d.ts +5 -4
  9. package/dist/checks/source/config-file.d.ts +9 -6
  10. package/dist/checks/source/dangling-links.d.ts +1 -1
  11. package/dist/checks/types.d.ts +2 -2
  12. package/dist/{cli-pz4bn98t.js → cli-54xt7pjg.js} +19 -13
  13. package/dist/{index-2ppw6q9v.js → cli-5crpmz42.js} +80 -1
  14. package/dist/{cli-xq6djqbj.js → cli-93mkaw6v.js} +166 -308
  15. package/dist/{cli-evg8sbht.js → cli-d9mm3vvh.js} +7 -2
  16. package/dist/{cli-kh8v4vvw.js → cli-gnpea9dx.js} +1 -1
  17. package/dist/{cli-aqh6brew.js → cli-pspjxnc8.js} +1 -1
  18. package/dist/{cli-pwwfxdgb.js → cli-rqh295j9.js} +15 -21
  19. package/dist/{index-x3ema2w3.js → cli-y6d1arem.js} +321 -272
  20. package/dist/cli.js +12 -12
  21. package/dist/{doctor-5gtpgpd1.js → doctor-ptb346k8.js} +4 -3
  22. package/dist/engine/shared/gcpm-extract.d.ts +8 -0
  23. package/dist/engine/shared/print-area.d.ts +16 -4
  24. package/dist/{engine-mc5br8g8.js → engine-4rzdx6af.js} +1 -1
  25. package/dist/{engine-tn13gk0b.js → engine-6txhxmmv.js} +2 -2
  26. package/dist/{ext-wn2a5afq.js → ext-gy8szg3x.js} +8 -8
  27. package/dist/{extension-restore-s3x1618g.js → extension-restore-dymzcasz.js} +2 -2
  28. package/dist/{extension-restore-g8jnmmzq.js → extension-restore-m8tj43e7.js} +4 -4
  29. package/dist/{gutterpress-viewer-701vf4qp.js → gutterpress-viewer-mafsby5k.js} +9 -2
  30. package/dist/{cli-2ppw6q9v.js → index-5crpmz42.js} +80 -1
  31. package/dist/{index-0skhjx3e.js → index-5kh4c78h.js} +19 -13
  32. package/dist/{index-2bjcghze.js → index-8ywkd2sv.js} +15 -21
  33. package/dist/{index-j5z86r4a.js → index-ea94zbq4.js} +329 -488
  34. package/dist/{cli-sdmv4bba.js → index-kaks3mm2.js} +448 -156
  35. package/dist/{index-4x6y8krm.js → index-yc3xj266.js} +1 -1
  36. package/dist/index.js +6 -6
  37. package/dist/lib/build-preflight.d.ts +4 -10
  38. package/dist/lib/build-runner.d.ts +1 -1
  39. package/dist/lib/extension-manager.d.ts +8 -7
  40. package/dist/lib/extension-manifest.d.ts +1 -13
  41. package/dist/lib/ghostscript.d.ts +5 -2
  42. package/dist/lib/lint-rules.d.ts +5 -1
  43. package/dist/lib/manifest-config.d.ts +3 -2
  44. package/dist/lib/manifest-old-spellings.d.ts +64 -0
  45. package/dist/lib/manifest.d.ts +15 -1
  46. package/dist/lib/markdown/assemble.d.ts +4 -3
  47. package/dist/lib/markdown/chapter-id.d.ts +1 -1
  48. package/dist/lib/markdown/index.d.ts +1 -1
  49. package/dist/lib/markdown/table.d.ts +5 -3
  50. package/dist/lib/page-size.d.ts +45 -33
  51. package/dist/lib/pdf-inspect.d.ts +27 -0
  52. package/dist/lib/presets.d.ts +10 -8
  53. package/dist/lib/printsafe.d.ts +2 -1
  54. package/dist/lib/project-scaffold.d.ts +1 -1
  55. package/dist/lib/project-templates.d.ts +9 -0
  56. package/dist/lib/remote-auth/sync-messages.d.ts +2 -2
  57. package/dist/lib/targets.d.ts +4 -4
  58. package/dist/lib/validation-exec.d.ts +4 -4
  59. package/dist/manifest-2kc56wvw.yaml +22 -0
  60. package/dist/manifest-41ddzm13.yaml +18 -0
  61. package/dist/manifest-79zsgkpn.yaml +26 -0
  62. package/dist/manifest-sqzm4681.yaml +22 -0
  63. package/dist/{manifest.schema-t7nx2stg.json → manifest.schema-w86c1xw1.json} +30 -308
  64. package/dist/{new-mhs46pw3.js → new-t2t28ccb.js} +9 -15
  65. package/dist/{package-aenwjew3.json → package-awwkt7sa.json} +0 -1
  66. package/dist/{page-rules-nsj3aw42.css → page-rules-ytj9p04v.css} +12 -40
  67. package/dist/{pdf-inspect-wnw4za71.js → pdf-inspect-b3mf81ex.js} +3 -1
  68. package/dist/{plugin.test.js-xgxrd8hf.tpl → plugin.test.js-gxzqqfdh.tpl} +0 -1
  69. package/dist/{plugins-2cek4mz1.js → plugins-fec8t2bh.js} +1 -1
  70. package/dist/{plugins-1sxe0dkz.js → plugins-sqa4msdk.js} +3 -3
  71. package/dist/{preflight-3k2b1x8e.js → preflight-srq8fktp.js} +8 -8
  72. package/dist/preview/file-watcher.d.ts +1 -3
  73. package/dist/{preview-6p9v6rht.js → preview-zsp9hstd.js} +8 -8
  74. package/dist/{publish-qgsngy8s.js → publish-hhy31gr9.js} +8 -8
  75. package/dist/render.js +30 -562
  76. package/dist/schema/manifest.types.d.ts +60 -105
  77. package/dist/{tokens-7984461t.css → tokens-n82t4k9h.css} +12 -12
  78. package/dist/{validate-0v7xw6wa.js → validate-r9jdz85h.js} +8 -8
  79. package/package.json +1 -1
  80. package/dist/checks/asset/approved-fonts.d.ts +0 -3
  81. package/dist/manifest-eagfhba6.yaml +0 -19
  82. package/dist/manifest-n1gh3qw5.yaml +0 -9
package/dist/cli.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  } from "./cli-d8xjns66.js";
9
9
  import {
10
10
  package_default
11
- } from "./cli-kh8v4vvw.js";
11
+ } from "./cli-gnpea9dx.js";
12
12
  import {
13
13
  EXIT_CODES
14
14
  } from "./cli-46ycxe6r.js";
@@ -20,14 +20,14 @@ import {
20
20
  import { defineCommand, parseArgs, runMain } from "citty";
21
21
  import { statSync } from "node:fs";
22
22
  var SUBCOMMANDS = {
23
- new: () => import("./new-mhs46pw3.js").then((m) => m.default),
24
- preview: () => import("./preview-6p9v6rht.js").then((m) => m.default),
25
- build: () => import("./build-encgnv0c.js").then((m) => m.default),
26
- publish: () => import("./publish-qgsngy8s.js").then((m) => m.default),
27
- validate: () => import("./validate-0v7xw6wa.js").then((m) => m.default),
28
- preflight: () => import("./preflight-3k2b1x8e.js").then((m) => m.default),
29
- doctor: () => import("./doctor-5gtpgpd1.js").then((m) => m.default),
30
- ext: () => import("./ext-wn2a5afq.js").then((m) => m.default)
23
+ new: () => import("./new-t2t28ccb.js").then((m) => m.default),
24
+ preview: () => import("./preview-zsp9hstd.js").then((m) => m.default),
25
+ build: () => import("./build-c48eer6f.js").then((m) => m.default),
26
+ publish: () => import("./publish-hhy31gr9.js").then((m) => m.default),
27
+ validate: () => import("./validate-r9jdz85h.js").then((m) => m.default),
28
+ preflight: () => import("./preflight-srq8fktp.js").then((m) => m.default),
29
+ doctor: () => import("./doctor-ptb346k8.js").then((m) => m.default),
30
+ ext: () => import("./ext-gy8szg3x.js").then((m) => m.default)
31
31
  };
32
32
  var VERSION = package_default.version;
33
33
  var main = defineCommand({
@@ -52,7 +52,7 @@ async function preflightRequiredInvocations(rawArgs) {
52
52
  const [command, ...commandArgs] = rawArgs;
53
53
  try {
54
54
  if (command === "new") {
55
- const { newArgs } = await import("./new-mhs46pw3.js");
55
+ const { newArgs } = await import("./new-t2t28ccb.js");
56
56
  rejectUnknownFlags(commandArgs, newArgs, "new");
57
57
  const parsed = parseArgs(commandArgs, {
58
58
  ...newArgs,
@@ -64,7 +64,7 @@ async function preflightRequiredInvocations(rawArgs) {
64
64
  return;
65
65
  }
66
66
  if (command === "preflight") {
67
- const { preflightArgs } = await import("./preflight-3k2b1x8e.js");
67
+ const { preflightArgs } = await import("./preflight-srq8fktp.js");
68
68
  rejectUnknownFlags(commandArgs, preflightArgs, "preflight");
69
69
  const parsed = parseArgs(commandArgs, {
70
70
  ...preflightArgs,
@@ -84,7 +84,7 @@ async function preflightRequiredInvocations(rawArgs) {
84
84
  }
85
85
  if (subcommand.startsWith("-"))
86
86
  return;
87
- const { EXT_SUBCOMMANDS, extAddArgs, extRemoveArgs, extEnableArgs, extDisableArgs } = await import("./ext-wn2a5afq.js");
87
+ const { EXT_SUBCOMMANDS, extAddArgs, extRemoveArgs, extEnableArgs, extDisableArgs } = await import("./ext-gy8szg3x.js");
88
88
  if (!EXT_SUBCOMMANDS.includes(subcommand)) {
89
89
  throw new UsageError(`gutterpress ext: unknown command "${subcommand}"`);
90
90
  }
@@ -1,16 +1,17 @@
1
1
  import {
2
2
  getSystemDiagnostics
3
- } from "./cli-evg8sbht.js";
3
+ } from "./cli-d9mm3vvh.js";
4
+ import"./cli-5crpmz42.js";
4
5
  import"./cli-asap4t1z.js";
5
6
  import {
6
7
  log
7
- } from "./cli-aqh6brew.js";
8
+ } from "./cli-pspjxnc8.js";
8
9
  import {
9
10
  UsageError,
10
11
  rejectExtraPositionals,
11
12
  rejectUnknownFlags
12
13
  } from "./cli-d8xjns66.js";
13
- import"./cli-kh8v4vvw.js";
14
+ import"./cli-gnpea9dx.js";
14
15
  import"./cli-46ycxe6r.js";
15
16
  import"./cli-37x76zdn.js";
16
17
 
@@ -109,6 +109,14 @@ export declare function parseMargin(value: string): {
109
109
  * Later rules win; specificity follows the spec's simplified order
110
110
  * (unnamed < named, no-pseudo < pseudo).
111
111
  */
112
+ /**
113
+ * The margin a page has when no `@page` rule sets one: what `resolvePage`
114
+ * assumes, and what the assembly writes ahead of every stylesheet
115
+ * (`defaultPageMarginCss`, lib/markdown/assemble.ts) so Chromium prints with
116
+ * the same number instead of its own default of about 0.4in, which would
117
+ * make the preview and the PDF paginate differently.
118
+ */
119
+ export declare const DEFAULT_PAGE_MARGIN_PT = 72;
112
120
  export declare function resolvePage(model: GcpmModel, ctx?: {
113
121
  name?: string;
114
122
  pseudos?: string[];
@@ -55,6 +55,13 @@ export interface PrintAreaSource {
55
55
  safe?: number;
56
56
  artSafe?: number;
57
57
  gutter?: number;
58
+ /** The margins the manifest sets (pt), written as the book's `@page` margins; absent = the stylesheets'. */
59
+ margin?: {
60
+ top: number;
61
+ bottom: number;
62
+ inside: number;
63
+ outside: number;
64
+ };
58
65
  preset?: string;
59
66
  spec?: {
60
67
  label: string;
@@ -63,11 +70,16 @@ export interface PrintAreaSource {
63
70
  }
64
71
  /** A usable point value: finite and positive (a page dimension, an inset). */
65
72
  export declare function isPositivePoints(value: unknown): value is number;
73
+ /** A margin value: finite and 0 or more (a full-bleed edge has no margin). */
74
+ export declare function isNonNegativePoints(value: unknown): value is number;
75
+ /** Round to 3dp so 8.27in doesn't print as 8.270000000000001in. */
76
+ export declare const round3: (n: number) => number;
77
+ /** CSS length for a point value: inches when exact to 3dp (612 -> 8.5in), else points. */
78
+ export declare function cssLength(pt: number): string;
66
79
  /**
67
- * The `size` value written for a page — `8.5in 11in`, `595pt 842pt` — by
68
- * everything that writes one: Book settings (lib/page-size.ts) into the
69
- * book's stylesheet, and the assembly's manifest default
70
- * (lib/markdown/assemble.ts), so one size has one spelling.
80
+ * The `size` value written for a page — `8.5in 11in`, `595pt 842pt` — by the
81
+ * assembly's `@page` rule (lib/markdown/assemble.ts), the one place a size is
82
+ * written, so one size has one spelling.
71
83
  */
72
84
  export declare function formatPageSize(page: {
73
85
  width: number;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  build
3
- } from "./cli-pz4bn98t.js";
3
+ } from "./cli-54xt7pjg.js";
4
4
  import"./cli-eyyggect.js";
5
5
  import"./cli-asap4t1z.js";
6
6
  import {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  build
3
- } from "./index-4x6y8krm.js";
4
- import"./index-0skhjx3e.js";
3
+ } from "./index-yc3xj266.js";
4
+ import"./index-5kh4c78h.js";
5
5
  import {
6
6
  BuildError
7
7
  } from "./index-46ycxe6r.js";
@@ -2,11 +2,11 @@ import {
2
2
  importExtensionFromFile,
3
3
  importExtensionFromUrl,
4
4
  searchNpmExtensions
5
- } from "./cli-xq6djqbj.js";
6
- import"./cli-evg8sbht.js";
5
+ } from "./cli-93mkaw6v.js";
6
+ import"./cli-d9mm3vvh.js";
7
7
  import"./cli-ht1bcqdd.js";
8
- import"./cli-pz4bn98t.js";
9
- import"./cli-2ppw6q9v.js";
8
+ import"./cli-54xt7pjg.js";
9
+ import"./cli-5crpmz42.js";
10
10
  import"./cli-eyyggect.js";
11
11
  import"./cli-asap4t1z.js";
12
12
  import"./cli-a35w7wzg.js";
@@ -18,12 +18,12 @@ import {
18
18
  removeExtension,
19
19
  setExtensionEnabled,
20
20
  updateExtensions
21
- } from "./cli-sdmv4bba.js";
21
+ } from "./cli-y6d1arem.js";
22
22
  import {
23
23
  isPathSpecifier,
24
24
  parseExtensionSpecifier
25
- } from "./cli-pwwfxdgb.js";
26
- import"./cli-aqh6brew.js";
25
+ } from "./cli-rqh295j9.js";
26
+ import"./cli-pspjxnc8.js";
27
27
  import {
28
28
  UsageError,
29
29
  exitForUsage,
@@ -31,7 +31,7 @@ import {
31
31
  rejectUnknownFlags,
32
32
  resolveProjectDir
33
33
  } from "./cli-d8xjns66.js";
34
- import"./cli-kh8v4vvw.js";
34
+ import"./cli-gnpea9dx.js";
35
35
  import {
36
36
  EXIT_CODES
37
37
  } from "./cli-46ycxe6r.js";
@@ -3,8 +3,8 @@ import {
3
3
  restoreForCommand,
4
4
  restoreOfflineMessage,
5
5
  restorePinnedExtensions
6
- } from "./index-x3ema2w3.js";
7
- import"./index-2bjcghze.js";
6
+ } from "./index-kaks3mm2.js";
7
+ import"./index-8ywkd2sv.js";
8
8
  import"./index-46ycxe6r.js";
9
9
  import"./index-5x42amh8.js";
10
10
  import"./index-37x76zdn.js";
@@ -3,11 +3,11 @@ import {
3
3
  restoreForCommand,
4
4
  restoreOfflineMessage,
5
5
  restorePinnedExtensions
6
- } from "./cli-sdmv4bba.js";
7
- import"./cli-pwwfxdgb.js";
8
- import"./cli-aqh6brew.js";
6
+ } from "./cli-y6d1arem.js";
7
+ import"./cli-rqh295j9.js";
8
+ import"./cli-pspjxnc8.js";
9
9
  import"./cli-d8xjns66.js";
10
- import"./cli-kh8v4vvw.js";
10
+ import"./cli-gnpea9dx.js";
11
11
  import"./cli-46ycxe6r.js";
12
12
  import"./cli-y28j019d.js";
13
13
  import"./cli-37x76zdn.js";
@@ -368,7 +368,8 @@
368
368
  mediaPrintBodies: () => mediaPrintBodies,
369
369
  extract: () => extract,
370
370
  PAGE_SIZES: () => PAGE_SIZES,
371
- MARGIN_BOX_NAMES: () => MARGIN_BOX_NAMES
371
+ MARGIN_BOX_NAMES: () => MARGIN_BOX_NAMES,
372
+ DEFAULT_PAGE_MARGIN_PT: () => DEFAULT_PAGE_MARGIN_PT
372
373
  });
373
374
  var MARGIN_BOX_NAMES = [
374
375
  "top-left-corner",
@@ -923,12 +924,18 @@
923
924
  const d = parts[3] ?? b;
924
925
  return { top: a, right: b, bottom: c, left: d };
925
926
  }
927
+ var DEFAULT_PAGE_MARGIN_PT = 72;
926
928
  function resolvePage(model, ctx = {}) {
927
929
  const wanted = new Set(ctx.pseudos ?? []);
928
930
  const applicable = model.pageRules.filter((r) => r.name ? r.name === ctx.name : true).filter((r) => r.pseudos.every((p) => wanted.has(p))).sort((a, b) => specificity(a) - specificity(b));
929
931
  const decls = {};
930
932
  const marginBoxes = {};
931
- const margin = { top: 72, right: 72, bottom: 72, left: 72 };
933
+ const margin = {
934
+ top: DEFAULT_PAGE_MARGIN_PT,
935
+ right: DEFAULT_PAGE_MARGIN_PT,
936
+ bottom: DEFAULT_PAGE_MARGIN_PT,
937
+ left: DEFAULT_PAGE_MARGIN_PT
938
+ };
932
939
  for (const rule of applicable) {
933
940
  for (const [prop, value] of Object.entries(rule.decls)) {
934
941
  if (prop === "margin")
@@ -348,6 +348,85 @@ async function unsplittableTextReasons(pdfBytes, pages) {
348
348
  }
349
349
  return reasons;
350
350
  }
351
+ var FILL_PAINT_OPS = opSet(["fill", "eoFill", "fillStroke", "eoFillStroke", "closeFillStroke", "closeEOFillStroke"]);
352
+ var STROKE_PAINT_OPS = opSet(["stroke", "closeStroke", "fillStroke", "eoFillStroke", "closeFillStroke", "closeEOFillStroke"]);
353
+ var SLIVER_PT = 0.25;
354
+ async function pagesWithVisibleShadingPaints(pdfBytes, pages) {
355
+ const box = (b, m) => {
356
+ const xs = [];
357
+ const ys = [];
358
+ const corners = [[b[0], b[1]], [b[2], b[1]], [b[2], b[3]], [b[0], b[3]]];
359
+ for (const [x, y] of corners) {
360
+ xs.push(m[0] * x + m[2] * y + m[4]);
361
+ ys.push(m[1] * x + m[3] * y + m[5]);
362
+ }
363
+ return [Math.min(...xs), Math.min(...ys), Math.max(...xs), Math.max(...ys)];
364
+ };
365
+ const intersect = (a, b) => a ? [Math.max(a[0], b[0]), Math.max(a[1], b[1]), Math.min(a[2], b[2]), Math.min(a[3], b[3])] : b;
366
+ const visible = (b) => !b || b[2] - b[0] >= SLIVER_PT && b[3] - b[1] >= SLIVER_PT;
367
+ const doc = await getDocumentProxy(new Uint8Array(pdfBytes));
368
+ const out = [];
369
+ try {
370
+ for (const i of pages) {
371
+ const ops = await (await doc.getPage(i)).getOperatorList();
372
+ let ctm = [1, 0, 0, 1, 0, 0];
373
+ let clip = null;
374
+ let fillShading = false;
375
+ let strokeShading = false;
376
+ let pendingClip = false;
377
+ const stack = [];
378
+ let found = false;
379
+ for (let j = 0;j < ops.fnArray.length && !found; j++) {
380
+ const fn = ops.fnArray[j];
381
+ const args = ops.argsArray[j];
382
+ if (fn === OPS.save)
383
+ stack.push([ctm, clip, fillShading, strokeShading]);
384
+ else if (fn === OPS.restore || fn === OPS.paintFormXObjectEnd) {
385
+ const saved = stack.pop();
386
+ if (saved)
387
+ [ctm, clip, fillShading, strokeShading] = saved;
388
+ } else if (fn === OPS.transform)
389
+ ctm = multiply(ctm, args);
390
+ else if (fn === OPS.paintFormXObjectBegin) {
391
+ stack.push([ctm, clip, fillShading, strokeShading]);
392
+ if (Array.isArray(args[0]))
393
+ ctm = multiply(ctm, args[0]);
394
+ if (Array.isArray(args[1]))
395
+ clip = intersect(clip, box(args[1], ctm));
396
+ } else if (fn === OPS.setFillColorN)
397
+ fillShading = args[0] === "Shading";
398
+ else if (fn === OPS.setStrokeColorN)
399
+ strokeShading = args[0] === "Shading";
400
+ else if (FILL_COLOR_OPS.has(fn))
401
+ fillShading = false;
402
+ else if (STROKE_COLOR_OPS.has(fn))
403
+ strokeShading = false;
404
+ else if (fn === OPS.clip || fn === OPS.eoClip)
405
+ pendingClip = true;
406
+ else if (fn === OPS.constructPath) {
407
+ const paintOp = args[0];
408
+ const bounds = args[2] ? box(args[2], ctm) : null;
409
+ if (fillShading && FILL_PAINT_OPS.has(paintOp) && bounds)
410
+ found = visible(intersect(clip, bounds));
411
+ if (strokeShading && STROKE_PAINT_OPS.has(paintOp))
412
+ found = true;
413
+ if (pendingClip) {
414
+ clip = bounds ? intersect(clip, bounds) : [0, 0, 0, 0];
415
+ pendingClip = false;
416
+ }
417
+ } else if (fn === OPS.shadingFill)
418
+ found = visible(clip);
419
+ else if (SHOW_TEXT_OPS.has(fn) && fillShading)
420
+ found = true;
421
+ }
422
+ if (found)
423
+ out.push(i);
424
+ }
425
+ } finally {
426
+ await doc.destroy();
427
+ }
428
+ return out;
429
+ }
351
430
  function getImagePixelSize(page, name, timeoutMs = 2000) {
352
431
  return new Promise((resolve) => {
353
432
  let done = false;
@@ -435,4 +514,4 @@ async function isLoadable(doc) {
435
514
  }
436
515
  }
437
516
 
438
- export { DOC_CACHE_MAX, loadPdf, retainPdfCache, clearPdfCache, pendingGraceDestroyCount, getPageSize, getOutlineCount, getPageLabels, countLinkAnnotations, getTextPass, getOpPass, unsplittableTextReasons, pageHasMarks, getImageResolutions, isLoadable };
517
+ export { DOC_CACHE_MAX, loadPdf, retainPdfCache, clearPdfCache, pendingGraceDestroyCount, getPageSize, getOutlineCount, getPageLabels, countLinkAnnotations, getTextPass, getOpPass, unsplittableTextReasons, pagesWithVisibleShadingPaints, pageHasMarks, getImageResolutions, isLoadable };
@@ -643,12 +643,18 @@ function parseMargin(value) {
643
643
  const d = parts[3] ?? b;
644
644
  return { top: a, right: b, bottom: c, left: d };
645
645
  }
646
+ var DEFAULT_PAGE_MARGIN_PT = 72;
646
647
  function resolvePage(model, ctx = {}) {
647
648
  const wanted = new Set(ctx.pseudos ?? []);
648
649
  const applicable = model.pageRules.filter((r) => r.name ? r.name === ctx.name : true).filter((r) => r.pseudos.every((p) => wanted.has(p))).sort((a, b) => specificity(a) - specificity(b));
649
650
  const decls = {};
650
651
  const marginBoxes = {};
651
- const margin = { top: 72, right: 72, bottom: 72, left: 72 };
652
+ const margin = {
653
+ top: DEFAULT_PAGE_MARGIN_PT,
654
+ right: DEFAULT_PAGE_MARGIN_PT,
655
+ bottom: DEFAULT_PAGE_MARGIN_PT,
656
+ left: DEFAULT_PAGE_MARGIN_PT
657
+ };
652
658
  for (const rule of applicable) {
653
659
  for (const [prop, value] of Object.entries(rule.decls)) {
654
660
  if (prop === "margin")
@@ -691,7 +697,7 @@ import { fileURLToPath } from "node:url";
691
697
  var favicon_default = "./favicon-272ga6y0.ico";
692
698
 
693
699
  // src/assets/manifest.schema.json
694
- var manifest_schema_default = "./manifest.schema-t7nx2stg.json";
700
+ var manifest_schema_default = "./manifest.schema-w86c1xw1.json";
695
701
 
696
702
  // src/assets/preview/scripts/preview-interface.js
697
703
  var preview_interface_default = "./preview-interface-nnmrxyqm.js";
@@ -706,31 +712,31 @@ var preview_shell_default = "./preview-shell-wk9k3gcd.js";
706
712
  var CGATS21_CRPC1_default = "./CGATS21_CRPC1-g0e3k7kr.icc";
707
713
 
708
714
  // src/assets/engine/gutterpress-viewer.js
709
- var gutterpress_viewer_default = "./gutterpress-viewer-701vf4qp.js";
715
+ var gutterpress_viewer_default = "./gutterpress-viewer-mafsby5k.js";
710
716
 
711
717
  // src/assets/engine/gutterpress-agent.js
712
718
  var gutterpress_agent_default = "./gutterpress-agent-d29ry3ak.js";
713
719
 
714
720
  // src/assets/templates/book/manifest.yaml
715
- var manifest_default = "./manifest-n1gh3qw5.yaml";
721
+ var manifest_default = "./manifest-41ddzm13.yaml";
716
722
 
717
723
  // src/assets/templates/book/chapter-01.md
718
724
  var chapter_01_default = "./chapter-01-gsbjt584.md";
719
725
 
720
726
  // src/assets/templates/zine/manifest.yaml
721
- var manifest_default2 = "./manifest-n1gh3qw5.yaml";
727
+ var manifest_default2 = "./manifest-sqzm4681.yaml";
722
728
 
723
729
  // src/assets/templates/zine/chapter-01.md
724
730
  var chapter_01_default2 = "./chapter-01-wgjfz4w6.md";
725
731
 
726
732
  // src/assets/templates/technical/manifest.yaml
727
- var manifest_default3 = "./manifest-n1gh3qw5.yaml";
733
+ var manifest_default3 = "./manifest-2kc56wvw.yaml";
728
734
 
729
735
  // src/assets/templates/technical/chapter-01.md
730
736
  var chapter_01_default3 = "./chapter-01-6fn9pvd0.md";
731
737
 
732
738
  // src/assets/templates/paper/manifest.yaml
733
- var manifest_default4 = "./manifest-eagfhba6.yaml";
739
+ var manifest_default4 = "./manifest-79zsgkpn.yaml";
734
740
 
735
741
  // src/assets/templates/paper/chapter-01.md
736
742
  var chapter_01_default4 = "./chapter-01-s71xrf5q.md";
@@ -757,13 +763,13 @@ var fixture_default = "./fixture-2qnyqgb5.md";
757
763
  var expected_default = "./expected-ycmacem8.html";
758
764
 
759
765
  // src/assets/extension-templates/plugin/test/plugin.test.js.tpl
760
- var plugin_test_js_default = "./plugin.test.js-xgxrd8hf.tpl";
766
+ var plugin_test_js_default = "./plugin.test.js-gxzqqfdh.tpl";
761
767
 
762
768
  // src/assets/extension-templates/look/package.json
763
- var package_default2 = "./package-aenwjew3.json";
769
+ var package_default2 = "./package-awwkt7sa.json";
764
770
 
765
771
  // src/assets/extension-templates/look/README.md
766
- var README_default2 = "./README-8ef336pp.md";
772
+ var README_default2 = "./README-syg2hn83.md";
767
773
 
768
774
  // src/assets/extension-templates/look/components.yaml
769
775
  var components_default = "./components-zzqdpt3m.yaml";
@@ -772,7 +778,7 @@ var components_default = "./components-zzqdpt3m.yaml";
772
778
  var callout_default = "./callout-hv56m16h.md";
773
779
 
774
780
  // src/assets/extension-templates/look/styles/tokens.css
775
- var tokens_default = "./tokens-7984461t.css";
781
+ var tokens_default = "./tokens-n82t4k9h.css";
776
782
 
777
783
  // src/assets/extension-templates/look/styles/base.css
778
784
  var base_default = "./base-ypqh9n7f.css";
@@ -784,7 +790,7 @@ var components_default2 = "./components-aam0fe2z.css";
784
790
  var page_templates_default = "./page-templates-tx9ryt19.css";
785
791
 
786
792
  // src/assets/extension-templates/look/styles/page-rules.css
787
- var page_rules_default = "./page-rules-nsj3aw42.css";
793
+ var page_rules_default = "./page-rules-ytj9p04v.css";
788
794
 
789
795
  // src/assets/extension-templates/look/styles/book.css
790
796
  var book_default = "./book-ted3tzrp.css";
@@ -913,4 +919,4 @@ function marginBoxAlign(name) {
913
919
  return /right/.test(name) ? "end" : "start";
914
920
  }
915
921
 
916
- export { isRectoVersoBreak, wantsRecto, planRectoBlanks, lastPageMode, signaturePadding, parseWhich, stringValueAt, stringSymbols, cssQuote, counterStyleName, restartedPageValues, toFolioPage, leaderMarker, generatedContentCss, extract, splitTopLevel, parseSize, resolvePage, getAssetPath, MARGIN_BOX_IGNORED_PROPERTIES, isIgnoredMarginBoxProperty, marginBoxRectPt, marginBoxAlign };
922
+ export { isRectoVersoBreak, wantsRecto, planRectoBlanks, lastPageMode, signaturePadding, parseWhich, stringValueAt, stringSymbols, cssQuote, counterStyleName, restartedPageValues, toFolioPage, leaderMarker, generatedContentCss, extract, splitTopLevel, DEFAULT_PAGE_MARGIN_PT, resolvePage, getAssetPath, MARGIN_BOX_IGNORED_PROPERTIES, isIgnoredMarginBoxProperty, marginBoxRectPt, marginBoxAlign };
@@ -20,6 +20,7 @@ import { pathToFileURL } from "node:url";
20
20
  var theme_default = `/* =============================================================================
21
21
  Clean Book — gutterpress built-in theme (theme.css)
22
22
  A calm, classic long-form book look. Change the :root tokens from the book's own stylesheet.
23
+ The page SIZE comes from the manifest (Setup > Book), so it is deliberately not set here.
23
24
  ============================================================================= */
24
25
 
25
26
  :root {
@@ -38,11 +39,7 @@ var theme_default = `/* ========================================================
38
39
  --fs-h2: 1.5rem;
39
40
  --fs-h3: 1.2rem;
40
41
  --leading: 1.55;
41
- }
42
42
 
43
- @page {
44
- size: 6in 9in;
45
- margin: 0.85in 0.75in;
46
43
  }
47
44
 
48
45
  body {
@@ -82,6 +79,7 @@ hr { border: 0; border-top: 1px solid var(--color-rule); margin: 1.5em 0; }
82
79
  var theme_default2 = `/* =============================================================================
83
80
  Zine — gutterpress built-in theme (theme.css)
84
81
  High-contrast, punchy, photocopier-friendly. Change the :root tokens from the book's own stylesheet.
82
+ The page SIZE comes from the manifest (Setup > Book), so it is deliberately not set here.
85
83
  ============================================================================= */
86
84
 
87
85
  :root {
@@ -100,11 +98,7 @@ var theme_default2 = `/* =======================================================
100
98
  --fs-h2: 1.8rem;
101
99
  --fs-h3: 1.3rem;
102
100
  --leading: 1.4;
103
- }
104
101
 
105
- @page {
106
- size: 5.5in 8.5in;
107
- margin: 0.4in;
108
102
  }
109
103
 
110
104
  body {
@@ -146,6 +140,7 @@ code, pre { font-family: var(--font-mono); font-size: 0.95em; }
146
140
  var theme_default3 = `/* =============================================================================
147
141
  Technical Document — gutterpress built-in theme (theme.css)
148
142
  Clean sans-serif manual look with clear hierarchy. Change the :root tokens from the book's own stylesheet.
143
+ The page SIZE comes from the manifest (Setup > Book), so it is deliberately not set here.
149
144
  ============================================================================= */
150
145
 
151
146
  :root {
@@ -153,6 +148,7 @@ var theme_default3 = `/* =======================================================
153
148
  --color-ink-muted: #5a5f66; /* captions, secondary text */
154
149
  --color-accent: #0b5fff; /* headings, links */
155
150
  --color-paper: #ffffff; /* page background */
151
+ /* @label Note and code background */
156
152
  --color-tint: #f3f5f9; /* code / note fill */
157
153
  --color-rule: #d6dae0; /* borders, rules */
158
154
 
@@ -165,11 +161,7 @@ var theme_default3 = `/* =======================================================
165
161
  --fs-h2: 1.45rem;
166
162
  --fs-h3: 1.15rem;
167
163
  --leading: 1.5;
168
- }
169
164
 
170
- @page {
171
- size: 8.5in 11in;
172
- margin: 0.9in 1in;
173
165
  }
174
166
 
175
167
  body {
@@ -242,10 +234,10 @@ var theme_default4 = `/* =======================================================
242
234
  --fs-h2: 1.2em;
243
235
  --fs-h3: 1em;
244
236
  --leading: 1.38;
237
+
245
238
  }
246
239
 
247
240
  @page {
248
- margin: 1in;
249
241
  @bottom-center { content: counter(page); font-family: var(--font-body); font-size: 9pt; }
250
242
  }
251
243
 
@@ -406,7 +398,7 @@ import { satisfies, validRange } from "semver";
406
398
  // package.json
407
399
  var package_default = {
408
400
  name: "gutterpress",
409
- version: "0.11.23-alpha.2",
401
+ version: "0.11.23-alpha.4",
410
402
  description: "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
411
403
  author: "itlackey",
412
404
  license: "MPL-2.0",
@@ -541,7 +533,6 @@ function metaFromPackageJson(raw) {
541
533
  ...str(object(pkg.engines)?.gutterpress) ? { gutterpressRange: str(object(pkg.engines)?.gutterpress) } : {},
542
534
  ..."preview" in gp ? { preview: str(gp.preview) ?? null } : {},
543
535
  ...Array.isArray(gp.styles) ? { styles: declaredList(gp.styles) } : {},
544
- ...str(gp.tokensFile) ? { tokensFile: str(gp.tokensFile) } : {},
545
536
  ...str(gp.markdown) ? { markdown: str(gp.markdown) } : {},
546
537
  ...str(gp.components) ? { components: str(gp.components) } : {},
547
538
  ...str(gp.snippets) ? { snippets: str(gp.snippets) } : {},
@@ -607,8 +598,7 @@ function assertExtensionContained(meta) {
607
598
  ...entry ? [entry] : [],
608
599
  ...meta.publish && meta.main?.trim() ? [meta.main.trim()] : [],
609
600
  ...meta.components ? [meta.components] : [],
610
- ...meta.snippets ? [meta.snippets] : [],
611
- ...meta.tokensFile ? [meta.tokensFile] : []
601
+ ...meta.snippets ? [meta.snippets] : []
612
602
  ];
613
603
  for (const rel of declared) {
614
604
  if (pathEscapesFolder(rel)) {
@@ -625,7 +615,6 @@ function resolveExtension(dir, meta, subject) {
625
615
  return {
626
616
  ...markdown ? { markdown } : {},
627
617
  ...styles ? { styles } : {},
628
- ...meta.tokensFile?.trim() ? { tokensFile: meta.tokensFile.trim() } : {},
629
618
  ...components ? { components } : {},
630
619
  ...snippets ? { snippets } : {}
631
620
  };
@@ -2518,7 +2507,12 @@ function splitCells(str2, spans) {
2518
2507
  lastPos = pos;
2519
2508
  }
2520
2509
  } else if (!isEscaped && spans[ch]) {
2521
- pos = spans[ch](str2, pos, max);
2510
+ const end = spans[ch](str2, pos, max);
2511
+ if (ch === 96) {
2512
+ current += str2.substring(lastPos, pos) + str2.substring(pos, end).replace(/\\\|/g, "|");
2513
+ lastPos = end;
2514
+ }
2515
+ pos = end;
2522
2516
  continue;
2523
2517
  }
2524
2518
  isEscaped = ch === 92;
@@ -3753,9 +3747,9 @@ async function loadNpmPackage(packageName, baseDir, version) {
3753
3747
  const looksLikeJsFilename = /\.(m?js|cjs)$/i.test(packageName);
3754
3748
  const suggestedPath = looksLikeJsFilename ? `./${packageName}` : `./plugins/${packageName}.js`;
3755
3749
  if (!looksLikeJsFilename && (!version || !isExactNpmVersion(version))) {
3756
- throw new Error(`Extension "${packageName}${version ? `@${version}` : ""}" is not pinned to an exact version, so it can't be downloaded automatically. Run \`gutterpress ext add ${packageName}\` (or use Book settings > Features in the desktop app) to download it and pin its version in your manifest.`);
3750
+ throw new Error(`Extension "${packageName}${version ? `@${version}` : ""}" is not pinned to an exact version, so it can't be downloaded automatically. Run \`gutterpress ext add ${packageName}\` (or use Book setup > Advanced in the desktop app) to download it and pin its version in your manifest.`);
3757
3751
  }
3758
- throw new Error(`Extension "${packageName}" not found. Install it with \`gutterpress ext add ${version ? `${packageName}@${version}` : packageName}\` (or Book settings > Features > Advanced in the desktop app),
3752
+ throw new Error(`Extension "${packageName}" not found. Install it with \`gutterpress ext add ${version ? `${packageName}@${version}` : packageName}\` (or Book setup > Advanced in the desktop app),
3759
3753
  or reference a local file under \`extensions:\`:
3760
3754
  extensions:
3761
3755
  - ${suggestedPath}`);