gutterpress 0.11.23-beta.1 → 0.11.23-beta.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 (65) hide show
  1. package/README.md +13 -3
  2. package/dist/api/index.d.ts +5 -5
  3. package/dist/api/index.js +19 -7
  4. package/dist/{build-dg8a566j.js → build-fq3mexhy.js} +9 -9
  5. package/dist/checks/asset/approved-fonts.d.ts +8 -0
  6. package/dist/checks/asset/extensions.d.ts +1 -1
  7. package/dist/checks/asset/index.d.ts +1 -0
  8. package/dist/{cli-e31jshz6.js → cli-5zbdb6mt.js} +296 -65
  9. package/dist/{cli-ttj95aex.js → cli-7mt0dftw.js} +47 -18
  10. package/dist/{cli-989eg8jz.js → cli-ah93yyzb.js} +163 -55
  11. package/dist/{cli-31anr0r9.js → cli-eymdsefg.js} +69 -29
  12. package/dist/{cli-1fy1pm9d.js → cli-fh685nqs.js} +1 -1
  13. package/dist/{cli-k087gj0p.js → cli-fsjre61x.js} +123 -12
  14. package/dist/{cli-s1zt779w.js → cli-q7t04gjt.js} +1 -1
  15. package/dist/{cli-vhav8g82.js → cli-rybz2dfs.js} +1 -1
  16. package/dist/cli.js +12 -12
  17. package/dist/{doctor-g4a42tcz.js → doctor-tg9ht1n3.js} +3 -3
  18. package/dist/engine/compiler/postprocess.d.ts +3 -0
  19. package/dist/engine/shared/pdf-inspect.d.ts +33 -0
  20. package/dist/{engine-jvkcahr1.js → engine-17v87vq5.js} +1 -1
  21. package/dist/{engine-wgkaqjsc.js → engine-y9fnarfa.js} +2 -2
  22. package/dist/{ext-w9d5ftcg.js → ext-esz03jz4.js} +27 -10
  23. package/dist/{extension-restore-5x4mj79d.js → extension-restore-91gy1e28.js} +3 -3
  24. package/dist/{extension-restore-as0g38p1.js → extension-restore-q70wqah5.js} +5 -5
  25. package/dist/{gutterpress-agent-d29ry3ak.js → gutterpress-agent-wyryqehx.js} +13 -4
  26. package/dist/{gutterpress-viewer-ze691rrd.js → gutterpress-viewer-ywkf49q5.js} +38 -153
  27. package/dist/{index-a4j3xcfp.js → index-67g8f7r4.js} +47 -18
  28. package/dist/{index-798jt0qc.js → index-d9w3r89w.js} +3 -3
  29. package/dist/{index-rj5vrhz6.js → index-fntpr44x.js} +321 -66
  30. package/dist/{index-5x42amh8.js → index-g3te5ey1.js} +2 -1
  31. package/dist/{index-cw03e9p4.js → index-kw4tbthz.js} +69 -29
  32. package/dist/{index-fk2kpf2t.js → index-santcs4q.js} +121 -10
  33. package/dist/{index-c6y0p7jy.js → index-z6vzj3s5.js} +243 -73
  34. package/dist/index.js +35 -8
  35. package/dist/lib/check-options.d.ts +70 -0
  36. package/dist/lib/extension-manager.d.ts +16 -1
  37. package/dist/lib/extension-scaffold.d.ts +15 -2
  38. package/dist/lib/extension-specifier.d.ts +8 -1
  39. package/dist/lib/manifest-config.d.ts +3 -1
  40. package/dist/lib/manifest-old-spellings.d.ts +32 -9
  41. package/dist/lib/markdown/gutterpress-css.d.ts +1 -1
  42. package/dist/lib/markdown/math.d.ts +1 -1
  43. package/dist/lib/markdown/typography.d.ts +1 -0
  44. package/dist/lib/page-size.d.ts +12 -4
  45. package/dist/lib/plugin-vendor.d.ts +6 -0
  46. package/dist/lib/presets.d.ts +2 -2
  47. package/dist/lib/root-tokens.d.ts +2 -1
  48. package/dist/lib/source-provider.d.ts +27 -0
  49. package/dist/lib/style-resolver.d.ts +2 -1
  50. package/dist/lib/version-changes.d.ts +22 -6
  51. package/dist/{manifest.schema-0jgj0jt1.json → manifest.schema-5cm13vr3.json} +215 -5
  52. package/dist/{new-jtk028rf.js → new-rmfyb7va.js} +22 -15
  53. package/dist/{plugins-bcbe7xs8.js → plugins-gs21xz5s.js} +2 -2
  54. package/dist/{plugins-zsm6wv79.js → plugins-tqv1s16f.js} +4 -4
  55. package/dist/{preflight-cs6mj1d6.js → preflight-bjyeeq0d.js} +9 -9
  56. package/dist/{preview-d1j1g4qf.js → preview-ke03fk5d.js} +9 -9
  57. package/dist/{publish-7yw4jyrt.js → publish-wpnz0qng.js} +9 -9
  58. package/dist/render.js +55 -13
  59. package/dist/schema/manifest.types.d.ts +45 -7
  60. package/dist/{source-provider-n7vehh6t.js → source-provider-3g3yrn1f.js} +6 -2
  61. package/dist/{source-provider-tgzet3j5.js → source-provider-azg9ywhb.js} +6 -2
  62. package/dist/test-helpers/vocabulary.d.ts +12 -0
  63. package/dist/{validate-rkcdnzhw.js → validate-zcwykb43.js} +9 -9
  64. package/package.json +1 -1
  65. /package/dist/{cli-y28j019d.js → cli-1dha1nxk.js} +0 -0
@@ -8,7 +8,7 @@ import {
8
8
  stampCreator,
9
9
  stripAnnotations,
10
10
  transparentPages
11
- } from "./cli-vhav8g82.js";
11
+ } from "./cli-rybz2dfs.js";
12
12
  import {
13
13
  blackTextToGray
14
14
  } from "./cli-ht1bcqdd.js";
@@ -17,7 +17,7 @@ import {
17
17
  MARGIN_BOX_IGNORED_PROPERTIES,
18
18
  getAssetPath,
19
19
  lastPageMode
20
- } from "./cli-k087gj0p.js";
20
+ } from "./cli-fsjre61x.js";
21
21
  import {
22
22
  countLinkAnnotations,
23
23
  getImageResolutions,
@@ -42,7 +42,7 @@ import {
42
42
  import {
43
43
  hasUncommittedChanges,
44
44
  listWorkdirChanges
45
- } from "./cli-31anr0r9.js";
45
+ } from "./cli-eymdsefg.js";
46
46
  import {
47
47
  detectProjectSource,
48
48
  repoSubPath
@@ -66,10 +66,11 @@ import {
66
66
  resolveConfigForTarget,
67
67
  resolveTargets,
68
68
  restoreForCommand,
69
+ setCheckOption,
69
70
  uniqueExtensionId,
70
71
  withFetchTimeout,
71
72
  writeManifestDoc
72
- } from "./cli-e31jshz6.js";
73
+ } from "./cli-5zbdb6mt.js";
73
74
  import {
74
75
  EXTENSION_MANIFEST_FILENAME,
75
76
  GUTTERPRESS_CSS,
@@ -90,7 +91,7 @@ import {
90
91
  readExtensionMeta,
91
92
  resolveDeclaredStyles,
92
93
  slugify
93
- } from "./cli-ttj95aex.js";
94
+ } from "./cli-7mt0dftw.js";
94
95
  import {
95
96
  PACKAGE_META,
96
97
  PACKAGE_VERSION,
@@ -100,7 +101,7 @@ import {
100
101
  log,
101
102
  setLogLevel,
102
103
  warn
103
- } from "./cli-1fy1pm9d.js";
104
+ } from "./cli-fh685nqs.js";
104
105
  import {
105
106
  DEBOUNCE,
106
107
  UsageError,
@@ -121,7 +122,7 @@ import {
121
122
  EXTENSIONS_DIR,
122
123
  resolveVendoredPluginInstallRoot,
123
124
  vendoredNpmPluginPackageDir
124
- } from "./cli-y28j019d.js";
125
+ } from "./cli-1dha1nxk.js";
125
126
  import {
126
127
  __require
127
128
  } from "./cli-37x76zdn.js";
@@ -1740,7 +1741,13 @@ import { existsSync as existsSync3 } from "node:fs";
1740
1741
  import { readdir } from "node:fs/promises";
1741
1742
  import path from "node:path";
1742
1743
  var STYLES_SUBDIR = "styles";
1743
- var DEFAULT_STYLESHEET = "styles/book.css";
1744
+ var FALLBACK_PRIORITY = [
1745
+ "styles/book.css",
1746
+ "css/print.css",
1747
+ "css/index.css",
1748
+ "css/style.css",
1749
+ "css/main.css"
1750
+ ];
1744
1751
  function relDisplay(projectDir, absPath) {
1745
1752
  return path.relative(projectDir, absPath).split(path.sep).join("/");
1746
1753
  }
@@ -1778,8 +1785,10 @@ async function resolveActiveStyles(projectDir, manifestStyles) {
1778
1785
  const manifest = configured.filter((s) => typeof s === "string" && s.trim().length > 0);
1779
1786
  if (manifest.length > 0)
1780
1787
  return manifest;
1781
- if (existsSync3(path.join(projectDir, DEFAULT_STYLESHEET)))
1782
- return [DEFAULT_STYLESHEET];
1788
+ for (const rel of FALLBACK_PRIORITY) {
1789
+ if (existsSync3(path.join(projectDir, rel)))
1790
+ return [rel];
1791
+ }
1783
1792
  const discovered = await discoverCssFiles(projectDir);
1784
1793
  if (discovered.length > 0) {
1785
1794
  const first = discovered.map((abs) => relDisplay(projectDir, abs)).sort((a, b) => a.localeCompare(b))[0];
@@ -3532,6 +3541,58 @@ var check30 = {
3532
3541
  };
3533
3542
  registerCheck(check30);
3534
3543
 
3544
+ // src/checks/asset/approved-fonts.ts
3545
+ var check31 = {
3546
+ id: "asset.font.approved-files",
3547
+ name: "Approved Font Files",
3548
+ description: "Checks font files against the approved file patterns",
3549
+ category: "asset",
3550
+ phase: "pre-build",
3551
+ async run(ctx) {
3552
+ const patterns = ctx.config.validate.assets.approvedFontFiles;
3553
+ if (!patterns || patterns.length === 0)
3554
+ return [];
3555
+ const { glob } = await import("glob");
3556
+ const dirs = ctx.assetDirs ?? [ctx.inputDir];
3557
+ const allFonts = [];
3558
+ for (const dir of dirs) {
3559
+ const matches = await glob(`**/*.{${FONT_EXTS2.join(",")}}`, {
3560
+ cwd: dir,
3561
+ absolute: true,
3562
+ ignore: [...ASSET_SCAN_IGNORE_GLOBS]
3563
+ });
3564
+ allFonts.push(...matches);
3565
+ }
3566
+ if (allFonts.length === 0)
3567
+ return [];
3568
+ const approvedFonts = new Set;
3569
+ for (const dir of dirs) {
3570
+ for (const pattern of patterns) {
3571
+ const matches = await glob(pattern, {
3572
+ cwd: dir,
3573
+ absolute: true,
3574
+ ignore: [...ASSET_SCAN_IGNORE_GLOBS]
3575
+ });
3576
+ for (const m of matches)
3577
+ approvedFonts.add(m);
3578
+ }
3579
+ }
3580
+ const results = [];
3581
+ for (const font of allFonts) {
3582
+ if (!approvedFonts.has(font)) {
3583
+ results.push({
3584
+ checkId: check31.id,
3585
+ severity: "warning",
3586
+ message: "Font file not in approved list",
3587
+ file: font
3588
+ });
3589
+ }
3590
+ }
3591
+ return results;
3592
+ }
3593
+ };
3594
+ registerCheck(check31);
3595
+
3535
3596
  // src/checks/asset/font-license.ts
3536
3597
  import { existsSync as existsSync5 } from "node:fs";
3537
3598
  import { resolve as resolve3 } from "node:path";
@@ -3545,7 +3606,7 @@ var LICENSE_NAMES = [
3545
3606
  "OFL-1.1.txt",
3546
3607
  "COPYING"
3547
3608
  ];
3548
- var check31 = {
3609
+ var check32 = {
3549
3610
  id: "asset.font.license",
3550
3611
  name: "Font License",
3551
3612
  description: "Checks for license files in font directories",
@@ -3570,7 +3631,7 @@ var check31 = {
3570
3631
  const hasLicense = LICENSE_NAMES.some((name) => existsSync5(resolve3(fontDir, name)));
3571
3632
  if (!hasLicense) {
3572
3633
  results.push({
3573
- checkId: check31.id,
3634
+ checkId: check32.id,
3574
3635
  severity: "warning",
3575
3636
  message: `No font license file found in directory`,
3576
3637
  file: fontDir
@@ -3580,10 +3641,10 @@ var check31 = {
3580
3641
  return results;
3581
3642
  }
3582
3643
  };
3583
- registerCheck(check31);
3644
+ registerCheck(check32);
3584
3645
 
3585
3646
  // src/checks/heuristic/text-density.ts
3586
- var check32 = {
3647
+ var check33 = {
3587
3648
  id: "heuristic.whitespace.text-density",
3588
3649
  name: "Text Density",
3589
3650
  description: "Checks characters-per-page ratio",
@@ -3612,7 +3673,7 @@ var check32 = {
3612
3673
  });
3613
3674
  if (lowPages.length > 0) {
3614
3675
  results.push({
3615
- checkId: check32.id,
3676
+ checkId: check33.id,
3616
3677
  severity: "info",
3617
3678
  message: `Low text density on pages: ${lowPages.join(", ")} (below ${range.min} chars)`,
3618
3679
  file: ctx.pdfPath
@@ -3620,7 +3681,7 @@ var check32 = {
3620
3681
  }
3621
3682
  if (highPages.length > 0) {
3622
3683
  results.push({
3623
- checkId: check32.id,
3684
+ checkId: check33.id,
3624
3685
  severity: "info",
3625
3686
  message: `High text density on pages: ${highPages.join(", ")} (above ${range.max} chars)`,
3626
3687
  file: ctx.pdfPath
@@ -3629,11 +3690,11 @@ var check32 = {
3629
3690
  return results;
3630
3691
  }
3631
3692
  };
3632
- registerCheck(check32);
3693
+ registerCheck(check33);
3633
3694
 
3634
3695
  // src/checks/heuristic/section-density.ts
3635
3696
  import { readFile as readFile15 } from "node:fs/promises";
3636
- var check33 = {
3697
+ var check34 = {
3637
3698
  id: "heuristic.chunking.section-density",
3638
3699
  name: "Section Density",
3639
3700
  description: "Checks heading/paragraph/callout density from source Markdown",
@@ -3659,7 +3720,7 @@ var check33 = {
3659
3720
  const line = lines[i];
3660
3721
  if (/^#{1,6}\s/.test(line)) {
3661
3722
  if (paragraphCount > maxParas) {
3662
- results.push(finding(check33.id, {
3723
+ results.push(finding(check34.id, {
3663
3724
  severity: "info",
3664
3725
  message: `Section has ${paragraphCount} paragraphs (max recommended: ${maxParas})`,
3665
3726
  file,
@@ -3679,7 +3740,7 @@ var check33 = {
3679
3740
  }
3680
3741
  }
3681
3742
  if (paragraphCount > maxParas) {
3682
- results.push(finding(check33.id, {
3743
+ results.push(finding(check34.id, {
3683
3744
  severity: "info",
3684
3745
  message: `Section has ${paragraphCount} paragraphs (max recommended: ${maxParas})`,
3685
3746
  file,
@@ -3687,7 +3748,7 @@ var check33 = {
3687
3748
  }));
3688
3749
  }
3689
3750
  } catch {
3690
- results.push(inspectionFailed(check33.id, `Could not read source file: ${file}`, {
3751
+ results.push(inspectionFailed(check34.id, `Could not read source file: ${file}`, {
3691
3752
  file
3692
3753
  }));
3693
3754
  }
@@ -3695,10 +3756,10 @@ var check33 = {
3695
3756
  return results;
3696
3757
  }
3697
3758
  };
3698
- registerCheck(check33);
3759
+ registerCheck(check34);
3699
3760
 
3700
3761
  // src/checks/heuristic/layer-count.ts
3701
- var check34 = {
3762
+ var check35 = {
3702
3763
  id: "heuristic.decoration.layer-count",
3703
3764
  name: "Layer Count",
3704
3765
  description: "Counts image objects per page",
@@ -3723,7 +3784,7 @@ var check34 = {
3723
3784
  heavyPages.sort((a, b) => a - b);
3724
3785
  return [
3725
3786
  {
3726
- checkId: check34.id,
3787
+ checkId: check35.id,
3727
3788
  severity: "info",
3728
3789
  message: `Pages with many image layers (>${maxLayers}): ${heavyPages.join(", ")}`,
3729
3790
  file: ctx.pdfPath
@@ -3733,10 +3794,10 @@ var check34 = {
3733
3794
  return [];
3734
3795
  }
3735
3796
  };
3736
- registerCheck(check34);
3797
+ registerCheck(check35);
3737
3798
 
3738
3799
  // src/checks/heuristic/placement-variance.ts
3739
- var check35 = {
3800
+ var check36 = {
3740
3801
  id: "heuristic.layout.placement-variance",
3741
3802
  name: "Placement Variance",
3742
3803
  description: "Analyzes text baseline coordinates for layout consistency",
@@ -3754,7 +3815,7 @@ var check35 = {
3754
3815
  const uniqueX = new Set(positions.map((p) => Math.round(p.x)));
3755
3816
  return [
3756
3817
  {
3757
- checkId: check35.id,
3818
+ checkId: check36.id,
3758
3819
  severity: "info",
3759
3820
  message: `Layout analysis: ${uniqueX.size} unique horizontal text positions across ${positions.length} text blocks.`,
3760
3821
  file: ctx.pdfPath
@@ -3762,21 +3823,21 @@ var check35 = {
3762
3823
  ];
3763
3824
  }
3764
3825
  };
3765
- registerCheck(check35);
3826
+ registerCheck(check36);
3766
3827
 
3767
3828
  // src/checks/tool-check.ts
3768
3829
  async function checkToolAvailability(config, opts = {}) {
3769
3830
  const { checks: checks2 } = selectChecks(opts, config);
3770
3831
  const toolToChecks = new Map;
3771
- for (const check36 of checks2) {
3772
- if (!check36.requiredTools?.length)
3832
+ for (const check37 of checks2) {
3833
+ if (!check37.requiredTools?.length)
3773
3834
  continue;
3774
- for (const tool of check36.requiredTools) {
3835
+ for (const tool of check37.requiredTools) {
3775
3836
  const existing = toolToChecks.get(tool);
3776
3837
  if (existing) {
3777
- existing.push(check36.id);
3838
+ existing.push(check37.id);
3778
3839
  } else {
3779
- toolToChecks.set(tool, [check36.id]);
3840
+ toolToChecks.set(tool, [check37.id]);
3780
3841
  }
3781
3842
  }
3782
3843
  }
@@ -3792,11 +3853,11 @@ async function checkToolAvailability(config, opts = {}) {
3792
3853
  const missing = results.filter((r) => !r.found).map((r) => r.tool);
3793
3854
  const missingSet = new Set(missing);
3794
3855
  const skippedChecks = [];
3795
- for (const check36 of checks2) {
3796
- if (!check36.requiredTools?.length)
3856
+ for (const check37 of checks2) {
3857
+ if (!check37.requiredTools?.length)
3797
3858
  continue;
3798
- if (check36.requiredTools.some((t) => missingSet.has(t))) {
3799
- skippedChecks.push(check36.id);
3859
+ if (check37.requiredTools.some((t) => missingSet.has(t))) {
3860
+ skippedChecks.push(check37.id);
3800
3861
  }
3801
3862
  }
3802
3863
  return { available, missing, skippedChecks, toolToChecks };
@@ -3939,6 +4000,14 @@ ${TABLE_ALIGN_CSS.trim()}`),
3939
4000
  ${pageGeometry}`)
3940
4001
  ];
3941
4002
  }
4003
+ function resolveOldFootnoteLinks(html, ids) {
4004
+ if (ids.size === 0)
4005
+ return html;
4006
+ return html.replace(/ href=(["'])#(fn(?:ref)?\d+(?::\d+)?)\1/g, (link, quote, old) => {
4007
+ const id = ids.get(old);
4008
+ return id && !html.includes(` id="${old}"`) ? ` href=${quote}#${id}${quote}` : link;
4009
+ });
4010
+ }
3942
4011
  async function assembleBookHtml(opts) {
3943
4012
  const title = opts.title ?? "Document";
3944
4013
  const projectCss = opts.projectCss ?? "";
@@ -3951,6 +4020,7 @@ async function assembleBookHtml(opts) {
3951
4020
  const md = createMarkdownRenderer(opts.plugins, { language });
3952
4021
  let bodyContent = "";
3953
4022
  const imageRefs = new Set;
4023
+ const oldFootnoteIds = new Map;
3954
4024
  for (const file of files) {
3955
4025
  const chapterId = canonicalChapterId(file);
3956
4026
  let content;
@@ -3969,9 +4039,14 @@ async function assembleBookHtml(opts) {
3969
4039
  }
3970
4040
  for (const ref of env.imageRefs ?? [])
3971
4041
  imageRefs.add(ref);
4042
+ for (const [, kind, n] of rendered.matchAll(new RegExp(` id="(fn|fnref)-${env.docId}-(\\d+(?::\\d+)?)"`, "g"))) {
4043
+ if (!oldFootnoteIds.has(`${kind}${n}`))
4044
+ oldFootnoteIds.set(`${kind}${n}`, `${kind}-${env.docId}-${n}`);
4045
+ }
3972
4046
  bodyContent += rendered + `
3973
4047
  `;
3974
4048
  }
4049
+ bodyContent = resolveOldFootnoteLinks(bodyContent, oldFootnoteIds);
3975
4050
  if (opts.onImageRefs) {
3976
4051
  for (const ref of collectHtmlImageRefs(bodyContent))
3977
4052
  imageRefs.add(ref);
@@ -4231,25 +4306,25 @@ async function runChecks(ctx, opts = {}) {
4231
4306
  }
4232
4307
  const release = retainPdfCache();
4233
4308
  try {
4234
- for (const check36 of checks2) {
4309
+ for (const check37 of checks2) {
4235
4310
  try {
4236
- const results = await check36.run(ctx);
4237
- const severityOverride = getCheckSeverityOverride(check36.id, ctx.config);
4311
+ const results = await check37.run(ctx);
4312
+ const severityOverride = getCheckSeverityOverride(check37.id, ctx.config);
4238
4313
  if (severityOverride) {
4239
4314
  for (const r of results) {
4240
4315
  r.severity = severityOverride;
4241
4316
  }
4242
4317
  }
4243
4318
  if (results.length === 0) {
4244
- passed.push(check36.id);
4319
+ passed.push(check37.id);
4245
4320
  } else {
4246
4321
  allResults.push(...results);
4247
4322
  }
4248
4323
  } catch (err) {
4249
4324
  allResults.push({
4250
- checkId: check36.id,
4325
+ checkId: check37.id,
4251
4326
  severity: "error",
4252
- message: `Check "${check36.id}" threw: ${err instanceof Error ? err.message : String(err)}`
4327
+ message: `Check "${check37.id}" threw: ${err instanceof Error ? err.message : String(err)}`
4253
4328
  });
4254
4329
  }
4255
4330
  }
@@ -4559,7 +4634,7 @@ async function executeValidation(args) {
4559
4634
  };
4560
4635
  if (args.fix) {
4561
4636
  const selected = selectChecks(runnerOptions, config).checks;
4562
- if (selected.some((check36) => check36.id === MARKDOWNLINT_CHECK_ID)) {
4637
+ if (selected.some((check37) => check37.id === MARKDOWNLINT_CHECK_ID)) {
4563
4638
  await applyMarkdownlintFixes(context);
4564
4639
  } else {
4565
4640
  log.warn(`--fix: ${MARKDOWNLINT_CHECK_ID} is not part of this run — no files were fixed.`);
@@ -5103,7 +5178,7 @@ class PdfOutput {
5103
5178
  const rawPdf = pdfxMode ? path7.join(stage, "raw.pdf") : path7.resolve(pdfFile);
5104
5179
  await fsp2.mkdir(path7.dirname(path7.resolve(pdfFile)), { recursive: true });
5105
5180
  log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
5106
- const { buildNativePdf } = await import("./engine-jvkcahr1.js");
5181
+ const { buildNativePdf } = await import("./engine-17v87vq5.js");
5107
5182
  const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
5108
5183
  title: config.title,
5109
5184
  author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
@@ -6399,11 +6474,13 @@ import path12 from "node:path";
6399
6474
 
6400
6475
  // src/lib/page-size.ts
6401
6476
  import { isMap } from "yaml";
6477
+ var PAGE_SIZE_CHECK = "pdf.print.page-size";
6402
6478
  function writePageBounds(doc, page) {
6403
6479
  ensurePageMap(doc);
6404
6480
  doc.setIn(["page", "width"], page.width);
6405
6481
  doc.setIn(["page", "height"], page.height);
6406
- doc.deleteIn(["page", "tolerance"]);
6482
+ if (page.tolerance !== undefined)
6483
+ setCheckOption(doc, PAGE_SIZE_CHECK, "tolerance", page.tolerance);
6407
6484
  }
6408
6485
  function deletePageBounds(doc) {
6409
6486
  const block = doc.get("page", true);
@@ -6411,7 +6488,7 @@ function deletePageBounds(doc) {
6411
6488
  doc.delete("page");
6412
6489
  return;
6413
6490
  }
6414
- for (const key of ["width", "height", "tolerance"])
6491
+ for (const key of ["width", "height"])
6415
6492
  block.delete(key);
6416
6493
  if (block.items.length === 0)
6417
6494
  doc.delete("page");
@@ -6468,6 +6545,9 @@ function requirePreset(preset, customPage) {
6468
6545
  } else if (customPage && (!isPositivePoints(customPage.width) || !isPositivePoints(customPage.height))) {
6469
6546
  throw new CreateProjectErrorImpl("custom-page-required", "Page overrides need a positive width and height in points (72pt = 1in).");
6470
6547
  }
6548
+ if (customPage?.tolerance !== undefined && !isPositivePoints(customPage.tolerance)) {
6549
+ throw new CreateProjectErrorImpl("custom-page-required", "Page tolerance must be a positive number of points.");
6550
+ }
6471
6551
  return preset;
6472
6552
  }
6473
6553
  function resolveScaffoldTargets(requested, preset) {
@@ -6571,7 +6651,7 @@ async function scaffoldProject(options) {
6571
6651
  let versionHistoryError;
6572
6652
  if (requested === "local-git") {
6573
6653
  try {
6574
- const { providerFor } = await import("./source-provider-n7vehh6t.js");
6654
+ const { providerFor } = await import("./source-provider-3g3yrn1f.js");
6575
6655
  const provider = providerFor({ type: "local-folder", path: projectDir });
6576
6656
  await provider.initVersionHistory({
6577
6657
  projectDir,
@@ -6624,6 +6704,12 @@ import { access as access2, mkdir as mkdir5, readFile as readFile23, writeFile a
6624
6704
  import { constants as FS2 } from "node:fs";
6625
6705
  import path13 from "node:path";
6626
6706
  var EXTENSION_KINDS = ["plugin", "look"];
6707
+ var EXTENSION_KIND_ALIASES = { theme: "look" };
6708
+ function extensionKindFor(word) {
6709
+ if (EXTENSION_KINDS.includes(word))
6710
+ return word;
6711
+ return Object.hasOwn(EXTENSION_KIND_ALIASES, word) ? EXTENSION_KIND_ALIASES[word] : undefined;
6712
+ }
6627
6713
  var RESERVED_PREFIX = "gp-";
6628
6714
  var TEMPLATE_FILES = {
6629
6715
  plugin: [
@@ -6686,9 +6772,9 @@ function escapeJsonScalar(value) {
6686
6772
  return JSON.stringify(value).slice(1, -1);
6687
6773
  }
6688
6774
  async function scaffoldExtension(options) {
6689
- const kind = options.kind;
6690
- if (kind !== "plugin" && kind !== "look") {
6691
- throw new ExtensionScaffoldError("invalid-name", `Unknown extension kind "${String(kind)}". Choose one of: ${EXTENSION_KINDS.join(", ")}.`);
6775
+ const kind = extensionKindFor(String(options.kind));
6776
+ if (!kind) {
6777
+ throw new ExtensionScaffoldError("invalid-name", `Unknown extension kind "${String(options.kind)}". Choose one of: ${EXTENSION_KINDS.join(", ")}.`);
6692
6778
  }
6693
6779
  const name = (options.name ?? "").trim();
6694
6780
  if (!name) {
@@ -8978,7 +9064,7 @@ async function resolvePublishProvider(id, book) {
8978
9064
  const ext = await bookExtensions(book);
8979
9065
  const npmEntry = ext.extensions.some((c) => !c.path && c.name === id);
8980
9066
  if (npmEntry) {
8981
- const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-as0g38p1.js");
9067
+ const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-q70wqah5.js");
8982
9068
  await restoreForCommand2(book.projectDir, { manifestPath: book.manifestPath, failFast: true });
8983
9069
  }
8984
9070
  const publishers = await discover(ext);
@@ -9016,7 +9102,7 @@ function infoFor(p) {
9016
9102
  }
9017
9103
  function pluginProvider(p) {
9018
9104
  let loading;
9019
- const load = () => loading ??= import("./plugins-zsm6wv79.js").then((m) => m.loadPublishFunction(p));
9105
+ const load = () => loading ??= import("./plugins-tqv1s16f.js").then((m) => m.loadPublishFunction(p));
9020
9106
  return {
9021
9107
  info: infoFor(p),
9022
9108
  async authenticate() {
@@ -9404,6 +9490,7 @@ var defaultGitHttp = withIdleTimeout(httpNode);
9404
9490
 
9405
9491
  // src/lib/version-changes.ts
9406
9492
  var decoder = new TextDecoder;
9493
+ var CLOCK_SKEW_SECONDS = 10 * 60;
9407
9494
  // src/lib/host-policy.ts
9408
9495
  var AUTO_SYNC_MAX_MINUTES = 24 * 60;
9409
9496
  // src/lib/remote-auth/github-repos.ts
@@ -9445,7 +9532,7 @@ class PublishSelectionsStore {
9445
9532
  return {
9446
9533
  version: 1,
9447
9534
  global: parsed.global ?? {},
9448
- projects: parsed.projects ?? {}
9535
+ projects: readProjects(parsed.projects)
9449
9536
  };
9450
9537
  }
9451
9538
  } catch {}
@@ -9531,6 +9618,27 @@ class PublishSelectionsStore {
9531
9618
  });
9532
9619
  }
9533
9620
  }
9621
+ function readProjects(projects) {
9622
+ const out = {};
9623
+ if (!projects || typeof projects !== "object")
9624
+ return out;
9625
+ for (const [book, providers] of Object.entries(projects)) {
9626
+ if (!providers || typeof providers !== "object")
9627
+ continue;
9628
+ const values = {};
9629
+ for (const [provider, value] of Object.entries(providers)) {
9630
+ if (typeof value === "string") {
9631
+ if (value.trim())
9632
+ values[provider] = { credential: value };
9633
+ } else if (value && typeof value === "object") {
9634
+ values[provider] = value;
9635
+ }
9636
+ }
9637
+ if (Object.keys(values).length > 0)
9638
+ out[book] = values;
9639
+ }
9640
+ return out;
9641
+ }
9534
9642
  function normalizeProjectKey(projectDir) {
9535
9643
  return projectDir.replace(/[\\/]+$/, "");
9536
9644
  }
@@ -9538,4 +9646,4 @@ function normalizeProjectKey(projectDir) {
9538
9646
  import { isMap as isMap4 } from "yaml";
9539
9647
  // src/lib/root-tokens.ts
9540
9648
  import postcss7 from "postcss";
9541
- export { reportMissingTools, executeValidation, executeAndReport, splitOutPath, runBuild, openPath, startPreviewServer, scaffoldProject, EXTENSION_KINDS, scaffoldExtension, BUILT_IN_TEMPLATE_IDS, importExtensionFromFile, importExtensionFromUrl, searchNpmExtensions, publishCredentialKey, publishConnectionStatus, listPublishAccounts, connectGoogleDrive, listBookPublishProviders, resolvePublishProvider, resolvePublishFormat, runPublish, connectPublishProvider, disconnectPublishCredential };
9649
+ export { reportMissingTools, executeValidation, executeAndReport, splitOutPath, runBuild, openPath, startPreviewServer, scaffoldProject, EXTENSION_KINDS, extensionKindFor, scaffoldExtension, BUILT_IN_TEMPLATE_IDS, importExtensionFromFile, importExtensionFromUrl, searchNpmExtensions, publishCredentialKey, publishConnectionStatus, listPublishAccounts, connectGoogleDrive, listBookPublishProviders, resolvePublishProvider, resolvePublishFormat, runPublish, connectPublishProvider, disconnectPublishCredential };
@@ -8,7 +8,7 @@ import {
8
8
  EXTENSIONS_DIR,
9
9
  LEGACY_PLUGINS_DIR,
10
10
  VENDORED_NPM_DIR
11
- } from "./cli-y28j019d.js";
11
+ } from "./cli-1dha1nxk.js";
12
12
 
13
13
  // src/lib/git-fs.ts
14
14
  import * as nodeFs from "node:fs";
@@ -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,6 +1,6 @@
1
1
  import {
2
2
  package_default
3
- } from "./cli-s1zt779w.js";
3
+ } from "./cli-q7t04gjt.js";
4
4
 
5
5
  // src/utils/logger.ts
6
6
  var currentLevel = "INFO";