gutterpress 0.10.3 → 0.10.4-beta.1

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/dist/api/index.js CHANGED
@@ -95,12 +95,12 @@ import {
95
95
  syncProject,
96
96
  testRemoteAccess,
97
97
  validateProjectPlugins
98
- } from "../index-wdkvhdzj.js";
98
+ } from "../index-g0vvds4s.js";
99
99
  import {
100
100
  BuildError,
101
101
  DEFAULT_PRINT_OPTS,
102
102
  readyProbeExpr
103
- } from "../index-wbm6p5j3.js";
103
+ } from "../index-p4yq14qw.js";
104
104
  import {
105
105
  AUTO_SNAPSHOT_MESSAGE,
106
106
  HISTORY_PAGE_LIMIT,
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  executeAndReport
3
- } from "./cli-qx6mak9k.js";
3
+ } from "./cli-avsnd8r3.js";
4
4
  import {
5
5
  log
6
- } from "./cli-qbasg0r3.js";
6
+ } from "./cli-2y07zn1g.js";
7
7
  import {
8
8
  UsageError,
9
9
  rejectExtraPositionals,
10
10
  rejectUnknownFlags
11
- } from "./cli-yezsxehb.js";
12
- import"./cli-c2yvktan.js";
11
+ } from "./cli-00gqsfce.js";
12
+ import"./cli-7hay1r0h.js";
13
13
  import"./cli-c41yr7he.js";
14
14
  import {
15
15
  EXIT_CODES
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  runBuild,
3
3
  splitOutPath
4
- } from "./cli-qx6mak9k.js";
4
+ } from "./cli-avsnd8r3.js";
5
5
  import {
6
6
  log
7
- } from "./cli-qbasg0r3.js";
7
+ } from "./cli-2y07zn1g.js";
8
8
  import {
9
9
  UsageError,
10
10
  parseEngine,
@@ -12,8 +12,8 @@ import {
12
12
  parsePdfxFlavor,
13
13
  rejectExtraPositionals,
14
14
  rejectUnknownFlags
15
- } from "./cli-yezsxehb.js";
16
- import"./cli-c2yvktan.js";
15
+ } from "./cli-00gqsfce.js";
16
+ import"./cli-7hay1r0h.js";
17
17
  import"./cli-c41yr7he.js";
18
18
  import {
19
19
  BuildError
@@ -4,7 +4,7 @@ import {
4
4
  // package.json
5
5
  var package_default = {
6
6
  name: "gutterpress",
7
- version: "0.10.3",
7
+ version: "0.10.4-beta.1",
8
8
  description: "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
9
9
  author: "itlackey",
10
10
  license: "MPL-2.0",
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  package_default
3
- } from "./cli-yezsxehb.js";
3
+ } from "./cli-00gqsfce.js";
4
4
  import {
5
5
  execCapture,
6
6
  findTool,
@@ -171,7 +171,7 @@ function readDevToolsUrl(proc) {
171
171
  return new Promise((resolve, reject) => {
172
172
  let buf = "";
173
173
  const timer = setTimeout(() => reject(new Error(`Chromium did not report a DevTools URL:
174
- ${buf}`)), 20000);
174
+ ${buf}`)), 60000);
175
175
  proc.stderr.on("data", (d) => {
176
176
  buf += String(d);
177
177
  const m = /ws:\/\/[^\s]+/.exec(buf);
@@ -1445,7 +1445,7 @@ var preview_shell_default = "./preview-shell-gqnc5xxe.js";
1445
1445
  var CGATS21_CRPC1_default = "./CGATS21_CRPC1-g0e3k7kr.icc";
1446
1446
 
1447
1447
  // src/assets/engine/gutterpress-viewer.js
1448
- var gutterpress_viewer_default = "./gutterpress-viewer-mfeccbys.js";
1448
+ var gutterpress_viewer_default = "./gutterpress-viewer-k0xrt5hw.js";
1449
1449
 
1450
1450
  // src/assets/engine/gutterpress-agent.js
1451
1451
  var gutterpress_agent_default = "./gutterpress-agent-cazqstr1.js";
@@ -2006,7 +2006,8 @@ ${flushCss}`);
2006
2006
  const widthOffenders = await findWidthOffenders(page, model, 2 * (tier2.geometry.bleed + tier2.geometry.slug), sheetViewport);
2007
2007
  const describe = (list) => list.map((o) => {
2008
2008
  const fix = o.left !== undefined && o.left < -1 ? "keep it inside the page content box" : "give it an explicit width";
2009
- return ` ${o.desc} ${Math.round(o.px)}px > ${Math.round(widthOffenders.limitPx)}px content box (${fix})`;
2009
+ const lim = o.limit ?? widthOffenders.limitPx;
2010
+ return ` ${o.desc} — ${Math.round(o.px)}px > ${Math.round(lim)}px content box (${fix})`;
2010
2011
  }).join(`
2011
2012
  `);
2012
2013
  if (widthOffenders.boxes.length) {
@@ -2528,20 +2529,42 @@ async function findWidthOffenders(page, model, bleedSlugExtensionPt, restoreView
2528
2529
  resolvePage(model),
2529
2530
  ...model.pageNames.filter((n) => !n.startsWith("gp-") || n.startsWith("gp--flush-")).map((n) => resolvePage(model, { name: n }))
2530
2531
  ];
2531
- const maxContentPt = Math.max(...contexts.map((c) => c.geometry.width - c.geometry.margin.left - c.geometry.margin.right)) + bleedSlugExtensionPt;
2532
- const limitPx = maxContentPt * 96 / 72;
2532
+ const contentPxOf = (c) => (c.geometry.width - c.geometry.margin.left - c.geometry.margin.right + bleedSlugExtensionPt) * 96 / 72;
2533
+ const defaultLimitPx = contentPxOf(contexts[0]);
2534
+ const namedLimits = {};
2535
+ model.pageNames.filter((n) => !n.startsWith("gp-") || n.startsWith("gp--flush-")).forEach((n) => {
2536
+ namedLimits[n] = contentPxOf(resolvePage(model, { name: n }));
2537
+ });
2538
+ const widths = [...new Set([defaultLimitPx, ...Object.values(namedLimits)])].sort((a, b) => a - b);
2539
+ const limitPx = Math.max(...widths);
2533
2540
  await page.evaluate(`Promise.allSettled(
2534
2541
  [...document.images].map((i) => i.decode().catch(() => {}))
2535
2542
  )`);
2536
2543
  try {
2537
- await page.send("Emulation.setDeviceMetricsOverride", {
2538
- width: Math.ceil(limitPx),
2539
- height: 1080,
2540
- deviceScaleFactor: 1,
2541
- mobile: false
2542
- });
2543
- const boxes = JSON.parse(await page.evaluate(`(() => {
2544
- const LIMIT = ${limitPx} + 1;
2544
+ const boxes = [];
2545
+ for (const widthPx of widths) {
2546
+ await page.send("Emulation.setDeviceMetricsOverride", {
2547
+ width: Math.ceil(widthPx),
2548
+ height: 1080,
2549
+ deviceScaleFactor: 1,
2550
+ mobile: false
2551
+ });
2552
+ boxes.push(...JSON.parse(await page.evaluate(`(() => {
2553
+ const LIMIT = ${widthPx} + 1;
2554
+ const NAMED = ${JSON.stringify(namedLimits)};
2555
+ const DEFAULT_LIMIT = ${defaultLimitPx};
2556
+ // The page an element lands on: the nearest ancestor with a non-auto
2557
+ // page property, else the default page. Chromium reports the computed
2558
+ // value on the assigned element only -- descendants read "auto" -- so
2559
+ // this walk is what turns it into the USED value.
2560
+ const limitOf = (el) => {
2561
+ for (let e = el; e; e = e.parentElement) {
2562
+ const n = getComputedStyle(e).page;
2563
+ if (n && n !== "auto") return NAMED[n] ?? DEFAULT_LIMIT;
2564
+ }
2565
+ return DEFAULT_LIMIT;
2566
+ };
2567
+ const mine = (el) => Math.abs(limitOf(el) - ${widthPx}) < 0.5;
2545
2568
  const desc = ${DESC_JS};
2546
2569
  // Shrink-to-fit only reacts to overflow that ESCAPES: a clipping or
2547
2570
  // scrolling ancestor contains its subtree's overflow, so the
@@ -2558,7 +2581,9 @@ async function findWidthOffenders(page, model, bleedSlugExtensionPt, restoreView
2558
2581
  // response.
2559
2582
  const clipEdges = ${CLIP_EDGES_JS};
2560
2583
  const out = [];
2584
+ const boxEls = [];
2561
2585
  for (const el of document.querySelectorAll("*")) {
2586
+ if (!mine(el)) continue;
2562
2587
  const r = el.getBoundingClientRect();
2563
2588
  const right = Math.max(r.right, r.left + r.width);
2564
2589
  // Flag right-edge overflow (fixed-width blocks, negative-margin
@@ -2574,11 +2599,74 @@ async function findWidthOffenders(page, model, bleedSlugExtensionPt, restoreView
2574
2599
  if (c.getBoundingClientRect().width >= r.width - 1) { deepest = false; break; }
2575
2600
  }
2576
2601
  if (!deepest) continue;
2577
- out.push({ desc: desc(el), px: Math.max(r.width, right), left: r.left });
2602
+ out.push({ desc: desc(el), px: Math.max(r.width, right), left: r.left, limit: limitOf(el) });
2603
+ boxEls.push(el);
2578
2604
  if (out.length >= 20) break;
2579
2605
  }
2606
+
2607
+ // pass 1b -- SCROLLABLE overflow, which the border-box walk above
2608
+ // cannot see. querySelectorAll("*") returns elements and
2609
+ // getBoundingClientRect() measures their border boxes, so a
2610
+ // ::before / ::after that sticks out is invisible to it -- while its
2611
+ // overflow still reaches the document and still shrinks the book.
2612
+ // scrollWidth DOES account for pseudo-elements, so it is the one
2613
+ // cheap read that closes the gap.
2614
+ //
2615
+ // MEASURED, the field guide: .dc-spray::before is a decorative skewed
2616
+ // tab at right:-8px, width:14px. It escaped its shell (scrollWidth 394
2617
+ // vs clientWidth 384), Chromium's print widened the layout 696 -> 697
2618
+ // CSS px, that one pixel re-broke a line, and the book printed TWO
2619
+ // PAGES shorter than the preview -- with this audit silent throughout.
2620
+ // page-templates.css had already recorded the gap: "this book still
2621
+ // has one the audit does not catch".
2622
+ //
2623
+ // Same escape rule as above: overflow a clipping ancestor contains
2624
+ // never reaches the document, so it is not a trigger. The element
2625
+ // CARRYING the pseudo is what gets named -- an author cannot select a
2626
+ // pseudo-element to fix it.
2627
+ const scrollCands = [];
2628
+ for (const el of document.querySelectorAll("*")) {
2629
+ if (!mine(el)) continue;
2630
+ const over = el.scrollWidth - el.clientWidth;
2631
+ // clientWidth is 0 on inline/replaced boxes, where scrollWidth
2632
+ // carries no overflow information -- skip rather than guess.
2633
+ if (el.clientWidth <= 0 || over <= 1) continue;
2634
+ // A descendant assigned to a DIFFERENT page is not overflowing this
2635
+ // element's page -- it is laid out against its own, wider one. The
2636
+ // full-bleed art plate is the standard case: it is legitimately
2637
+ // sheet-wide on its own zero-margin page, and its wrapper on the
2638
+ // ordinary page must not be blamed for containing it.
2639
+ if ([...el.querySelectorAll("*")].some((d) => {
2640
+ const n = getComputedStyle(d).page;
2641
+ return n && n !== "auto" && Math.abs((NAMED[n] ?? DEFAULT_LIMIT) - limitOf(el)) >= 0.5;
2642
+ })) continue;
2643
+ // An element that clips its OWN horizontal overflow contains it, so
2644
+ // nothing reaches the document. Read the computed value, not the
2645
+ // declaration: per CSS Overflow 3 an axis set to visible beside a
2646
+ // non-visible one computes to auto, and that really does clip --
2647
+ // while overflow-y: clip leaves x genuinely visible.
2648
+ if (getComputedStyle(el).overflowX !== "visible") continue;
2649
+ const r = el.getBoundingClientRect();
2650
+ const right = r.left + el.scrollWidth;
2651
+ if (right <= LIMIT) continue;
2652
+ if (Math.min(right, clipEdges(el).edges.right) <= LIMIT) continue;
2653
+ scrollCands.push({ el, right, left: r.left });
2654
+ }
2655
+ // Scroll overflow propagates UP: an offender's ancestors all report it
2656
+ // too (html, body, the page wrapper...). Name only the innermost box
2657
+ // of each chain -- the one the author can actually act on.
2658
+ for (const c of scrollCands) {
2659
+ if (out.length >= 20) break;
2660
+ if (scrollCands.some((o) => o !== c && c.el.contains(o.el))) continue;
2661
+ // The border-box pass already named a descendant, so this element's
2662
+ // scroll overflow is that box's, reported one level too high.
2663
+ if (boxEls.some((b) => c.el.contains(b))) continue;
2664
+ if (out.some((o) => o.desc === desc(c.el))) continue;
2665
+ out.push({ desc: desc(c.el), px: c.right, left: c.left, limit: limitOf(c.el) });
2666
+ }
2580
2667
  return JSON.stringify(out);
2581
- })()`));
2668
+ })()`)));
2669
+ }
2582
2670
  const replaced = JSON.parse(await page.evaluate(`(() => {
2583
2671
  const LIMIT = ${limitPx} + 1;
2584
2672
  const desc = ${DESC_JS};
@@ -13,12 +13,12 @@ import {
13
13
  stampCreator,
14
14
  stripAnnotations,
15
15
  warn
16
- } from "./cli-qbasg0r3.js";
16
+ } from "./cli-2y07zn1g.js";
17
17
  import {
18
18
  DEBOUNCE,
19
19
  UsageError,
20
20
  resolvePort
21
- } from "./cli-yezsxehb.js";
21
+ } from "./cli-00gqsfce.js";
22
22
  import {
23
23
  MARGIN_BOX_IGNORED_PROPERTIES,
24
24
  RENDER_TIMEOUT_MS,
@@ -27,7 +27,7 @@ import {
27
27
  getAssetPath,
28
28
  getBrowser,
29
29
  prewarmBrowser
30
- } from "./cli-c2yvktan.js";
30
+ } from "./cli-7hay1r0h.js";
31
31
  import {
32
32
  INSTALL_HINTS,
33
33
  execCapture,
@@ -1100,7 +1100,6 @@ var riskyProperties = new Set([
1100
1100
  "backdrop-filter",
1101
1101
  "mix-blend-mode",
1102
1102
  "background-blend-mode",
1103
- "isolation",
1104
1103
  "animation",
1105
1104
  "animation-name",
1106
1105
  "transition",
@@ -1381,12 +1380,12 @@ async function runLint(opts = {}) {
1381
1380
  const { manifest, manifestDir } = await loadManifestWithPath(opts.manifest, {
1382
1381
  explicit: opts.manifest !== undefined
1383
1382
  });
1384
- resolveConfig({}, manifest);
1383
+ const resolved = resolveConfig({}, manifest);
1385
1384
  let files;
1386
1385
  if (opts.files) {
1387
1386
  files = await glob([opts.files], { nodir: true, ignore: ["**/*.min.css"] });
1388
1387
  } else {
1389
- const relStyles = await resolveActiveStyles(manifestDir, manifest.styles);
1388
+ const relStyles = await resolveActiveStyles(manifestDir, resolved.styles);
1390
1389
  files = relStyles.map((rel) => resolve2(manifestDir, rel)).filter((f) => !f.endsWith(".min.css"));
1391
1390
  }
1392
1391
  if (files.length === 0) {
@@ -7538,7 +7537,7 @@ class PdfOutput {
7538
7537
  const rawPdf = pdfxMode ? path8.join(stage, "raw.pdf") : path8.resolve(pdfFile);
7539
7538
  await fsp2.mkdir(path8.dirname(path8.resolve(pdfFile)), { recursive: true });
7540
7539
  log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
7541
- const { buildNativePdf } = await import("./engine-36jts441.js");
7540
+ const { buildNativePdf } = await import("./engine-dzrzyyew.js");
7542
7541
  const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
7543
7542
  title: config.title,
7544
7543
  author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
package/dist/cli.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  UsageError,
7
7
  package_default,
8
8
  rejectUnknownFlags
9
- } from "./cli-yezsxehb.js";
9
+ } from "./cli-00gqsfce.js";
10
10
  import {
11
11
  EXIT_CODES
12
12
  } from "./cli-46ycxe6r.js";
@@ -18,16 +18,16 @@ import {
18
18
  import { defineCommand, parseArgs, runMain } from "citty";
19
19
  import { statSync } from "node:fs";
20
20
  var SUBCOMMANDS = {
21
- new: () => import("./new-2d5a06r1.js").then((m) => m.default),
22
- preview: () => import("./preview-9s96vvsy.js").then((m) => m.default),
23
- build: () => import("./build-g16kk5hn.js").then((m) => m.default),
24
- publish: () => import("./publish-fznwgzsz.js").then((m) => m.default),
25
- lint: () => import("./lint-qr8qcft3.js").then((m) => m.default),
26
- validate: () => import("./validate-64hafnaa.js").then((m) => m.default),
27
- audit: () => import("./audit-sd4p4dq5.js").then((m) => m.default),
28
- preflight: () => import("./preflight-gxxw4391.js").then((m) => m.default),
29
- doctor: () => import("./doctor-kx4th8g4.js").then((m) => m.default),
30
- plugin: () => import("./plugin-kjextnnb.js").then((m) => m.default)
21
+ new: () => import("./new-ca7931w9.js").then((m) => m.default),
22
+ preview: () => import("./preview-k56acsvd.js").then((m) => m.default),
23
+ build: () => import("./build-j6ygk7fv.js").then((m) => m.default),
24
+ publish: () => import("./publish-yyc10rj3.js").then((m) => m.default),
25
+ lint: () => import("./lint-7ngwa1mj.js").then((m) => m.default),
26
+ validate: () => import("./validate-bv3tknh5.js").then((m) => m.default),
27
+ audit: () => import("./audit-8eaaemfk.js").then((m) => m.default),
28
+ preflight: () => import("./preflight-nht6dqvw.js").then((m) => m.default),
29
+ doctor: () => import("./doctor-wtpgvfnr.js").then((m) => m.default),
30
+ plugin: () => import("./plugin-52qk3h7k.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-2d5a06r1.js");
55
+ const { newArgs } = await import("./new-ca7931w9.js");
56
56
  rejectUnknownFlags(commandArgs, newArgs, "new");
57
57
  const parsed2 = 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-gxxw4391.js");
67
+ const { preflightArgs } = await import("./preflight-nht6dqvw.js");
68
68
  rejectUnknownFlags(commandArgs, preflightArgs, "preflight");
69
69
  const parsed2 = parseArgs(commandArgs, {
70
70
  ...preflightArgs,
@@ -88,7 +88,7 @@ async function preflightRequiredInvocations(rawArgs) {
88
88
  if (subcommand !== "add") {
89
89
  throw new UsageError(`gutterpress plugin: unknown command "${subcommand}"`);
90
90
  }
91
- const { pluginAddArgs } = await import("./plugin-kjextnnb.js");
91
+ const { pluginAddArgs } = await import("./plugin-52qk3h7k.js");
92
92
  rejectUnknownFlags(subcommandArgs, pluginAddArgs, "plugin add");
93
93
  const parsed = parseArgs(subcommandArgs, {
94
94
  ...pluginAddArgs,
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  getSystemDiagnostics,
3
3
  log
4
- } from "./cli-qbasg0r3.js";
4
+ } from "./cli-2y07zn1g.js";
5
5
  import {
6
6
  UsageError,
7
7
  rejectExtraPositionals,
8
8
  rejectUnknownFlags
9
- } from "./cli-yezsxehb.js";
9
+ } from "./cli-00gqsfce.js";
10
10
  import"./cli-c41yr7he.js";
11
11
  import"./cli-46ycxe6r.js";
12
12
  import"./cli-37x76zdn.js";
@@ -4,7 +4,7 @@ import {
4
4
  build,
5
5
  connectChromium,
6
6
  getBrowser
7
- } from "./cli-c2yvktan.js";
7
+ } from "./cli-7hay1r0h.js";
8
8
  import"./cli-c41yr7he.js";
9
9
  import {
10
10
  BuildError
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  build
3
- } from "./index-my3v298z.js";
3
+ } from "./index-cm4dywtk.js";
4
4
  import {
5
5
  BuildError,
6
6
  RENDER_TIMEOUT_MS,
7
7
  assertMilestone,
8
8
  connectChromium,
9
9
  getBrowser
10
- } from "./index-wbm6p5j3.js";
10
+ } from "./index-p4yq14qw.js";
11
11
  import"./index-37x76zdn.js";
12
12
 
13
13
  // src/lib/engine.ts
@@ -35,7 +35,6 @@
35
35
  injectBreakMapping: () => injectBreakMapping,
36
36
  fragmentDocument: () => fragmentDocument,
37
37
  contentEdgeRect: () => contentEdgeRect,
38
- compensateTrailingMarginsBeforeAvoids: () => compensateTrailingMarginsBeforeAvoids,
39
38
  compensateRepeatedHeaders: () => compensateRepeatedHeaders,
40
39
  compensateRectoBreaks: () => compensateRectoBreaks,
41
40
  columnReserve: () => columnReserve,
@@ -112,8 +111,22 @@
112
111
 
113
112
  Scope: \`>\` means this only ever reached the flow root's OWN children, so a
114
113
  book whose atomic blocks sit inside \`@page\`/\`@section\` wrappers was never
115
- affected — which is why removing it does not move the dc-op-manual field
116
- guide's remaining 4-page divergence. That one is still open. */
114
+ affected — which is why removing it did not move the dc-op-manual field
115
+ guide's divergence.
116
+
117
+ That separate divergence is now PARTLY closed. Its cause was
118
+ \`compensateTrailingMarginsBeforeAvoids\`, a viewer shim built on the false
119
+ premise that print discards a trailing margin at a fragmentainer edge.
120
+ Measured with printToPDF on the shim's own fixture: print keeps the margin
121
+ and defers the avoid block (8 print pages; the viewer reported 6). Removing
122
+ it took the field guide from viewer 294 / PDF 295 to 295 / 295.
123
+
124
+ STILL OPEN, and NOT what that shim caused: an interior +1 then -1 pair,
125
+ opening after PDF p108 (inside Gutterdruid) and closing before p176
126
+ (Wirephreak), so roughly p109-p153 is one page out of register while the
127
+ totals still agree. Anchor it with image identity, not text — that PDF has
128
+ no extractable body text; \`rabbit-walking.png\` (1379x2530, unique) sits on
129
+ PDF p134 vs viewer folio 135. */
117
130
 
118
131
  /* View mode (\`applySpreadMode\` in fragment.ts): wraps this run's multicol
119
132
  columns into \`--gp-wrap-cols\` ROWS instead of one long row — 2 for
@@ -1315,87 +1328,6 @@
1315
1328
  delete el.dataset.gpOverflowYPriority;
1316
1329
  }
1317
1330
  }
1318
- function compensateTrailingMarginsBeforeAvoids(model, strips) {
1319
- const candidates = new Set;
1320
- for (const decl of model.breaks) {
1321
- if (decl.prop !== "break-inside" || !/^avoid(?:-|$)/.test(decl.value.trim()))
1322
- continue;
1323
- let els;
1324
- try {
1325
- els = Array.from(document.querySelectorAll(decl.selector));
1326
- } catch {
1327
- continue;
1328
- }
1329
- for (const el of els) {
1330
- if (el instanceof HTMLElement && el.closest(".gp-strip"))
1331
- candidates.add(el);
1332
- }
1333
- }
1334
- let compensated = 0;
1335
- const orderedCandidates = Array.from(candidates).sort((a, b) => a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1);
1336
- for (const el of orderedCandidates) {
1337
- if (!/^avoid(?:-|$)/.test(getComputedStyle(el).breakInside))
1338
- continue;
1339
- const prev = el.previousElementSibling;
1340
- const stripEl = el.closest(".gp-strip");
1341
- const strip = strips.find((item) => item.el === stripEl);
1342
- if (!prev || !stripEl || !strip)
1343
- continue;
1344
- const rects = Array.from(el.getClientRects());
1345
- const prevRects = Array.from(prev.getClientRects());
1346
- if (rects.length !== 1 || !prevRects.length)
1347
- continue;
1348
- const rect = rects[0];
1349
- const prevRect = prevRects.at(-1);
1350
- const stripRect = stripEl.getBoundingClientRect();
1351
- const { stride } = stripMetrics(stripEl);
1352
- const zoom = cssZoomOf(stripEl);
1353
- const colOf = (r) => Math.floor(((r.left - stripRect.left) / zoom + 1) / stride);
1354
- const currentCol = colOf(rect);
1355
- if (currentCol !== colOf(prevRect) + 1)
1356
- continue;
1357
- if (Math.abs(rect.top - stripRect.top) / zoom > 0.5)
1358
- continue;
1359
- const marginEnd = parseFloat(getComputedStyle(prev).marginBlockEnd) || 0;
1360
- if (marginEnd <= 0.5)
1361
- continue;
1362
- const remaining = stripEl.clientHeight - (prevRect.bottom - stripRect.top) / zoom;
1363
- const height = rect.height / zoom;
1364
- if (height > remaining + 0.5)
1365
- continue;
1366
- if (height + marginEnd <= remaining + 0.5)
1367
- continue;
1368
- prev.dataset.gpTrailingMargin = "compensated";
1369
- prev.dataset.gpTrailingMarginValue = prev.style.getPropertyValue("margin-block-end");
1370
- prev.dataset.gpTrailingMarginPriority = prev.style.getPropertyPriority("margin-block-end");
1371
- prev.style.setProperty("margin-block-end", "0px");
1372
- compensated++;
1373
- }
1374
- return compensated;
1375
- }
1376
- function restoreTrailingMargins(doc = document) {
1377
- for (const el of Array.from(doc.querySelectorAll('[data-gp-trailing-margin="compensated"]')))
1378
- restoreTrailingMargin(el);
1379
- }
1380
- function restoreTrailingMargin(el) {
1381
- const value = el.dataset.gpTrailingMarginValue ?? "";
1382
- const priority = el.dataset.gpTrailingMarginPriority ?? "";
1383
- if (value)
1384
- el.style.setProperty("margin-block-end", value, priority);
1385
- else
1386
- el.style.removeProperty("margin-block-end");
1387
- delete el.dataset.gpTrailingMargin;
1388
- delete el.dataset.gpTrailingMarginValue;
1389
- delete el.dataset.gpTrailingMarginPriority;
1390
- }
1391
- function restoreIneffectiveTrailingMargins(strips) {
1392
- for (const prev of Array.from(document.querySelectorAll('[data-gp-trailing-margin="compensated"]'))) {
1393
- const target = prev.nextElementSibling;
1394
- if (!target || pageOf(target, strips) !== pageRangeOf(prev, strips)[1]) {
1395
- restoreTrailingMargin(prev);
1396
- }
1397
- }
1398
- }
1399
1331
  function runPageBox(model, name, warnings = []) {
1400
1332
  const right = resolvePage(model, { name, pseudos: ["right"] }).geometry;
1401
1333
  const left = resolvePage(model, { name, pseudos: ["left"] }).geometry;
@@ -1754,14 +1686,12 @@
1754
1686
  await layoutReady;
1755
1687
  makeOverflowFragmentable(strips);
1756
1688
  stabilizeFullHeightPageRoots(model, strips);
1757
- compensateTrailingMarginsBeforeAvoids(model, strips);
1758
1689
  synthesizeColumnBreaks(model);
1759
1690
  measure(strips);
1760
1691
  const blanks = compensateRectoBreaks(model, strips);
1761
1692
  if (blanks)
1762
1693
  measure(strips);
1763
1694
  const headers = opts.compensateHeaders === false ? { tables: 0, passes: 0, warnings: [] } : compensateRepeatedHeaders(strips);
1764
- restoreIneffectiveTrailingMargins(strips);
1765
1695
  const { totalPages } = measure(strips);
1766
1696
  const api = {
1767
1697
  model,
@@ -1774,7 +1704,6 @@
1774
1704
  pageRangeOf: (sel) => pageRangeOf(typeof sel === "string" ? document.querySelector(sel) : sel, strips),
1775
1705
  relayout: () => {
1776
1706
  restoreFullHeightPageRoots();
1777
- restoreTrailingMargins();
1778
1707
  restoreScrollContainers();
1779
1708
  unwrapStrips(strips);
1780
1709
  for (const spacer of Array.from(document.querySelectorAll(".gp-recto-spacer")))
@@ -1784,7 +1713,6 @@
1784
1713
  strips.push(...rebuilt);
1785
1714
  makeOverflowFragmentable(strips);
1786
1715
  stabilizeFullHeightPageRoots(model, strips);
1787
- compensateTrailingMarginsBeforeAvoids(model, strips);
1788
1716
  synthesizeColumnBreaks(model);
1789
1717
  measure(strips);
1790
1718
  api.blankPages = compensateRectoBreaks(model, strips);
@@ -1792,7 +1720,6 @@
1792
1720
  api.warnings = [
1793
1721
  ...new Set([...authoring, ...compensateRepeatedHeaders(strips).warnings])
1794
1722
  ];
1795
- restoreIneffectiveTrailingMargins(strips);
1796
1723
  const r = measure(strips);
1797
1724
  api.totalPages = r.totalPages;
1798
1725
  api.blankPageIndices = blankPageIndices(strips);
@@ -4,7 +4,7 @@ import {
4
4
  launchChromium,
5
5
  marginBoxAlign,
6
6
  marginBoxRectPt
7
- } from "./index-wbm6p5j3.js";
7
+ } from "./index-p4yq14qw.js";
8
8
 
9
9
  // src/engine/compiler/build.ts
10
10
  import { readFile } from "node:fs/promises";
@@ -1521,7 +1521,8 @@ ${flushCss}`);
1521
1521
  const widthOffenders = await findWidthOffenders(page, model, 2 * (tier2.geometry.bleed + tier2.geometry.slug), sheetViewport);
1522
1522
  const describe = (list) => list.map((o) => {
1523
1523
  const fix = o.left !== undefined && o.left < -1 ? "keep it inside the page content box" : "give it an explicit width";
1524
- return ` ${o.desc} ${Math.round(o.px)}px > ${Math.round(widthOffenders.limitPx)}px content box (${fix})`;
1524
+ const lim = o.limit ?? widthOffenders.limitPx;
1525
+ return ` ${o.desc} — ${Math.round(o.px)}px > ${Math.round(lim)}px content box (${fix})`;
1525
1526
  }).join(`
1526
1527
  `);
1527
1528
  if (widthOffenders.boxes.length) {
@@ -2043,20 +2044,42 @@ async function findWidthOffenders(page, model, bleedSlugExtensionPt, restoreView
2043
2044
  resolvePage(model),
2044
2045
  ...model.pageNames.filter((n) => !n.startsWith("gp-") || n.startsWith("gp--flush-")).map((n) => resolvePage(model, { name: n }))
2045
2046
  ];
2046
- const maxContentPt = Math.max(...contexts.map((c) => c.geometry.width - c.geometry.margin.left - c.geometry.margin.right)) + bleedSlugExtensionPt;
2047
- const limitPx = maxContentPt * 96 / 72;
2047
+ const contentPxOf = (c) => (c.geometry.width - c.geometry.margin.left - c.geometry.margin.right + bleedSlugExtensionPt) * 96 / 72;
2048
+ const defaultLimitPx = contentPxOf(contexts[0]);
2049
+ const namedLimits = {};
2050
+ model.pageNames.filter((n) => !n.startsWith("gp-") || n.startsWith("gp--flush-")).forEach((n) => {
2051
+ namedLimits[n] = contentPxOf(resolvePage(model, { name: n }));
2052
+ });
2053
+ const widths = [...new Set([defaultLimitPx, ...Object.values(namedLimits)])].sort((a, b) => a - b);
2054
+ const limitPx = Math.max(...widths);
2048
2055
  await page.evaluate(`Promise.allSettled(
2049
2056
  [...document.images].map((i) => i.decode().catch(() => {}))
2050
2057
  )`);
2051
2058
  try {
2052
- await page.send("Emulation.setDeviceMetricsOverride", {
2053
- width: Math.ceil(limitPx),
2054
- height: 1080,
2055
- deviceScaleFactor: 1,
2056
- mobile: false
2057
- });
2058
- const boxes = JSON.parse(await page.evaluate(`(() => {
2059
- const LIMIT = ${limitPx} + 1;
2059
+ const boxes = [];
2060
+ for (const widthPx of widths) {
2061
+ await page.send("Emulation.setDeviceMetricsOverride", {
2062
+ width: Math.ceil(widthPx),
2063
+ height: 1080,
2064
+ deviceScaleFactor: 1,
2065
+ mobile: false
2066
+ });
2067
+ boxes.push(...JSON.parse(await page.evaluate(`(() => {
2068
+ const LIMIT = ${widthPx} + 1;
2069
+ const NAMED = ${JSON.stringify(namedLimits)};
2070
+ const DEFAULT_LIMIT = ${defaultLimitPx};
2071
+ // The page an element lands on: the nearest ancestor with a non-auto
2072
+ // page property, else the default page. Chromium reports the computed
2073
+ // value on the assigned element only -- descendants read "auto" -- so
2074
+ // this walk is what turns it into the USED value.
2075
+ const limitOf = (el) => {
2076
+ for (let e = el; e; e = e.parentElement) {
2077
+ const n = getComputedStyle(e).page;
2078
+ if (n && n !== "auto") return NAMED[n] ?? DEFAULT_LIMIT;
2079
+ }
2080
+ return DEFAULT_LIMIT;
2081
+ };
2082
+ const mine = (el) => Math.abs(limitOf(el) - ${widthPx}) < 0.5;
2060
2083
  const desc = ${DESC_JS};
2061
2084
  // Shrink-to-fit only reacts to overflow that ESCAPES: a clipping or
2062
2085
  // scrolling ancestor contains its subtree's overflow, so the
@@ -2073,7 +2096,9 @@ async function findWidthOffenders(page, model, bleedSlugExtensionPt, restoreView
2073
2096
  // response.
2074
2097
  const clipEdges = ${CLIP_EDGES_JS};
2075
2098
  const out = [];
2099
+ const boxEls = [];
2076
2100
  for (const el of document.querySelectorAll("*")) {
2101
+ if (!mine(el)) continue;
2077
2102
  const r = el.getBoundingClientRect();
2078
2103
  const right = Math.max(r.right, r.left + r.width);
2079
2104
  // Flag right-edge overflow (fixed-width blocks, negative-margin
@@ -2089,11 +2114,74 @@ async function findWidthOffenders(page, model, bleedSlugExtensionPt, restoreView
2089
2114
  if (c.getBoundingClientRect().width >= r.width - 1) { deepest = false; break; }
2090
2115
  }
2091
2116
  if (!deepest) continue;
2092
- out.push({ desc: desc(el), px: Math.max(r.width, right), left: r.left });
2117
+ out.push({ desc: desc(el), px: Math.max(r.width, right), left: r.left, limit: limitOf(el) });
2118
+ boxEls.push(el);
2093
2119
  if (out.length >= 20) break;
2094
2120
  }
2121
+
2122
+ // pass 1b -- SCROLLABLE overflow, which the border-box walk above
2123
+ // cannot see. querySelectorAll("*") returns elements and
2124
+ // getBoundingClientRect() measures their border boxes, so a
2125
+ // ::before / ::after that sticks out is invisible to it -- while its
2126
+ // overflow still reaches the document and still shrinks the book.
2127
+ // scrollWidth DOES account for pseudo-elements, so it is the one
2128
+ // cheap read that closes the gap.
2129
+ //
2130
+ // MEASURED, the field guide: .dc-spray::before is a decorative skewed
2131
+ // tab at right:-8px, width:14px. It escaped its shell (scrollWidth 394
2132
+ // vs clientWidth 384), Chromium's print widened the layout 696 -> 697
2133
+ // CSS px, that one pixel re-broke a line, and the book printed TWO
2134
+ // PAGES shorter than the preview -- with this audit silent throughout.
2135
+ // page-templates.css had already recorded the gap: "this book still
2136
+ // has one the audit does not catch".
2137
+ //
2138
+ // Same escape rule as above: overflow a clipping ancestor contains
2139
+ // never reaches the document, so it is not a trigger. The element
2140
+ // CARRYING the pseudo is what gets named -- an author cannot select a
2141
+ // pseudo-element to fix it.
2142
+ const scrollCands = [];
2143
+ for (const el of document.querySelectorAll("*")) {
2144
+ if (!mine(el)) continue;
2145
+ const over = el.scrollWidth - el.clientWidth;
2146
+ // clientWidth is 0 on inline/replaced boxes, where scrollWidth
2147
+ // carries no overflow information -- skip rather than guess.
2148
+ if (el.clientWidth <= 0 || over <= 1) continue;
2149
+ // A descendant assigned to a DIFFERENT page is not overflowing this
2150
+ // element's page -- it is laid out against its own, wider one. The
2151
+ // full-bleed art plate is the standard case: it is legitimately
2152
+ // sheet-wide on its own zero-margin page, and its wrapper on the
2153
+ // ordinary page must not be blamed for containing it.
2154
+ if ([...el.querySelectorAll("*")].some((d) => {
2155
+ const n = getComputedStyle(d).page;
2156
+ return n && n !== "auto" && Math.abs((NAMED[n] ?? DEFAULT_LIMIT) - limitOf(el)) >= 0.5;
2157
+ })) continue;
2158
+ // An element that clips its OWN horizontal overflow contains it, so
2159
+ // nothing reaches the document. Read the computed value, not the
2160
+ // declaration: per CSS Overflow 3 an axis set to visible beside a
2161
+ // non-visible one computes to auto, and that really does clip --
2162
+ // while overflow-y: clip leaves x genuinely visible.
2163
+ if (getComputedStyle(el).overflowX !== "visible") continue;
2164
+ const r = el.getBoundingClientRect();
2165
+ const right = r.left + el.scrollWidth;
2166
+ if (right <= LIMIT) continue;
2167
+ if (Math.min(right, clipEdges(el).edges.right) <= LIMIT) continue;
2168
+ scrollCands.push({ el, right, left: r.left });
2169
+ }
2170
+ // Scroll overflow propagates UP: an offender's ancestors all report it
2171
+ // too (html, body, the page wrapper...). Name only the innermost box
2172
+ // of each chain -- the one the author can actually act on.
2173
+ for (const c of scrollCands) {
2174
+ if (out.length >= 20) break;
2175
+ if (scrollCands.some((o) => o !== c && c.el.contains(o.el))) continue;
2176
+ // The border-box pass already named a descendant, so this element's
2177
+ // scroll overflow is that box's, reported one level too high.
2178
+ if (boxEls.some((b) => c.el.contains(b))) continue;
2179
+ if (out.some((o) => o.desc === desc(c.el))) continue;
2180
+ out.push({ desc: desc(c.el), px: c.right, left: c.left, limit: limitOf(c.el) });
2181
+ }
2095
2182
  return JSON.stringify(out);
2096
- })()`));
2183
+ })()`)));
2184
+ }
2097
2185
  const replaced = JSON.parse(await page.evaluate(`(() => {
2098
2186
  const LIMIT = ${limitPx} + 1;
2099
2187
  const desc = ${DESC_JS};
@@ -17,7 +17,7 @@ import {
17
17
  resolveChromiumExecutable,
18
18
  run,
19
19
  spawnCapture
20
- } from "./index-wbm6p5j3.js";
20
+ } from "./index-p4yq14qw.js";
21
21
  import {
22
22
  gitFs,
23
23
  gitScopeFor,
@@ -3978,7 +3978,7 @@ import git from "isomorphic-git";
3978
3978
  // package.json
3979
3979
  var package_default = {
3980
3980
  name: "gutterpress",
3981
- version: "0.10.3",
3981
+ version: "0.10.4-beta.1",
3982
3982
  description: "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
3983
3983
  author: "itlackey",
3984
3984
  license: "MPL-2.0",
@@ -4274,7 +4274,6 @@ var riskyProperties = new Set([
4274
4274
  "backdrop-filter",
4275
4275
  "mix-blend-mode",
4276
4276
  "background-blend-mode",
4277
- "isolation",
4278
4277
  "animation",
4279
4278
  "animation-name",
4280
4279
  "transition",
@@ -4484,12 +4483,12 @@ async function runLint(opts = {}) {
4484
4483
  const { manifest, manifestDir } = await loadManifestWithPath(opts.manifest, {
4485
4484
  explicit: opts.manifest !== undefined
4486
4485
  });
4487
- resolveConfig({}, manifest);
4486
+ const resolved = resolveConfig({}, manifest);
4488
4487
  let files;
4489
4488
  if (opts.files) {
4490
4489
  files = await glob([opts.files], { nodir: true, ignore: ["**/*.min.css"] });
4491
4490
  } else {
4492
- const relStyles = await resolveActiveStyles(manifestDir, manifest.styles);
4491
+ const relStyles = await resolveActiveStyles(manifestDir, resolved.styles);
4493
4492
  files = relStyles.map((rel) => resolve4(manifestDir, rel)).filter((f) => !f.endsWith(".min.css"));
4494
4493
  }
4495
4494
  if (files.length === 0) {
@@ -8033,7 +8032,7 @@ class PdfOutput {
8033
8032
  const rawPdf = pdfxMode ? path8.join(stage, "raw.pdf") : path8.resolve(pdfFile);
8034
8033
  await fsp2.mkdir(path8.dirname(path8.resolve(pdfFile)), { recursive: true });
8035
8034
  log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
8036
- const { buildNativePdf } = await import("./engine-qg5tdaqv.js");
8035
+ const { buildNativePdf } = await import("./engine-pta3yeyt.js");
8037
8036
  const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
8038
8037
  title: config.title,
8039
8038
  author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
@@ -427,7 +427,7 @@ function readDevToolsUrl(proc) {
427
427
  return new Promise((resolve, reject) => {
428
428
  let buf = "";
429
429
  const timer = setTimeout(() => reject(new Error(`Chromium did not report a DevTools URL:
430
- ${buf}`)), 20000);
430
+ ${buf}`)), 60000);
431
431
  proc.stderr.on("data", (d) => {
432
432
  buf += String(d);
433
433
  const m = /ws:\/\/[^\s]+/.exec(buf);
@@ -608,7 +608,7 @@ var preview_shell_default = "./preview-shell-gqnc5xxe.js";
608
608
  var CGATS21_CRPC1_default = "./CGATS21_CRPC1-g0e3k7kr.icc";
609
609
 
610
610
  // src/assets/engine/gutterpress-viewer.js
611
- var gutterpress_viewer_default = "./gutterpress-viewer-mfeccbys.js";
611
+ var gutterpress_viewer_default = "./gutterpress-viewer-k0xrt5hw.js";
612
612
 
613
613
  // src/assets/engine/gutterpress-agent.js
614
614
  var gutterpress_agent_default = "./gutterpress-agent-cazqstr1.js";
package/dist/index.js CHANGED
@@ -113,15 +113,15 @@ import {
113
113
  syncProject,
114
114
  testRemoteAccess,
115
115
  validateProjectPlugins
116
- } from "./index-wdkvhdzj.js";
116
+ } from "./index-g0vvds4s.js";
117
117
  import {
118
118
  BUILD_DIAGNOSTIC_CODES
119
- } from "./index-my3v298z.js";
119
+ } from "./index-cm4dywtk.js";
120
120
  import {
121
121
  BuildError,
122
122
  DEFAULT_PRINT_OPTS,
123
123
  readyProbeExpr
124
- } from "./index-wbm6p5j3.js";
124
+ } from "./index-p4yq14qw.js";
125
125
  import {
126
126
  AUTO_SNAPSHOT_MESSAGE,
127
127
  HISTORY_PAGE_LIMIT,
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  MANIFEST_FILENAMES,
3
3
  runLint
4
- } from "./cli-qx6mak9k.js";
4
+ } from "./cli-avsnd8r3.js";
5
5
  import {
6
6
  log
7
- } from "./cli-qbasg0r3.js";
7
+ } from "./cli-2y07zn1g.js";
8
8
  import {
9
9
  UsageError,
10
10
  rejectExtraPositionals,
11
11
  rejectUnknownFlags
12
- } from "./cli-yezsxehb.js";
13
- import"./cli-c2yvktan.js";
12
+ } from "./cli-00gqsfce.js";
13
+ import"./cli-7hay1r0h.js";
14
14
  import"./cli-c41yr7he.js";
15
15
  import {
16
16
  EXIT_CODES
@@ -5,16 +5,16 @@ import {
5
5
  TARGETS,
6
6
  TARGET_IDS,
7
7
  scaffoldProject
8
- } from "./cli-qx6mak9k.js";
8
+ } from "./cli-avsnd8r3.js";
9
9
  import {
10
10
  resolveGhostscript
11
- } from "./cli-qbasg0r3.js";
11
+ } from "./cli-2y07zn1g.js";
12
12
  import {
13
13
  UsageError,
14
14
  rejectExtraPositionals,
15
15
  rejectUnknownFlags
16
- } from "./cli-yezsxehb.js";
17
- import"./cli-c2yvktan.js";
16
+ } from "./cli-00gqsfce.js";
17
+ import"./cli-7hay1r0h.js";
18
18
  import {
19
19
  isToolAvailable
20
20
  } from "./cli-c41yr7he.js";
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  addNpmPlugin,
3
3
  parseNpmPluginSpec
4
- } from "./cli-qx6mak9k.js";
5
- import"./cli-qbasg0r3.js";
4
+ } from "./cli-avsnd8r3.js";
5
+ import"./cli-2y07zn1g.js";
6
6
  import {
7
7
  UsageError,
8
8
  rejectExtraPositionals,
9
9
  rejectUnknownFlags
10
- } from "./cli-yezsxehb.js";
11
- import"./cli-c2yvktan.js";
10
+ } from "./cli-00gqsfce.js";
11
+ import"./cli-7hay1r0h.js";
12
12
  import"./cli-c41yr7he.js";
13
13
  import {
14
14
  EXIT_CODES
@@ -2,16 +2,16 @@ import {
2
2
  executeValidation,
3
3
  publishTargetFor,
4
4
  reportMissingTools
5
- } from "./cli-qx6mak9k.js";
5
+ } from "./cli-avsnd8r3.js";
6
6
  import {
7
7
  log
8
- } from "./cli-qbasg0r3.js";
8
+ } from "./cli-2y07zn1g.js";
9
9
  import {
10
10
  UsageError,
11
11
  rejectExtraPositionals,
12
12
  rejectUnknownFlags
13
- } from "./cli-yezsxehb.js";
14
- import"./cli-c2yvktan.js";
13
+ } from "./cli-00gqsfce.js";
14
+ import"./cli-7hay1r0h.js";
15
15
  import"./cli-c41yr7he.js";
16
16
  import {
17
17
  EXIT_CODES
@@ -6,10 +6,10 @@ import {
6
6
  runBuild,
7
7
  splitOutPath,
8
8
  startPreviewServer
9
- } from "./cli-qx6mak9k.js";
9
+ } from "./cli-avsnd8r3.js";
10
10
  import {
11
11
  log
12
- } from "./cli-qbasg0r3.js";
12
+ } from "./cli-2y07zn1g.js";
13
13
  import {
14
14
  UsageError,
15
15
  parseEngine,
@@ -18,8 +18,8 @@ import {
18
18
  rejectExtraPositionals,
19
19
  rejectUnknownFlags,
20
20
  resolvePort
21
- } from "./cli-yezsxehb.js";
22
- import"./cli-c2yvktan.js";
21
+ } from "./cli-00gqsfce.js";
22
+ import"./cli-7hay1r0h.js";
23
23
  import"./cli-c41yr7he.js";
24
24
  import {
25
25
  BuildError
@@ -7,17 +7,17 @@ import {
7
7
  publishCredentialKey,
8
8
  publishProviderFor,
9
9
  runPublish
10
- } from "./cli-qx6mak9k.js";
10
+ } from "./cli-avsnd8r3.js";
11
11
  import {
12
12
  FileTokenStore,
13
13
  log
14
- } from "./cli-qbasg0r3.js";
14
+ } from "./cli-2y07zn1g.js";
15
15
  import {
16
16
  UsageError,
17
17
  rejectExtraPositionals,
18
18
  rejectUnknownFlags
19
- } from "./cli-yezsxehb.js";
20
- import"./cli-c2yvktan.js";
19
+ } from "./cli-00gqsfce.js";
20
+ import"./cli-7hay1r0h.js";
21
21
  import"./cli-c41yr7he.js";
22
22
  import {
23
23
  EXIT_CODES
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  executeAndReport
3
- } from "./cli-qx6mak9k.js";
3
+ } from "./cli-avsnd8r3.js";
4
4
  import {
5
5
  log
6
- } from "./cli-qbasg0r3.js";
6
+ } from "./cli-2y07zn1g.js";
7
7
  import {
8
8
  UsageError,
9
9
  rejectExtraPositionals,
10
10
  rejectUnknownFlags
11
- } from "./cli-yezsxehb.js";
12
- import"./cli-c2yvktan.js";
11
+ } from "./cli-00gqsfce.js";
12
+ import"./cli-7hay1r0h.js";
13
13
  import"./cli-c41yr7he.js";
14
14
  import {
15
15
  EXIT_CODES
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gutterpress",
3
- "version": "0.10.3",
3
+ "version": "0.10.4-beta.1",
4
4
  "description": "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
5
5
  "author": "itlackey",
6
6
  "license": "MPL-2.0",