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.
Files changed (55) hide show
  1. package/README.md +6 -7
  2. package/dist/{README-8ef336pp.md → README-8db7btxb.md} +13 -19
  3. package/dist/api/index.d.ts +1 -1
  4. package/dist/api/index.js +4 -4
  5. package/dist/{build-encgnv0c.js → build-m78jcpf7.js} +7 -7
  6. package/dist/{cli-xq6djqbj.js → cli-1h17ktsg.js} +84 -113
  7. package/dist/{cli-kh8v4vvw.js → cli-5jzyw06s.js} +1 -1
  8. package/dist/{cli-sdmv4bba.js → cli-h4x81x97.js} +112 -8
  9. package/dist/{cli-evg8sbht.js → cli-n2tsxqpn.js} +1 -1
  10. package/dist/{cli-aqh6brew.js → cli-s6djx4ma.js} +1 -1
  11. package/dist/{cli-pwwfxdgb.js → cli-t8be9yeb.js} +9 -20
  12. package/dist/{cli-pz4bn98t.js → cli-xsrffqzt.js} +19 -13
  13. package/dist/cli.js +12 -12
  14. package/dist/{doctor-5gtpgpd1.js → doctor-j71jqce3.js} +3 -3
  15. package/dist/engine/shared/gcpm-extract.d.ts +8 -0
  16. package/dist/engine/shared/print-area.d.ts +16 -4
  17. package/dist/{engine-tn13gk0b.js → engine-1r6q80tq.js} +2 -2
  18. package/dist/{engine-mc5br8g8.js → engine-m4y10shc.js} +1 -1
  19. package/dist/{ext-wn2a5afq.js → ext-fq2hg9va.js} +7 -7
  20. package/dist/{extension-restore-s3x1618g.js → extension-restore-9dh7c4tp.js} +2 -2
  21. package/dist/{extension-restore-g8jnmmzq.js → extension-restore-tmxtzkm0.js} +4 -4
  22. package/dist/{gutterpress-viewer-701vf4qp.js → gutterpress-viewer-mafsby5k.js} +9 -2
  23. package/dist/{index-2bjcghze.js → index-0wee4408.js} +9 -20
  24. package/dist/{index-x3ema2w3.js → index-7pck1q9c.js} +124 -17
  25. package/dist/{index-0skhjx3e.js → index-nedd07bk.js} +19 -13
  26. package/dist/{index-4x6y8krm.js → index-nvmf22rt.js} +1 -1
  27. package/dist/{index-j5z86r4a.js → index-prqvz3xm.js} +213 -276
  28. package/dist/index.js +5 -5
  29. package/dist/lib/extension-manager.d.ts +8 -7
  30. package/dist/lib/extension-manifest.d.ts +1 -13
  31. package/dist/lib/manifest.d.ts +15 -1
  32. package/dist/lib/markdown/assemble.d.ts +4 -3
  33. package/dist/lib/page-size.d.ts +34 -27
  34. package/dist/lib/printsafe.d.ts +1 -0
  35. package/dist/lib/project-templates.d.ts +9 -0
  36. package/dist/manifest-8afhrk30.yaml +19 -0
  37. package/dist/manifest-d4f9q79e.yaml +23 -0
  38. package/dist/{manifest-eagfhba6.yaml → manifest-gf13sjp8.yaml} +10 -2
  39. package/dist/manifest-my7mdv8j.yaml +23 -0
  40. package/dist/{manifest.schema-t7nx2stg.json → manifest.schema-650pe0d1.json} +15 -3
  41. package/dist/{new-mhs46pw3.js → new-s4zcaepg.js} +7 -7
  42. package/dist/{package-aenwjew3.json → package-awwkt7sa.json} +0 -1
  43. package/dist/{page-rules-nsj3aw42.css → page-rules-fj09xct5.css} +12 -40
  44. package/dist/{plugin.test.js-xgxrd8hf.tpl → plugin.test.js-gxzqqfdh.tpl} +0 -1
  45. package/dist/{plugins-1sxe0dkz.js → plugins-4vaf27n9.js} +3 -3
  46. package/dist/{plugins-2cek4mz1.js → plugins-80emnf31.js} +1 -1
  47. package/dist/{preflight-3k2b1x8e.js → preflight-c7w1xdn3.js} +7 -7
  48. package/dist/{preview-6p9v6rht.js → preview-mzytcwyk.js} +7 -7
  49. package/dist/{publish-qgsngy8s.js → publish-fez14ad4.js} +7 -7
  50. package/dist/render.js +24 -561
  51. package/dist/schema/manifest.types.d.ts +22 -0
  52. package/dist/{tokens-7984461t.css → tokens-ye64p899.css} +5 -12
  53. package/dist/{validate-0v7xw6wa.js → validate-p2chr6hr.js} +7 -7
  54. package/package.json +1 -1
  55. package/dist/manifest-n1gh3qw5.yaml +0 -9
@@ -11,10 +11,10 @@ import {
11
11
  prettify,
12
12
  readExtensionMeta,
13
13
  slugify
14
- } from "./cli-pwwfxdgb.js";
14
+ } from "./cli-t8be9yeb.js";
15
15
  import {
16
16
  log
17
- } from "./cli-aqh6brew.js";
17
+ } from "./cli-s6djx4ma.js";
18
18
  import {
19
19
  UsageError
20
20
  } from "./cli-d8xjns66.js";
@@ -94,6 +94,87 @@ import { existsSync, statSync } from "node:fs";
94
94
  import { resolve, dirname } from "node:path";
95
95
  import { parse as parseYaml, YAMLParseError } from "yaml";
96
96
 
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, "&amp;").replace(/'/g, "&#39;")}'>`;
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
+ };
152
+ }
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
+ }
174
+ }
175
+ return worst;
176
+ }
177
+
97
178
  // src/lib/presets.ts
98
179
  var PRESET_IDS = ["dtrpg", "book", "custom"];
99
180
  var DTRPG_PRESET = {
@@ -124,7 +205,8 @@ var DTRPG_PRESET = {
124
205
  bleed: 9,
125
206
  safe: 36,
126
207
  artSafe: 18,
127
- gutter: 36
208
+ gutter: 36,
209
+ margin: undefined
128
210
  },
129
211
  ink: {
130
212
  maxTac: 240,
@@ -210,7 +292,8 @@ var BOOK_PRESET = {
210
292
  bleed: undefined,
211
293
  safe: 18,
212
294
  artSafe: undefined,
213
- gutter: undefined
295
+ gutter: undefined,
296
+ margin: undefined
214
297
  },
215
298
  ink: {
216
299
  maxTac: 400,
@@ -572,9 +655,28 @@ function resolveCustomPage(c, m) {
572
655
  bleed: c.page?.bleed ?? m.page?.bleed,
573
656
  safe: c.page?.safe ?? m.page?.safe,
574
657
  artSafe: c.page?.artSafe ?? m.page?.artSafe,
575
- gutter: c.page?.gutter ?? m.page?.gutter
658
+ gutter: c.page?.gutter ?? m.page?.gutter,
659
+ margin: c.page?.margin ?? m.page?.margin
576
660
  };
577
661
  }
662
+ var MARGIN_EDGES = ["top", "bottom", "inside", "outside"];
663
+ function validatePageMargin(margin, size) {
664
+ const edges = isPlainObject(margin) && Object.keys(margin).every((k) => MARGIN_EDGES.includes(k)) && MARGIN_EDGES.every((e) => isNonNegativePoints(margin[e]));
665
+ if (!edges) {
666
+ throw new UsageError("Manifest field `page.margin` must set all four edges in points (72pt = 1in), for example\n" + ` page:
667
+ margin:
668
+ top: 54
669
+ bottom: 54
670
+ inside: 54
671
+ outside: 54
672
+ ` + `got ${JSON.stringify(margin)}.`);
673
+ }
674
+ const m = margin;
675
+ if (m.inside + m.outside >= size.width || m.top + m.bottom >= size.height) {
676
+ 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).`);
677
+ }
678
+ return m;
679
+ }
578
680
  function resolveWithPreset(cliOverrides, manifest, preset) {
579
681
  const m = manifest;
580
682
  const c = cliOverrides;
@@ -627,6 +729,9 @@ function resolveWithPreset(cliOverrides, manifest, preset) {
627
729
  throw new UsageError("Manifest field `extensions` must be a list of specifiers.");
628
730
  }
629
731
  const extensions = rawExtensions.map((entry, index) => ({ entry, index })).filter(({ entry }) => typeof entry === "string" || entry?.enabled !== false).map(({ entry, index }) => normalizeExtensionEntry(entry, index));
732
+ const page = preset.page ? mergeShape(c.page, m.page, preset.page) : resolveCustomPage(c, m);
733
+ if (page.margin !== undefined && page.margin !== null)
734
+ validatePageMargin(page.margin, page);
630
735
  return {
631
736
  title: c.title ?? m.title ?? "Document",
632
737
  authors: c.authors ?? m.authors ?? [],
@@ -639,7 +744,7 @@ function resolveWithPreset(cliOverrides, manifest, preset) {
639
744
  source: mergeShape(c.source, m.source, preset.source),
640
745
  pdfx: mergeShape(c.pdfx, m.pdfx, preset.pdfx),
641
746
  print: mergeShape(c.print, m.print, preset.print),
642
- page: preset.page ? mergeShape(c.page, m.page, preset.page) : resolveCustomPage(c, m),
747
+ page,
643
748
  ink: mergeShape(c.ink, m.ink, preset.ink),
644
749
  lint: {
645
750
  ...mergeShape(c.lint, m.lint, preset.lint),
@@ -1491,7 +1596,6 @@ async function describeFolder(dir, base, fallbackLabel, labelFrom = prettify) {
1491
1596
  ...meta.description?.trim() ? { description: meta.description.trim() } : {},
1492
1597
  ...meta.author?.trim() ? { author: meta.author.trim() } : {},
1493
1598
  ...meta.preview !== undefined ? { preview: meta.preview } : {},
1494
- ...meta.tokensFile?.trim() ? { tokensFile: meta.tokensFile.trim() } : {},
1495
1599
  ...styles.length > 0 ? { styles } : {},
1496
1600
  carries: extensionCarries(meta),
1497
1601
  dir
@@ -2026,4 +2130,4 @@ async function restoreForCommand(dir, options) {
2026
2130
  log.warn(problem);
2027
2131
  }
2028
2132
 
2029
- export { 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 };
2133
+ 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 };
@@ -11,7 +11,7 @@ import {
11
11
  import {
12
12
  PACKAGE_VERSION,
13
13
  log
14
- } from "./cli-aqh6brew.js";
14
+ } from "./cli-s6djx4ma.js";
15
15
  import {
16
16
  __require
17
17
  } from "./cli-37x76zdn.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  package_default
3
- } from "./cli-kh8v4vvw.js";
3
+ } from "./cli-5jzyw06s.js";
4
4
 
5
5
  // src/utils/logger.ts
6
6
  var currentLevel = "INFO";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  PACKAGE_VERSION,
3
3
  debug
4
- } from "./cli-aqh6brew.js";
4
+ } from "./cli-s6djx4ma.js";
5
5
  import {
6
6
  isExactNpmVersion,
7
7
  isValidNpmPackageName,
@@ -24,6 +24,7 @@ import { pathToFileURL } from "node:url";
24
24
  var theme_default = `/* =============================================================================
25
25
  Clean Book — gutterpress built-in theme (theme.css)
26
26
  A calm, classic long-form book look. Change the :root tokens from the book's own stylesheet.
27
+ The page SIZE comes from the manifest (Setup > Details), so it is deliberately not set here.
27
28
  ============================================================================= */
28
29
 
29
30
  :root {
@@ -42,11 +43,7 @@ var theme_default = `/* ========================================================
42
43
  --fs-h2: 1.5rem;
43
44
  --fs-h3: 1.2rem;
44
45
  --leading: 1.55;
45
- }
46
46
 
47
- @page {
48
- size: 6in 9in;
49
- margin: 0.85in 0.75in;
50
47
  }
51
48
 
52
49
  body {
@@ -86,6 +83,7 @@ hr { border: 0; border-top: 1px solid var(--color-rule); margin: 1.5em 0; }
86
83
  var theme_default2 = `/* =============================================================================
87
84
  Zine — gutterpress built-in theme (theme.css)
88
85
  High-contrast, punchy, photocopier-friendly. Change the :root tokens from the book's own stylesheet.
86
+ The page SIZE comes from the manifest (Setup > Details), so it is deliberately not set here.
89
87
  ============================================================================= */
90
88
 
91
89
  :root {
@@ -104,11 +102,7 @@ var theme_default2 = `/* =======================================================
104
102
  --fs-h2: 1.8rem;
105
103
  --fs-h3: 1.3rem;
106
104
  --leading: 1.4;
107
- }
108
105
 
109
- @page {
110
- size: 5.5in 8.5in;
111
- margin: 0.4in;
112
106
  }
113
107
 
114
108
  body {
@@ -150,6 +144,7 @@ code, pre { font-family: var(--font-mono); font-size: 0.95em; }
150
144
  var theme_default3 = `/* =============================================================================
151
145
  Technical Document — gutterpress built-in theme (theme.css)
152
146
  Clean sans-serif manual look with clear hierarchy. Change the :root tokens from the book's own stylesheet.
147
+ The page SIZE comes from the manifest (Setup > Details), so it is deliberately not set here.
153
148
  ============================================================================= */
154
149
 
155
150
  :root {
@@ -157,6 +152,7 @@ var theme_default3 = `/* =======================================================
157
152
  --color-ink-muted: #5a5f66; /* captions, secondary text */
158
153
  --color-accent: #0b5fff; /* headings, links */
159
154
  --color-paper: #ffffff; /* page background */
155
+ /* @label Note and code background */
160
156
  --color-tint: #f3f5f9; /* code / note fill */
161
157
  --color-rule: #d6dae0; /* borders, rules */
162
158
 
@@ -169,11 +165,7 @@ var theme_default3 = `/* =======================================================
169
165
  --fs-h2: 1.45rem;
170
166
  --fs-h3: 1.15rem;
171
167
  --leading: 1.5;
172
- }
173
168
 
174
- @page {
175
- size: 8.5in 11in;
176
- margin: 0.9in 1in;
177
169
  }
178
170
 
179
171
  body {
@@ -246,10 +238,10 @@ var theme_default4 = `/* =======================================================
246
238
  --fs-h2: 1.2em;
247
239
  --fs-h3: 1em;
248
240
  --leading: 1.38;
241
+
249
242
  }
250
243
 
251
244
  @page {
252
- margin: 1in;
253
245
  @bottom-center { content: counter(page); font-family: var(--font-body); font-size: 9pt; }
254
246
  }
255
247
 
@@ -433,7 +425,6 @@ function metaFromPackageJson(raw) {
433
425
  ...str(object(pkg.engines)?.gutterpress) ? { gutterpressRange: str(object(pkg.engines)?.gutterpress) } : {},
434
426
  ..."preview" in gp ? { preview: str(gp.preview) ?? null } : {},
435
427
  ...Array.isArray(gp.styles) ? { styles: declaredList(gp.styles) } : {},
436
- ...str(gp.tokensFile) ? { tokensFile: str(gp.tokensFile) } : {},
437
428
  ...str(gp.markdown) ? { markdown: str(gp.markdown) } : {},
438
429
  ...str(gp.components) ? { components: str(gp.components) } : {},
439
430
  ...str(gp.snippets) ? { snippets: str(gp.snippets) } : {},
@@ -499,8 +490,7 @@ function assertExtensionContained(meta) {
499
490
  ...entry ? [entry] : [],
500
491
  ...meta.publish && meta.main?.trim() ? [meta.main.trim()] : [],
501
492
  ...meta.components ? [meta.components] : [],
502
- ...meta.snippets ? [meta.snippets] : [],
503
- ...meta.tokensFile ? [meta.tokensFile] : []
493
+ ...meta.snippets ? [meta.snippets] : []
504
494
  ];
505
495
  for (const rel of declared) {
506
496
  if (pathEscapesFolder(rel)) {
@@ -517,7 +507,6 @@ function resolveExtension(dir, meta, subject) {
517
507
  return {
518
508
  ...markdown ? { markdown } : {},
519
509
  ...styles ? { styles } : {},
520
- ...meta.tokensFile?.trim() ? { tokensFile: meta.tokensFile.trim() } : {},
521
510
  ...components ? { components } : {},
522
511
  ...snippets ? { snippets } : {}
523
512
  };
@@ -3581,9 +3570,9 @@ async function loadNpmPackage(packageName, baseDir, version) {
3581
3570
  const looksLikeJsFilename = /\.(m?js|cjs)$/i.test(packageName);
3582
3571
  const suggestedPath = looksLikeJsFilename ? `./${packageName}` : `./plugins/${packageName}.js`;
3583
3572
  if (!looksLikeJsFilename && (!version || !isExactNpmVersion(version))) {
3584
- 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.`);
3573
+ 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 > Looks & features > Advanced in the desktop app) to download it and pin its version in your manifest.`);
3585
3574
  }
3586
- 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),
3575
+ throw new Error(`Extension "${packageName}" not found. Install it with \`gutterpress ext add ${version ? `${packageName}@${version}` : packageName}\` (or Book setup > Looks & features > Advanced in the desktop app),
3587
3576
  or reference a local file under \`extensions:\`:
3588
3577
  extensions:
3589
3578
  - ${suggestedPath}`);
@@ -530,12 +530,18 @@ function parseMargin(value) {
530
530
  const d = parts[3] ?? b;
531
531
  return { top: a, right: b, bottom: c, left: d };
532
532
  }
533
+ var DEFAULT_PAGE_MARGIN_PT = 72;
533
534
  function resolvePage(model, ctx = {}) {
534
535
  const wanted = new Set(ctx.pseudos ?? []);
535
536
  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));
536
537
  const decls = {};
537
538
  const marginBoxes = {};
538
- const margin = { top: 72, right: 72, bottom: 72, left: 72 };
539
+ const margin = {
540
+ top: DEFAULT_PAGE_MARGIN_PT,
541
+ right: DEFAULT_PAGE_MARGIN_PT,
542
+ bottom: DEFAULT_PAGE_MARGIN_PT,
543
+ left: DEFAULT_PAGE_MARGIN_PT
544
+ };
539
545
  for (const rule of applicable) {
540
546
  for (const [prop, value] of Object.entries(rule.decls)) {
541
547
  if (prop === "margin")
@@ -1134,7 +1140,7 @@ import { fileURLToPath } from "node:url";
1134
1140
  var favicon_default = "./favicon-272ga6y0.ico";
1135
1141
 
1136
1142
  // src/assets/manifest.schema.json
1137
- var manifest_schema_default = "./manifest.schema-t7nx2stg.json";
1143
+ var manifest_schema_default = "./manifest.schema-650pe0d1.json";
1138
1144
 
1139
1145
  // src/assets/preview/scripts/preview-interface.js
1140
1146
  var preview_interface_default = "./preview-interface-nnmrxyqm.js";
@@ -1149,31 +1155,31 @@ var preview_shell_default = "./preview-shell-wk9k3gcd.js";
1149
1155
  var CGATS21_CRPC1_default = "./CGATS21_CRPC1-g0e3k7kr.icc";
1150
1156
 
1151
1157
  // src/assets/engine/gutterpress-viewer.js
1152
- var gutterpress_viewer_default = "./gutterpress-viewer-701vf4qp.js";
1158
+ var gutterpress_viewer_default = "./gutterpress-viewer-mafsby5k.js";
1153
1159
 
1154
1160
  // src/assets/engine/gutterpress-agent.js
1155
1161
  var gutterpress_agent_default = "./gutterpress-agent-d29ry3ak.js";
1156
1162
 
1157
1163
  // src/assets/templates/book/manifest.yaml
1158
- var manifest_default = "./manifest-n1gh3qw5.yaml";
1164
+ var manifest_default = "./manifest-8afhrk30.yaml";
1159
1165
 
1160
1166
  // src/assets/templates/book/chapter-01.md
1161
1167
  var chapter_01_default = "./chapter-01-gsbjt584.md";
1162
1168
 
1163
1169
  // src/assets/templates/zine/manifest.yaml
1164
- var manifest_default2 = "./manifest-n1gh3qw5.yaml";
1170
+ var manifest_default2 = "./manifest-d4f9q79e.yaml";
1165
1171
 
1166
1172
  // src/assets/templates/zine/chapter-01.md
1167
1173
  var chapter_01_default2 = "./chapter-01-wgjfz4w6.md";
1168
1174
 
1169
1175
  // src/assets/templates/technical/manifest.yaml
1170
- var manifest_default3 = "./manifest-n1gh3qw5.yaml";
1176
+ var manifest_default3 = "./manifest-my7mdv8j.yaml";
1171
1177
 
1172
1178
  // src/assets/templates/technical/chapter-01.md
1173
1179
  var chapter_01_default3 = "./chapter-01-6fn9pvd0.md";
1174
1180
 
1175
1181
  // src/assets/templates/paper/manifest.yaml
1176
- var manifest_default4 = "./manifest-eagfhba6.yaml";
1182
+ var manifest_default4 = "./manifest-gf13sjp8.yaml";
1177
1183
 
1178
1184
  // src/assets/templates/paper/chapter-01.md
1179
1185
  var chapter_01_default4 = "./chapter-01-s71xrf5q.md";
@@ -1200,13 +1206,13 @@ var fixture_default = "./fixture-2qnyqgb5.md";
1200
1206
  var expected_default = "./expected-ycmacem8.html";
1201
1207
 
1202
1208
  // src/assets/extension-templates/plugin/test/plugin.test.js.tpl
1203
- var plugin_test_js_default = "./plugin.test.js-xgxrd8hf.tpl";
1209
+ var plugin_test_js_default = "./plugin.test.js-gxzqqfdh.tpl";
1204
1210
 
1205
1211
  // src/assets/extension-templates/look/package.json
1206
- var package_default2 = "./package-aenwjew3.json";
1212
+ var package_default2 = "./package-awwkt7sa.json";
1207
1213
 
1208
1214
  // src/assets/extension-templates/look/README.md
1209
- var README_default2 = "./README-8ef336pp.md";
1215
+ var README_default2 = "./README-8db7btxb.md";
1210
1216
 
1211
1217
  // src/assets/extension-templates/look/components.yaml
1212
1218
  var components_default = "./components-zzqdpt3m.yaml";
@@ -1215,7 +1221,7 @@ var components_default = "./components-zzqdpt3m.yaml";
1215
1221
  var callout_default = "./callout-hv56m16h.md";
1216
1222
 
1217
1223
  // src/assets/extension-templates/look/styles/tokens.css
1218
- var tokens_default = "./tokens-7984461t.css";
1224
+ var tokens_default = "./tokens-ye64p899.css";
1219
1225
 
1220
1226
  // src/assets/extension-templates/look/styles/base.css
1221
1227
  var base_default = "./base-ypqh9n7f.css";
@@ -1227,7 +1233,7 @@ var components_default2 = "./components-aam0fe2z.css";
1227
1233
  var page_templates_default = "./page-templates-tx9ryt19.css";
1228
1234
 
1229
1235
  // src/assets/extension-templates/look/styles/page-rules.css
1230
- var page_rules_default = "./page-rules-nsj3aw42.css";
1236
+ var page_rules_default = "./page-rules-fj09xct5.css";
1231
1237
 
1232
1238
  // src/assets/extension-templates/look/styles/book.css
1233
1239
  var book_default = "./book-ted3tzrp.css";
@@ -2679,4 +2685,4 @@ ${lines.length ? lines.join(`
2679
2685
  `);
2680
2686
  }
2681
2687
 
2682
- export { lastPageMode, extract, resolvePage, getAssetPath, MARGIN_BOX_IGNORED_PROPERTIES, build };
2688
+ export { lastPageMode, DEFAULT_PAGE_MARGIN_PT, getAssetPath, MARGIN_BOX_IGNORED_PROPERTIES, build };
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-5jzyw06s.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-s4zcaepg.js").then((m) => m.default),
24
+ preview: () => import("./preview-mzytcwyk.js").then((m) => m.default),
25
+ build: () => import("./build-m78jcpf7.js").then((m) => m.default),
26
+ publish: () => import("./publish-fez14ad4.js").then((m) => m.default),
27
+ validate: () => import("./validate-p2chr6hr.js").then((m) => m.default),
28
+ preflight: () => import("./preflight-c7w1xdn3.js").then((m) => m.default),
29
+ doctor: () => import("./doctor-j71jqce3.js").then((m) => m.default),
30
+ ext: () => import("./ext-fq2hg9va.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-s4zcaepg.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-c7w1xdn3.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-fq2hg9va.js");
88
88
  if (!EXT_SUBCOMMANDS.includes(subcommand)) {
89
89
  throw new UsageError(`gutterpress ext: unknown command "${subcommand}"`);
90
90
  }
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  getSystemDiagnostics
3
- } from "./cli-evg8sbht.js";
3
+ } from "./cli-n2tsxqpn.js";
4
4
  import"./cli-asap4t1z.js";
5
5
  import {
6
6
  log
7
- } from "./cli-aqh6brew.js";
7
+ } from "./cli-s6djx4ma.js";
8
8
  import {
9
9
  UsageError,
10
10
  rejectExtraPositionals,
11
11
  rejectUnknownFlags
12
12
  } from "./cli-d8xjns66.js";
13
- import"./cli-kh8v4vvw.js";
13
+ import"./cli-5jzyw06s.js";
14
14
  import"./cli-46ycxe6r.js";
15
15
  import"./cli-37x76zdn.js";
16
16
 
@@ -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,7 +1,7 @@
1
1
  import {
2
2
  build
3
- } from "./index-4x6y8krm.js";
4
- import"./index-0skhjx3e.js";
3
+ } from "./index-nvmf22rt.js";
4
+ import"./index-nedd07bk.js";
5
5
  import {
6
6
  BuildError
7
7
  } from "./index-46ycxe6r.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  build
3
- } from "./cli-pz4bn98t.js";
3
+ } from "./cli-xsrffqzt.js";
4
4
  import"./cli-eyyggect.js";
5
5
  import"./cli-asap4t1z.js";
6
6
  import {
@@ -2,10 +2,10 @@ import {
2
2
  importExtensionFromFile,
3
3
  importExtensionFromUrl,
4
4
  searchNpmExtensions
5
- } from "./cli-xq6djqbj.js";
6
- import"./cli-evg8sbht.js";
5
+ } from "./cli-1h17ktsg.js";
6
+ import"./cli-n2tsxqpn.js";
7
7
  import"./cli-ht1bcqdd.js";
8
- import"./cli-pz4bn98t.js";
8
+ import"./cli-xsrffqzt.js";
9
9
  import"./cli-2ppw6q9v.js";
10
10
  import"./cli-eyyggect.js";
11
11
  import"./cli-asap4t1z.js";
@@ -18,12 +18,12 @@ import {
18
18
  removeExtension,
19
19
  setExtensionEnabled,
20
20
  updateExtensions
21
- } from "./cli-sdmv4bba.js";
21
+ } from "./cli-h4x81x97.js";
22
22
  import {
23
23
  isPathSpecifier,
24
24
  parseExtensionSpecifier
25
- } from "./cli-pwwfxdgb.js";
26
- import"./cli-aqh6brew.js";
25
+ } from "./cli-t8be9yeb.js";
26
+ import"./cli-s6djx4ma.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-5jzyw06s.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-7pck1q9c.js";
7
+ import"./index-0wee4408.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-h4x81x97.js";
7
+ import"./cli-t8be9yeb.js";
8
+ import"./cli-s6djx4ma.js";
9
9
  import"./cli-d8xjns66.js";
10
- import"./cli-kh8v4vvw.js";
10
+ import"./cli-5jzyw06s.js";
11
11
  import"./cli-46ycxe6r.js";
12
12
  import"./cli-y28j019d.js";
13
13
  import"./cli-37x76zdn.js";