gutterpress 0.11.23-alpha.7 → 0.11.23-beta.2

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 (69) hide show
  1. package/README.md +3 -1
  2. package/dist/{README-syg2hn83.md → README-8rct3axy.md} +2 -2
  3. package/dist/api/index.d.ts +3 -3
  4. package/dist/api/index.js +8 -6
  5. package/dist/{build-w572wq10.js → build-3e18wnqj.js} +9 -8
  6. package/dist/{cli-mmgtqnmr.js → cli-0ep11b0q.js} +1 -1
  7. package/dist/cli-65gy8ask.js +82 -0
  8. package/dist/{cli-6pv84kf3.js → cli-88arpdke.js} +6 -84
  9. package/dist/{cli-eatdqx3z.js → cli-9n9kg58f.js} +1 -1
  10. package/dist/{cli-58fsk6d7.js → cli-pd2cje5b.js} +187 -44
  11. package/dist/{cli-3cvq3n1c.js → cli-pnrararp.js} +189 -85
  12. package/dist/{cli-wyg7qstd.js → cli-tgnyvra3.js} +15 -5
  13. package/dist/{cli-31anr0r9.js → cli-v0evdpdf.js} +68 -28
  14. package/dist/{cli-5ba6bm6z.js → cli-x7gcdg6w.js} +1 -1
  15. package/dist/cli.js +12 -12
  16. package/dist/{doctor-2f3zqmza.js → doctor-2f4s9dyn.js} +3 -3
  17. package/dist/engine/compiler/postprocess.d.ts +3 -0
  18. package/dist/engine/shared/page-vars.d.ts +32 -0
  19. package/dist/engine/shared/pdf-inspect.d.ts +33 -0
  20. package/dist/{engine-4rabsgwq.js → engine-c4pxz79g.js} +2 -1
  21. package/dist/{engine-wm4fggac.js → engine-cs5g2ez0.js} +3 -3
  22. package/dist/{ext-0cgky8n3.js → ext-70gv86v5.js} +9 -8
  23. package/dist/{extension-restore-vghc58vx.js → extension-restore-chj5nx3t.js} +3 -3
  24. package/dist/{extension-restore-e7je32pr.js → extension-restore-pd87p8r2.js} +5 -4
  25. package/dist/{gutterpress-agent-d29ry3ak.js → gutterpress-agent-wyryqehx.js} +13 -4
  26. package/dist/{gutterpress-viewer-mafsby5k.js → gutterpress-viewer-ywkf49q5.js} +90 -166
  27. package/dist/{index-nfysshcc.js → index-0k43evt0.js} +309 -155
  28. package/dist/{index-wm4x7xbf.js → index-2t1gdma7.js} +178 -35
  29. package/dist/{index-cw03e9p4.js → index-7j3hkwya.js} +68 -28
  30. package/dist/{index-fp7xwvpr.js → index-80vg3ed6.js} +15 -5
  31. package/dist/{index-2vxzxyyj.js → index-swfdgn2n.js} +10 -10
  32. package/dist/index-tayzfr9c.js +99 -0
  33. package/dist/{index-hphcn7th.js → index-ytjkvwy5.js} +5 -85
  34. package/dist/index.d.ts +2 -0
  35. package/dist/index.js +234 -7
  36. package/dist/lib/book-css.d.ts +56 -0
  37. package/dist/lib/markdown/assemble.d.ts +58 -0
  38. package/dist/lib/markdown/gutterpress-css.d.ts +1 -1
  39. package/dist/lib/publish/google-drive.d.ts +12 -4
  40. package/dist/lib/publish/manifest-publish.d.ts +6 -0
  41. package/dist/lib/publish/providers/gdrive-folder.d.ts +30 -0
  42. package/dist/lib/publish/run-publish.d.ts +6 -1
  43. package/dist/lib/publish/types.d.ts +52 -5
  44. package/dist/lib/remote-auth/converge-merge.d.ts +3 -3
  45. package/dist/lib/remote-auth/sync-messages.d.ts +2 -2
  46. package/dist/lib/root-tokens.d.ts +76 -0
  47. package/dist/lib/source-provider.d.ts +27 -0
  48. package/dist/lib/version-changes.d.ts +26 -16
  49. package/dist/{manifest-79zsgkpn.yaml → manifest-0vwaskj2.yaml} +1 -1
  50. package/dist/{manifest-2kc56wvw.yaml → manifest-aya31jwt.yaml} +1 -1
  51. package/dist/{manifest-41ddzm13.yaml → manifest-mffah3hr.yaml} +1 -1
  52. package/dist/{manifest-sqzm4681.yaml → manifest-wbcv8cbp.yaml} +2 -2
  53. package/dist/{manifest.schema-93sd7zje.json → manifest.schema-0jgj0jt1.json} +1 -1
  54. package/dist/{new-88rkrv71.js → new-d61n5cn0.js} +9 -8
  55. package/dist/{page-rules-ytj9p04v.css → page-rules-vnja6grt.css} +2 -2
  56. package/dist/{plugins-3aj0wc5h.js → plugins-0hhw6s17.js} +1 -1
  57. package/dist/{plugins-sprxsz5d.js → plugins-e0n46s6m.js} +3 -3
  58. package/dist/{preflight-11dg1qkk.js → preflight-fjayhjr5.js} +9 -8
  59. package/dist/{preview-nftp782j.js → preview-h815jrfb.js} +9 -8
  60. package/dist/{publish-6tgxfck9.js → publish-ft39zgma.js} +25 -9
  61. package/dist/render.js +77 -26
  62. package/dist/schema/manifest.types.d.ts +2 -1
  63. package/dist/{source-provider-n7vehh6t.js → source-provider-j1w7byeq.js} +5 -1
  64. package/dist/{source-provider-tgzet3j5.js → source-provider-tjaf303m.js} +5 -1
  65. package/dist/test-helpers/vocabulary.d.ts +12 -0
  66. package/dist/{tokens-n82t4k9h.css → tokens-a7grv940.css} +4 -5
  67. package/dist/{validate-pktqrye5.js → validate-b201dbrb.js} +9 -8
  68. package/package.json +1 -1
  69. package/dist/index-46ycxe6r.js +0 -18
@@ -372,6 +372,40 @@ class LocalFolderSourceProvider {
372
372
  return Promise.reject(new Error(NO_VERSION_HISTORY));
373
373
  }
374
374
  }
375
+ var lastHistoryWalk = null;
376
+ async function startHistoryWalk(dir, cache, heads) {
377
+ const shallow = await gitFs.promises.readFile(path2.join(gitDirFor(dir), "shallow"), "utf8").catch(() => "");
378
+ const tips = await Promise.all(heads.map((oid) => git.readCommit({ fs: gitFs, dir, cache, oid })));
379
+ tips.sort((a, b) => a.commit.committer.timestamp - b.commit.committer.timestamp);
380
+ return {
381
+ tips,
382
+ queued: new Set(heads),
383
+ shallow: new Set(shallow.split(`
384
+ `)),
385
+ readAhead: new Map
386
+ };
387
+ }
388
+ async function nextInHistory(dir, walk, cache, needed) {
389
+ const commit = walk.tips.pop();
390
+ if (!commit || walk.shallow.has(commit.oid))
391
+ return commit;
392
+ for (const oid of commit.commit.parent) {
393
+ if (walk.queued.has(oid))
394
+ continue;
395
+ const oneLine = walk.tips.length === 0 && commit.commit.parent.length === 1;
396
+ if (needed > 1 && oneLine && !walk.readAhead.has(oid)) {
397
+ for (const c of await git.log({ fs: gitFs, dir, cache, ref: oid, depth: needed })) {
398
+ if (!walk.queued.has(c.oid))
399
+ walk.readAhead.set(c.oid, c);
400
+ }
401
+ }
402
+ walk.queued.add(oid);
403
+ walk.tips.push(walk.readAhead.get(oid) ?? await git.readCommit({ fs: gitFs, dir, cache, oid }));
404
+ walk.readAhead.delete(oid);
405
+ }
406
+ walk.tips.sort((a, b) => a.commit.committer.timestamp - b.commit.committer.timestamp);
407
+ return commit;
408
+ }
375
409
 
376
410
  class LocalGitSourceProvider {
377
411
  source;
@@ -409,40 +443,46 @@ class LocalGitSourceProvider {
409
443
  const dir = this.dir;
410
444
  const limit = Math.min(500, Math.max(1, options.limit ?? HISTORY_PAGE_LIMIT));
411
445
  const before = options.before;
412
- let commits;
446
+ const cache = {};
413
447
  try {
414
- commits = await git.log({
415
- fs: gitFs,
416
- dir,
417
- cache: {},
418
- depth: limit + 2,
419
- ...before ? { ref: before } : {}
420
- });
448
+ const head = await git.resolveRef({ fs: gitFs, dir, ref: "HEAD" });
449
+ let walk;
450
+ const saved = lastHistoryWalk;
451
+ if (before && saved?.dir === dir && saved.head === head && saved.last === before) {
452
+ walk = saved.walk;
453
+ lastHistoryWalk = null;
454
+ } else {
455
+ walk = await startHistoryWalk(dir, cache, [head]);
456
+ if (before) {
457
+ let c;
458
+ do {
459
+ c = await nextInHistory(dir, walk, cache, limit);
460
+ } while (c && c.oid !== before);
461
+ if (!c)
462
+ return { entries: [], hasMore: false };
463
+ }
464
+ }
465
+ const entries = [];
466
+ while (entries.length < limit) {
467
+ const c = await nextInHistory(dir, walk, cache, limit - entries.length);
468
+ if (!c)
469
+ break;
470
+ entries.push({
471
+ id: c.oid,
472
+ message: c.commit.message.trim(),
473
+ timestamp: c.commit.author.timestamp * 1000,
474
+ author: c.commit.author.name
475
+ });
476
+ }
477
+ const hasMore = walk.tips.length > 0;
478
+ lastHistoryWalk = hasMore ? { dir, head, last: entries.at(-1).id, walk } : null;
479
+ return { entries, hasMore };
421
480
  } catch (e) {
422
481
  if (before && e?.code === "NotFoundError") {
423
482
  return { entries: [], hasMore: false };
424
483
  }
425
484
  throw e;
426
485
  }
427
- const seen = new Set;
428
- let filtered = commits.filter((c) => {
429
- if (c.oid === before || seen.has(c.oid))
430
- return false;
431
- seen.add(c.oid);
432
- return true;
433
- });
434
- const hasMore = filtered.length > limit;
435
- if (hasMore)
436
- filtered = filtered.slice(0, limit);
437
- return {
438
- entries: filtered.map((c) => ({
439
- id: c.oid,
440
- message: c.commit.message.trim(),
441
- timestamp: c.commit.author.timestamp * 1000,
442
- author: c.commit.author.name
443
- })),
444
- hasMore
445
- };
446
486
  }
447
487
  restore(options) {
448
488
  return withRepoLock(this.dir, () => this.restoreUnlocked(options));
@@ -742,4 +782,4 @@ async function switchBranch(options) {
742
782
  });
743
783
  }
744
784
 
745
- export { gitScopeFor, HISTORY_PAGE_LIMIT, NO_VERSION_HISTORY, withRepoLock, whenGitIdle, __repoLockQueueSizeForTests, resolveGitAuthor, listWorkdirChanges, stageChanges, hasPendingChanges, hasUncommittedChanges, snapshotWorkingTreeUnlocked, isNoChangesError, countUnversionedChanges, providerFor, gitDirFor, snapshotStagingMarkerPath, RESTORE_BACKUP_MESSAGE, AUTO_SNAPSHOT_MESSAGE, restoreVersionWithBackup, SWITCH_BRANCH_SNAPSHOT_MESSAGE, readRevisionRefs, isContained, listRevisions, revisionNameFrom, assertFreeRevisionName, createRevision, switchBranch };
785
+ export { gitScopeFor, HISTORY_PAGE_LIMIT, NO_VERSION_HISTORY, withRepoLock, whenGitIdle, __repoLockQueueSizeForTests, resolveGitAuthor, listWorkdirChanges, stageChanges, hasPendingChanges, hasUncommittedChanges, startHistoryWalk, nextInHistory, snapshotWorkingTreeUnlocked, isNoChangesError, countUnversionedChanges, providerFor, gitDirFor, snapshotStagingMarkerPath, RESTORE_BACKUP_MESSAGE, AUTO_SNAPSHOT_MESSAGE, restoreVersionWithBackup, SWITCH_BRANCH_SNAPSHOT_MESSAGE, readRevisionRefs, isContained, listRevisions, revisionNameFrom, assertFreeRevisionName, createRevision, switchBranch };
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "gutterpress",
4
- version: "0.11.23-alpha.7",
4
+ version: "0.11.23-beta.2",
5
5
  description: "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
6
6
  author: "itlackey",
7
7
  license: "MPL-2.0",
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-5ba6bm6z.js";
11
+ } from "./cli-x7gcdg6w.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-88rkrv71.js").then((m) => m.default),
24
- preview: () => import("./preview-nftp782j.js").then((m) => m.default),
25
- build: () => import("./build-w572wq10.js").then((m) => m.default),
26
- publish: () => import("./publish-6tgxfck9.js").then((m) => m.default),
27
- validate: () => import("./validate-pktqrye5.js").then((m) => m.default),
28
- preflight: () => import("./preflight-11dg1qkk.js").then((m) => m.default),
29
- doctor: () => import("./doctor-2f3zqmza.js").then((m) => m.default),
30
- ext: () => import("./ext-0cgky8n3.js").then((m) => m.default)
23
+ new: () => import("./new-d61n5cn0.js").then((m) => m.default),
24
+ preview: () => import("./preview-h815jrfb.js").then((m) => m.default),
25
+ build: () => import("./build-3e18wnqj.js").then((m) => m.default),
26
+ publish: () => import("./publish-ft39zgma.js").then((m) => m.default),
27
+ validate: () => import("./validate-b201dbrb.js").then((m) => m.default),
28
+ preflight: () => import("./preflight-fjayhjr5.js").then((m) => m.default),
29
+ doctor: () => import("./doctor-2f4s9dyn.js").then((m) => m.default),
30
+ ext: () => import("./ext-70gv86v5.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-88rkrv71.js");
55
+ const { newArgs } = await import("./new-d61n5cn0.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-11dg1qkk.js");
67
+ const { preflightArgs } = await import("./preflight-fjayhjr5.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-0cgky8n3.js");
87
+ const { EXT_SUBCOMMANDS, extAddArgs, extRemoveArgs, extEnableArgs, extDisableArgs } = await import("./ext-70gv86v5.js");
88
88
  if (!EXT_SUBCOMMANDS.includes(subcommand)) {
89
89
  throw new UsageError(`gutterpress ext: unknown command "${subcommand}"`);
90
90
  }
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  getSystemDiagnostics
3
- } from "./cli-mmgtqnmr.js";
3
+ } from "./cli-0ep11b0q.js";
4
4
  import"./cli-5crpmz42.js";
5
5
  import"./cli-asap4t1z.js";
6
6
  import {
7
7
  log
8
- } from "./cli-eatdqx3z.js";
8
+ } from "./cli-9n9kg58f.js";
9
9
  import {
10
10
  UsageError,
11
11
  rejectExtraPositionals,
12
12
  rejectUnknownFlags
13
13
  } from "./cli-d8xjns66.js";
14
- import"./cli-5ba6bm6z.js";
14
+ import"./cli-x7gcdg6w.js";
15
15
  import"./cli-46ycxe6r.js";
16
16
  import"./cli-37x76zdn.js";
17
17
 
@@ -27,5 +27,8 @@ export interface PostprocessResult {
27
27
  bleed: number[];
28
28
  trim: number[];
29
29
  };
30
+ /** The scale Chromium printed at, read before anything here draws:
31
+ * `printScale` in shared/pdf-inspect.ts (1 = not shrunk). */
32
+ scale: number | null;
30
33
  }
31
34
  export declare function postprocess(input: Uint8Array, opts: PostprocessOptions): Promise<PostprocessResult>;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The page's own numbers, published as custom properties so a stylesheet reads
3
+ * them instead of keeping a copy that stops following Book setup:
4
+ *
5
+ * --gp-page-width --gp-page-height --gp-page-bleed --gp-page-safe
6
+ * --gp-page-gutter --gp-page-art-safe --gp-page-margin-top
7
+ * --gp-page-margin-bottom --gp-page-margin-inside --gp-page-margin-outside
8
+ *
9
+ * Every value is in `pt` with the unit, so `calc()` takes it directly, and every
10
+ * name is always there: a value the book does not define is `0pt`.
11
+ *
12
+ * Where each comes from:
13
+ * - size and margins: the `@page` reader (`resolvePage`) over the stylesheet
14
+ * the engine reads. The assembly writes the manifest's size, and its margins
15
+ * when it sets any, as plain `@page` rules after every sheet (see
16
+ * lib/markdown/assemble.ts), so the reader returns the manifest's when it
17
+ * decided and the look's or the 1in default when it did not. The recto is
18
+ * read (`:right`, page 1 and every odd page): `inside` is its left, the
19
+ * binding, and `outside` its right.
20
+ * - bleed, safe, gutter, art-safe: the manifest's `page`, through the book's
21
+ * `<meta name="gp-print-area">` (shared/print-area.ts).
22
+ *
23
+ * The size and margins are also published per named page, on the selectors that
24
+ * assign it (the way `--gp-content-h` is); the book-wide ones are on `:root`.
25
+ *
26
+ * Pure: the compiler publishes this CSS for the PDF and the viewer for the
27
+ * preview (viewer/fragment.ts), from the same model and print area.
28
+ */
29
+ import { type GcpmModel } from "./gcpm-extract.ts";
30
+ import { type PrintArea } from "./print-area.ts";
31
+ /** The `gp-page-vars` rules for one book; `area` is `null` when it carries no print area. */
32
+ export declare function pageGeometryVarsCss(model: GcpmModel, area: PrintArea | null): string;
@@ -1,3 +1,16 @@
1
+ /**
2
+ * Read-side PDF utilities (pdf-lib, pure JS).
3
+ *
4
+ * Three jobs:
5
+ * 1. Verification: page count, page boxes, embedded fonts — the evidence the
6
+ * tests assert on.
7
+ * 2. Tier 3 measurement channel (§8): harvest Chromium's own link annotations
8
+ * and document outline to learn "which page is element X on", with no text
9
+ * heuristics.
10
+ * 3. The print scale: whether Chromium's shrink-to-fit scaled the page area
11
+ * ({@link printScale}).
12
+ */
13
+ import { PDFDocument } from "pdf-lib";
1
14
  export interface PageBoxes {
2
15
  media: number[];
3
16
  crop?: number[];
@@ -18,3 +31,23 @@ export interface PdfFacts {
18
31
  }>;
19
32
  }
20
33
  export declare function inspectPdf(bytes: Uint8Array): Promise<PdfFacts>;
34
+ /**
35
+ * The scale Chromium printed the page area at: 1 when it laid the document
36
+ * out at the page content box's own width, below 1 when print shrink-to-fit
37
+ * scaled the whole document down because something reached past that box
38
+ * (ENGINE.md §9). `null` when no page shows the transform — a reader that
39
+ * cannot find it makes no claim. Pass Chromium's own print, before anything
40
+ * redraws its pages.
41
+ *
42
+ * Read off the content streams rather than predicted from element widths.
43
+ * Each page draws its page box (background, margin boxes) under an unscaled
44
+ * `3.125 0 0 3.125 0 0 cm` — CSS px to 300-per-inch device units — then clips
45
+ * to the page area, its largest clip, and draws the page area's content
46
+ * under `s 0 0 s x y cm`, where x is the clip's own left edge and s is 3.125
47
+ * times the shrink. An element with a CSS transform or its own clip draws
48
+ * under other matrices, so one page can read wrong; Chromium applies one
49
+ * factor to the whole document, so the first reading three pages agree on
50
+ * (or the most common, in a shorter document) is the answer. The prologue
51
+ * fixes the device resolution: the scale is s × prologue × 96/72.
52
+ */
53
+ export declare function printScale(doc: PDFDocument): number | null;
@@ -1,8 +1,9 @@
1
1
  import {
2
2
  build
3
- } from "./cli-58fsk6d7.js";
3
+ } from "./cli-pd2cje5b.js";
4
4
  import"./cli-eyyggect.js";
5
5
  import"./cli-asap4t1z.js";
6
+ import"./cli-65gy8ask.js";
6
7
  import {
7
8
  BuildError
8
9
  } from "./cli-46ycxe6r.js";
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  build
3
- } from "./index-wm4x7xbf.js";
4
- import"./index-2vxzxyyj.js";
3
+ } from "./index-2t1gdma7.js";
4
+ import"./index-swfdgn2n.js";
5
5
  import {
6
6
  BuildError
7
- } from "./index-46ycxe6r.js";
7
+ } from "./index-tayzfr9c.js";
8
8
  import"./index-bt0qws5c.js";
9
9
  import"./index-37x76zdn.js";
10
10
 
@@ -2,14 +2,14 @@ import {
2
2
  importExtensionFromFile,
3
3
  importExtensionFromUrl,
4
4
  searchNpmExtensions
5
- } from "./cli-3cvq3n1c.js";
6
- import"./cli-mmgtqnmr.js";
5
+ } from "./cli-pnrararp.js";
6
+ import"./cli-0ep11b0q.js";
7
7
  import"./cli-ht1bcqdd.js";
8
- import"./cli-58fsk6d7.js";
8
+ import"./cli-pd2cje5b.js";
9
9
  import"./cli-5crpmz42.js";
10
10
  import"./cli-eyyggect.js";
11
11
  import"./cli-asap4t1z.js";
12
- import"./cli-31anr0r9.js";
12
+ import"./cli-v0evdpdf.js";
13
13
  import"./cli-v5mp7a6q.js";
14
14
  import {
15
15
  addExtension,
@@ -18,12 +18,12 @@ import {
18
18
  removeExtension,
19
19
  setExtensionEnabled,
20
20
  updateExtensions
21
- } from "./cli-6pv84kf3.js";
21
+ } from "./cli-88arpdke.js";
22
22
  import {
23
23
  isPathSpecifier,
24
24
  parseExtensionSpecifier
25
- } from "./cli-wyg7qstd.js";
26
- import"./cli-eatdqx3z.js";
25
+ } from "./cli-tgnyvra3.js";
26
+ import"./cli-9n9kg58f.js";
27
27
  import {
28
28
  UsageError,
29
29
  exitForUsage,
@@ -31,7 +31,8 @@ import {
31
31
  rejectUnknownFlags,
32
32
  resolveProjectDir
33
33
  } from "./cli-d8xjns66.js";
34
- import"./cli-5ba6bm6z.js";
34
+ import"./cli-x7gcdg6w.js";
35
+ import"./cli-65gy8ask.js";
35
36
  import {
36
37
  EXIT_CODES
37
38
  } from "./cli-46ycxe6r.js";
@@ -3,9 +3,9 @@ import {
3
3
  restoreForCommand,
4
4
  restoreOfflineMessage,
5
5
  restorePinnedExtensions
6
- } from "./index-hphcn7th.js";
7
- import"./index-fp7xwvpr.js";
8
- import"./index-46ycxe6r.js";
6
+ } from "./index-ytjkvwy5.js";
7
+ import"./index-80vg3ed6.js";
8
+ import"./index-tayzfr9c.js";
9
9
  import"./index-5x42amh8.js";
10
10
  import"./index-37x76zdn.js";
11
11
  export {
@@ -3,11 +3,12 @@ import {
3
3
  restoreForCommand,
4
4
  restoreOfflineMessage,
5
5
  restorePinnedExtensions
6
- } from "./cli-6pv84kf3.js";
7
- import"./cli-wyg7qstd.js";
8
- import"./cli-eatdqx3z.js";
6
+ } from "./cli-88arpdke.js";
7
+ import"./cli-tgnyvra3.js";
8
+ import"./cli-9n9kg58f.js";
9
9
  import"./cli-d8xjns66.js";
10
- import"./cli-5ba6bm6z.js";
10
+ import"./cli-x7gcdg6w.js";
11
+ import"./cli-65gy8ask.js";
11
12
  import"./cli-46ycxe6r.js";
12
13
  import"./cli-y28j019d.js";
13
14
  import"./cli-37x76zdn.js";
@@ -59,6 +59,7 @@
59
59
  });
60
60
 
61
61
  // src/engine/shared/synthesis.ts
62
+ var RECTO_VERSO_VALUES = /^(right|recto|left|verso)$/;
62
63
  var WHICH_VALUES = new Set(["first", "start", "last", "first-except"]);
63
64
  var LEADER_RE = /\uE000([^\uE001]*)\uE001/;
64
65
  function leaderFillCount(gapPx, gluePx) {
@@ -422,7 +423,8 @@
422
423
  return out;
423
424
  }
424
425
  function forcedBreakSites(decls) {
425
- const out = [];
426
+ const found = [];
427
+ const seen = new Set;
426
428
  for (const d of decls) {
427
429
  let els = [];
428
430
  try {
@@ -430,10 +432,17 @@
430
432
  } catch {
431
433
  continue;
432
434
  }
433
- for (const el of els)
434
- out.push({ id: ensureAnchor(el), prop: d.prop, value: d.value, selector: d.selector });
435
+ for (const el of els) {
436
+ const id = ensureAnchor(el);
437
+ const value = getComputedStyle(el).breakBefore;
438
+ if (seen.has(el) || !RECTO_VERSO_VALUES.test(value))
439
+ continue;
440
+ seen.add(el);
441
+ found.push({ el, id, prop: d.prop, value, selector: d.selector });
442
+ }
435
443
  }
436
- return out;
444
+ found.sort((a, b) => a.el.compareDocumentPosition(b.el) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1);
445
+ return found.map(({ el: _el, ...site }) => site);
437
446
  }
438
447
  function counterResetSites(resets) {
439
448
  const out = [];