gutterpress 0.11.23-alpha.3 → 0.11.23-alpha.5

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 (75) hide show
  1. package/README.md +4 -6
  2. package/dist/{README-8db7btxb.md → README-syg2hn83.md} +1 -1
  3. package/dist/api/index.d.ts +1 -1
  4. package/dist/api/index.js +7 -5
  5. package/dist/{build-m78jcpf7.js → build-4qv9wvrx.js} +8 -8
  6. package/dist/checks/asset/extensions.d.ts +1 -1
  7. package/dist/checks/asset/index.d.ts +0 -1
  8. package/dist/checks/policy.d.ts +5 -4
  9. package/dist/checks/source/config-file.d.ts +9 -6
  10. package/dist/checks/source/dangling-links.d.ts +1 -1
  11. package/dist/checks/types.d.ts +2 -2
  12. package/dist/{cli-s6djx4ma.js → cli-2t3krcfy.js} +1 -1
  13. package/dist/{cli-xsrffqzt.js → cli-58fsk6d7.js} +9 -9
  14. package/dist/{cli-2ppw6q9v.js → cli-5crpmz42.js} +80 -1
  15. package/dist/{cli-t8be9yeb.js → cli-de8ydmm7.js} +12 -7
  16. package/dist/{cli-n2tsxqpn.js → cli-nk0efg2x.js} +7 -2
  17. package/dist/{cli-1h17ktsg.js → cli-pth362d8.js} +139 -222
  18. package/dist/{cli-h4x81x97.js → cli-w97xcpag.js} +207 -142
  19. package/dist/{cli-5jzyw06s.js → cli-yxfznmsq.js} +1 -1
  20. package/dist/cli.js +12 -12
  21. package/dist/{doctor-j71jqce3.js → doctor-5nh3t346.js} +4 -3
  22. package/dist/{engine-m4y10shc.js → engine-4rabsgwq.js} +1 -1
  23. package/dist/{engine-1r6q80tq.js → engine-wm4fggac.js} +2 -2
  24. package/dist/{ext-fq2hg9va.js → ext-nhcep6h6.js} +8 -8
  25. package/dist/{extension-restore-9dh7c4tp.js → extension-restore-55kp0ksq.js} +2 -2
  26. package/dist/{extension-restore-tmxtzkm0.js → extension-restore-x3mtn844.js} +4 -4
  27. package/dist/{index-nedd07bk.js → index-2vxzxyyj.js} +9 -9
  28. package/dist/{index-2ppw6q9v.js → index-5crpmz42.js} +80 -1
  29. package/dist/{index-0wee4408.js → index-9ye22m7r.js} +12 -7
  30. package/dist/{index-prqvz3xm.js → index-agrkfbkv.js} +217 -244
  31. package/dist/{index-7pck1q9c.js → index-t3jkavdz.js} +206 -141
  32. package/dist/{index-nvmf22rt.js → index-wm4x7xbf.js} +1 -1
  33. package/dist/index.js +8 -6
  34. package/dist/lib/build-preflight.d.ts +4 -10
  35. package/dist/lib/build-runner.d.ts +1 -1
  36. package/dist/lib/ghostscript.d.ts +5 -2
  37. package/dist/lib/lint-rules.d.ts +5 -1
  38. package/dist/lib/manifest-config.d.ts +3 -2
  39. package/dist/lib/manifest-old-spellings.d.ts +64 -0
  40. package/dist/lib/markdown/chapter-id.d.ts +1 -1
  41. package/dist/lib/markdown/index.d.ts +1 -1
  42. package/dist/lib/markdown/table.d.ts +5 -3
  43. package/dist/lib/page-size.d.ts +14 -9
  44. package/dist/lib/pdf-inspect.d.ts +27 -0
  45. package/dist/lib/presets.d.ts +10 -8
  46. package/dist/lib/printsafe.d.ts +1 -1
  47. package/dist/lib/project-scaffold.d.ts +1 -1
  48. package/dist/lib/publish/connect.d.ts +8 -1
  49. package/dist/lib/publish/manifest-publish.d.ts +26 -2
  50. package/dist/lib/publish/selections.d.ts +12 -1
  51. package/dist/lib/publish/types.d.ts +15 -5
  52. package/dist/lib/remote-auth/sync-messages.d.ts +2 -2
  53. package/dist/lib/targets.d.ts +4 -4
  54. package/dist/lib/validation-exec.d.ts +4 -4
  55. package/dist/{manifest-my7mdv8j.yaml → manifest-2kc56wvw.yaml} +3 -4
  56. package/dist/{manifest-8afhrk30.yaml → manifest-41ddzm13.yaml} +3 -4
  57. package/dist/{manifest-gf13sjp8.yaml → manifest-79zsgkpn.yaml} +3 -4
  58. package/dist/{manifest-d4f9q79e.yaml → manifest-sqzm4681.yaml} +3 -4
  59. package/dist/{manifest.schema-650pe0d1.json → manifest.schema-93sd7zje.json} +32 -315
  60. package/dist/{new-s4zcaepg.js → new-5a4w2vkh.js} +9 -15
  61. package/dist/{page-rules-fj09xct5.css → page-rules-ytj9p04v.css} +1 -1
  62. package/dist/{pdf-inspect-wnw4za71.js → pdf-inspect-b3mf81ex.js} +3 -1
  63. package/dist/{plugins-4vaf27n9.js → plugins-cfzf26b8.js} +3 -3
  64. package/dist/{plugins-80emnf31.js → plugins-mm8270tn.js} +1 -1
  65. package/dist/{preflight-c7w1xdn3.js → preflight-jma71n0j.js} +8 -8
  66. package/dist/preview/file-watcher.d.ts +1 -3
  67. package/dist/{preview-interface-nnmrxyqm.js → preview-interface-0xdh0r5b.js} +3 -66
  68. package/dist/{preview-mzytcwyk.js → preview-kmx4h7gv.js} +8 -8
  69. package/dist/{publish-fez14ad4.js → publish-62843020.js} +8 -8
  70. package/dist/render.js +6 -1
  71. package/dist/schema/manifest.types.d.ts +58 -110
  72. package/dist/{tokens-ye64p899.css → tokens-n82t4k9h.css} +11 -4
  73. package/dist/{validate-p2chr6hr.js → validate-vvmrd85g.js} +8 -8
  74. package/package.json +1 -1
  75. package/dist/checks/asset/approved-fonts.d.ts +0 -3
@@ -8,7 +8,7 @@ import {
8
8
  stampCreator,
9
9
  stripAnnotations,
10
10
  transparentPages
11
- } from "./cli-n2tsxqpn.js";
11
+ } from "./cli-nk0efg2x.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-xsrffqzt.js";
20
+ } from "./cli-58fsk6d7.js";
21
21
  import {
22
22
  countLinkAnnotations,
23
23
  getImageResolutions,
@@ -30,7 +30,7 @@ import {
30
30
  loadPdf,
31
31
  pageHasMarks,
32
32
  retainPdfCache
33
- } from "./cli-2ppw6q9v.js";
33
+ } from "./cli-5crpmz42.js";
34
34
  import {
35
35
  INSTALL_HINTS,
36
36
  execCapture,
@@ -75,7 +75,7 @@ import {
75
75
  uniqueExtensionId,
76
76
  withFetchTimeout,
77
77
  writeManifestDoc
78
- } from "./cli-h4x81x97.js";
78
+ } from "./cli-w97xcpag.js";
79
79
  import {
80
80
  EXTENSION_MANIFEST_FILENAME,
81
81
  GUTTERPRESS_CSS,
@@ -96,7 +96,7 @@ import {
96
96
  readExtensionMeta,
97
97
  resolveDeclaredStyles,
98
98
  slugify
99
- } from "./cli-t8be9yeb.js";
99
+ } from "./cli-de8ydmm7.js";
100
100
  import {
101
101
  PACKAGE_META,
102
102
  PACKAGE_VERSION,
@@ -106,7 +106,7 @@ import {
106
106
  log,
107
107
  setLogLevel,
108
108
  warn
109
- } from "./cli-s6djx4ma.js";
109
+ } from "./cli-2t3krcfy.js";
110
110
  import {
111
111
  DEBOUNCE,
112
112
  UsageError,
@@ -189,10 +189,7 @@ function selectorToRegex(selector) {
189
189
  // src/checks/policy.ts
190
190
  var INSPECT_FAILED_CODE = "inspect-failed";
191
191
  function isCheckEnabled(check, config) {
192
- const entry = config.validate.checks[check.id];
193
- if (entry === false)
194
- return false;
195
- if (typeof entry === "object" && entry.enabled === false)
192
+ if (config.checks[check.id] === "off")
196
193
  return false;
197
194
  if (check.enabledWhen && !check.enabledWhen(config))
198
195
  return false;
@@ -773,7 +770,7 @@ var check8 = {
773
770
  severity: "warning",
774
771
  message: `Dark four-colour text at ${LARGE_TEXT_PT}pt or smaller on page(s) ${found.pages.join(", ")}.`,
775
772
  file: ctx.pdfPath,
776
- detail: "Small text printed with all four inks can look fuzzy if the plates are slightly out of register, which is why print vendors such as DriveThruRPG want small black text on the black plate alone. `pdfx.blackText: k-only` already does that for near-black text; this text is either a dark colour (for example a dark brown, which keeps its colour) or painted in a way the build cannot rewrite (an image or a pattern). To print it on the black plate, make the text black (#000). If the colour is intended, set `lint.rules: { pdf.print.black-text: off }` in manifest.yaml.",
773
+ detail: "Small text printed with all four inks can look fuzzy if the plates are slightly out of register, which is why print vendors such as DriveThruRPG want small black text on the black plate alone. `pdfx.blackText: k-only` already does that for near-black text; this text is either a dark colour (for example a dark brown, which keeps its colour) or painted in a way the build cannot rewrite (an image or a pattern). To print it on the black plate, make the text black (#000). If the colour is intended, set `checks: { pdf.print.black-text: off }` in manifest.yaml.",
777
774
  code: "rich-black-text",
778
775
  data: { runs: found.runs, pages: found.pages }
779
776
  })
@@ -853,8 +850,6 @@ var check10 = {
853
850
  async run(ctx) {
854
851
  if (!ctx.pdfPath)
855
852
  return [];
856
- if (!ctx.config.validate.pdf.requireBookmarks)
857
- return [];
858
853
  const doc = await loadPdf(ctx.pdfPath);
859
854
  if (!doc) {
860
855
  return [
@@ -887,8 +882,6 @@ var check11 = {
887
882
  async run(ctx) {
888
883
  if (!ctx.pdfPath)
889
884
  return [];
890
- if (!ctx.config.validate.pdf.requireTocLinks)
891
- return [];
892
885
  const doc = await loadPdf(ctx.pdfPath);
893
886
  if (!doc) {
894
887
  return [
@@ -1026,8 +1019,6 @@ var check15 = {
1026
1019
  async run(ctx) {
1027
1020
  if (!ctx.pdfPath)
1028
1021
  return [];
1029
- if (!ctx.config.validate.pdf.forbidTransparency)
1030
- return [];
1031
1022
  const bytes = await readPdfBytes(ctx.pdfPath).catch(() => "");
1032
1023
  const found = [];
1033
1024
  if (bytes.includes("/Transparency"))
@@ -1068,8 +1059,6 @@ var check16 = {
1068
1059
  async run(ctx) {
1069
1060
  if (!ctx.pdfPath)
1070
1061
  return [];
1071
- if (!ctx.config.validate.pdf.requireBleed)
1072
- return [];
1073
1062
  const bytes = await readPdfBytes(ctx.pdfPath).catch(() => "");
1074
1063
  if (!bytes) {
1075
1064
  return [
@@ -1160,18 +1149,20 @@ import { parse as parseYaml } from "yaml";
1160
1149
 
1161
1150
  // src/checks/source/config-file.ts
1162
1151
  import { existsSync } from "node:fs";
1163
- import { resolve } from "node:path";
1164
- function findConfigFile(inputDir, names, explicit) {
1165
- if (explicit) {
1166
- const p = resolve(inputDir, explicit);
1167
- return existsSync(p) ? p : null;
1168
- }
1169
- for (const name of names) {
1170
- const p = resolve(inputDir, name);
1171
- if (existsSync(p))
1172
- return p;
1152
+ import { dirname, resolve } from "node:path";
1153
+ function findConfigFile(startDir, names) {
1154
+ let dir = resolve(startDir);
1155
+ for (;; ) {
1156
+ for (const name of names) {
1157
+ const p = resolve(dir, name);
1158
+ if (existsSync(p))
1159
+ return p;
1160
+ }
1161
+ const parent = dirname(dir);
1162
+ if (existsSync(resolve(dir, ".git")) || parent === dir)
1163
+ return null;
1164
+ dir = parent;
1173
1165
  }
1174
- return null;
1175
1166
  }
1176
1167
 
1177
1168
  // src/checks/source/markdownlint.ts
@@ -1213,17 +1204,13 @@ var check18 = {
1213
1204
  category: "source",
1214
1205
  phase: "pre-build",
1215
1206
  async run(ctx) {
1216
- const sourceConfig = ctx.config.validate.source;
1217
- if (sourceConfig.markdownlint === false)
1218
- return [];
1219
1207
  const files = ctx.markdownFiles;
1220
1208
  if (!files || files.length === 0)
1221
1209
  return [];
1222
- const configPath = typeof sourceConfig.markdownlint === "string" ? sourceConfig.markdownlint : null;
1223
- const resolvedConfig = findConfigFile(ctx.inputDir, CONFIG_NAMES, configPath);
1224
- if (!resolvedConfig && !configPath)
1210
+ const resolvedConfig = findConfigFile(ctx.inputDir, CONFIG_NAMES);
1211
+ if (!resolvedConfig)
1225
1212
  return [];
1226
- const config = resolvedConfig ? await loadConfig(resolvedConfig) : { default: true };
1213
+ const config = await loadConfig(resolvedConfig);
1227
1214
  const results = lint({ files, config });
1228
1215
  const out = [];
1229
1216
  for (const [file, violations] of Object.entries(results)) {
@@ -1259,14 +1246,10 @@ var check19 = {
1259
1246
  category: "source",
1260
1247
  phase: "pre-build",
1261
1248
  async run(ctx) {
1262
- const sourceConfig = ctx.config.validate.source;
1263
- if (sourceConfig.htmlhint === false)
1264
- return [];
1265
1249
  if (!ctx.htmlPath || !existsSync2(ctx.htmlPath))
1266
1250
  return [];
1267
- const configPath = typeof sourceConfig.htmlhint === "string" ? sourceConfig.htmlhint : null;
1268
- const resolvedConfig = findConfigFile(ctx.inputDir, CONFIG_NAMES2, configPath);
1269
- if (!resolvedConfig && !configPath)
1251
+ const resolvedConfig = findConfigFile(ctx.inputDir, CONFIG_NAMES2);
1252
+ if (!resolvedConfig)
1270
1253
  return [];
1271
1254
  const ruleset = resolvedConfig ? JSON.parse(await readFile4(resolvedConfig, "utf8")) : HTMLHint.defaultRuleset;
1272
1255
  const html = await readFile4(ctx.htmlPath, "utf8");
@@ -1294,7 +1277,7 @@ function ruleLevel(rules, id) {
1294
1277
  const v = rules?.[id];
1295
1278
  if (v === "off" || v === false)
1296
1279
  return "off";
1297
- if (v === "warn" || v === "warning")
1280
+ if (v === "warn" || v === "warning" || v === "info")
1298
1281
  return "warn";
1299
1282
  if (v === "error")
1300
1283
  return "error";
@@ -1613,7 +1596,7 @@ function checkCssRaw(css, from) {
1613
1596
  warnings.push({
1614
1597
  rule: rulePageSizeInStylesheet,
1615
1598
  severity: "warning",
1616
- message: `"size" in a stylesheet's @page rule is ignored: the page size comes from the manifest (preset:, or page: width and height — Setup > Details in the app), which is written after every stylesheet. Remove this declaration; to print at another size, change the manifest.`,
1599
+ message: `"size" in a stylesheet's @page rule is ignored: the page size comes from the manifest (preset:, or page: width and height — Setup > Book in the app), which is written after every stylesheet. Remove this declaration; to print at another size, change the manifest.`,
1617
1600
  ...nodeLoc(decl)
1618
1601
  });
1619
1602
  return;
@@ -1713,10 +1696,7 @@ var check20 = {
1713
1696
  description: "Checks CSS for print-safety issues (remote URLs, rasterizing effects, and page-layer containment)",
1714
1697
  category: "source",
1715
1698
  phase: "pre-build",
1716
- enabledWhen: (config) => config.validate.source.stylelint !== false,
1717
1699
  async run(ctx) {
1718
- if (ctx.config.validate.source.stylelint === false)
1719
- return [];
1720
1700
  const files = ctx.cssFiles;
1721
1701
  if (!files || files.length === 0)
1722
1702
  return [];
@@ -1734,7 +1714,7 @@ var check20 = {
1734
1714
  });
1735
1715
  continue;
1736
1716
  }
1737
- for (const w of checkCss(css, file, { rules: ctx.config.lint.rules })) {
1717
+ for (const w of checkCss(css, file, { rules: ctx.config.checks })) {
1738
1718
  results.push({
1739
1719
  checkId: check20.id,
1740
1720
  severity: w.severity,
@@ -1930,15 +1910,11 @@ var check21 = {
1930
1910
  description: "Checks an optional per-project CSS ownership contract (.gutterpress/css-contract.yaml): which file may declare which properties/at-rules, and which selectors must never appear unscoped.",
1931
1911
  category: "source",
1932
1912
  phase: "pre-build",
1933
- enabledWhen: (config) => config.validate.source.cssOwnership !== false,
1934
1913
  async run(ctx) {
1935
- if (ctx.config.validate.source.cssOwnership === false)
1936
- return [];
1937
1914
  const files = ctx.cssFiles;
1938
1915
  if (!files || files.length === 0)
1939
1916
  return [];
1940
- const explicit = typeof ctx.config.validate.source.cssOwnership === "string" ? ctx.config.validate.source.cssOwnership : null;
1941
- const configPath = findConfigFile(ctx.inputDir, CONFIG_NAMES3, explicit);
1917
+ const configPath = findConfigFile(ctx.inputDir, CONFIG_NAMES3);
1942
1918
  if (!configPath)
1943
1919
  return [];
1944
1920
  let contract;
@@ -2005,7 +1981,7 @@ registerCheck(check21);
2005
1981
 
2006
1982
  // src/checks/source/local-refs.ts
2007
1983
  import { existsSync as existsSync4 } from "node:fs";
2008
- import { dirname, resolve as resolve2 } from "node:path";
1984
+ import { dirname as dirname2, resolve as resolve2 } from "node:path";
2009
1985
 
2010
1986
  // src/lib/asset-inline.ts
2011
1987
  import { createHash } from "node:crypto";
@@ -2431,7 +2407,7 @@ function filesystemRef(ref) {
2431
2407
  }
2432
2408
  function localRefExists(ref, kind, sourceFile, projectRoot) {
2433
2409
  const cleaned = filesystemRef(ref);
2434
- const fileRelative = resolve2(dirname(sourceFile), cleaned);
2410
+ const fileRelative = resolve2(dirname2(sourceFile), cleaned);
2435
2411
  const rootRelative = resolve2(projectRoot, cleaned);
2436
2412
  switch (kind) {
2437
2413
  case "image":
@@ -3533,8 +3509,6 @@ var check30 = {
3533
3509
  category: "asset",
3534
3510
  phase: "pre-build",
3535
3511
  async run(ctx) {
3536
- if (ctx.config.validate.assets.allowAlpha)
3537
- return [];
3538
3512
  if (ctx.config.pdfx.transparency === "preserve-text")
3539
3513
  return [];
3540
3514
  const files = shippedImages(ctx, ["png", "tiff", "tif"]);
@@ -3557,58 +3531,6 @@ var check30 = {
3557
3531
  };
3558
3532
  registerCheck(check30);
3559
3533
 
3560
- // src/checks/asset/approved-fonts.ts
3561
- var check31 = {
3562
- id: "asset.font.approved-files",
3563
- name: "Approved Font Files",
3564
- description: "Checks font files against the approved file patterns",
3565
- category: "asset",
3566
- phase: "pre-build",
3567
- async run(ctx) {
3568
- const patterns = ctx.config.validate.assets.approvedFontFiles;
3569
- if (!patterns || patterns.length === 0)
3570
- return [];
3571
- const { glob } = await import("glob");
3572
- const dirs = ctx.assetDirs ?? [ctx.inputDir];
3573
- const allFonts = [];
3574
- for (const dir of dirs) {
3575
- const matches = await glob(`**/*.{${FONT_EXTS2.join(",")}}`, {
3576
- cwd: dir,
3577
- absolute: true,
3578
- ignore: [...ASSET_SCAN_IGNORE_GLOBS]
3579
- });
3580
- allFonts.push(...matches);
3581
- }
3582
- if (allFonts.length === 0)
3583
- return [];
3584
- const approvedFonts = new Set;
3585
- for (const dir of dirs) {
3586
- for (const pattern of patterns) {
3587
- const matches = await glob(pattern, {
3588
- cwd: dir,
3589
- absolute: true,
3590
- ignore: [...ASSET_SCAN_IGNORE_GLOBS]
3591
- });
3592
- for (const m of matches)
3593
- approvedFonts.add(m);
3594
- }
3595
- }
3596
- const results = [];
3597
- for (const font of allFonts) {
3598
- if (!approvedFonts.has(font)) {
3599
- results.push({
3600
- checkId: check31.id,
3601
- severity: "warning",
3602
- message: "Font file not in approved list",
3603
- file: font
3604
- });
3605
- }
3606
- }
3607
- return results;
3608
- }
3609
- };
3610
- registerCheck(check31);
3611
-
3612
3534
  // src/checks/asset/font-license.ts
3613
3535
  import { existsSync as existsSync5 } from "node:fs";
3614
3536
  import { resolve as resolve3 } from "node:path";
@@ -3622,15 +3544,13 @@ var LICENSE_NAMES = [
3622
3544
  "OFL-1.1.txt",
3623
3545
  "COPYING"
3624
3546
  ];
3625
- var check32 = {
3547
+ var check31 = {
3626
3548
  id: "asset.font.license",
3627
3549
  name: "Font License",
3628
3550
  description: "Checks for license files in font directories",
3629
3551
  category: "asset",
3630
3552
  phase: "pre-build",
3631
3553
  async run(ctx) {
3632
- if (!ctx.config.validate.assets.requireFontLicense)
3633
- return [];
3634
3554
  const { glob } = await import("glob");
3635
3555
  const dirs = ctx.assetDirs ?? [ctx.inputDir];
3636
3556
  const fontDirs = new Set;
@@ -3649,7 +3569,7 @@ var check32 = {
3649
3569
  const hasLicense = LICENSE_NAMES.some((name) => existsSync5(resolve3(fontDir, name)));
3650
3570
  if (!hasLicense) {
3651
3571
  results.push({
3652
- checkId: check32.id,
3572
+ checkId: check31.id,
3653
3573
  severity: "warning",
3654
3574
  message: `No font license file found in directory`,
3655
3575
  file: fontDir
@@ -3659,10 +3579,10 @@ var check32 = {
3659
3579
  return results;
3660
3580
  }
3661
3581
  };
3662
- registerCheck(check32);
3582
+ registerCheck(check31);
3663
3583
 
3664
3584
  // src/checks/heuristic/text-density.ts
3665
- var check33 = {
3585
+ var check32 = {
3666
3586
  id: "heuristic.whitespace.text-density",
3667
3587
  name: "Text Density",
3668
3588
  description: "Checks characters-per-page ratio",
@@ -3691,7 +3611,7 @@ var check33 = {
3691
3611
  });
3692
3612
  if (lowPages.length > 0) {
3693
3613
  results.push({
3694
- checkId: check33.id,
3614
+ checkId: check32.id,
3695
3615
  severity: "info",
3696
3616
  message: `Low text density on pages: ${lowPages.join(", ")} (below ${range.min} chars)`,
3697
3617
  file: ctx.pdfPath
@@ -3699,7 +3619,7 @@ var check33 = {
3699
3619
  }
3700
3620
  if (highPages.length > 0) {
3701
3621
  results.push({
3702
- checkId: check33.id,
3622
+ checkId: check32.id,
3703
3623
  severity: "info",
3704
3624
  message: `High text density on pages: ${highPages.join(", ")} (above ${range.max} chars)`,
3705
3625
  file: ctx.pdfPath
@@ -3708,11 +3628,11 @@ var check33 = {
3708
3628
  return results;
3709
3629
  }
3710
3630
  };
3711
- registerCheck(check33);
3631
+ registerCheck(check32);
3712
3632
 
3713
3633
  // src/checks/heuristic/section-density.ts
3714
3634
  import { readFile as readFile15 } from "node:fs/promises";
3715
- var check34 = {
3635
+ var check33 = {
3716
3636
  id: "heuristic.chunking.section-density",
3717
3637
  name: "Section Density",
3718
3638
  description: "Checks heading/paragraph/callout density from source Markdown",
@@ -3738,7 +3658,7 @@ var check34 = {
3738
3658
  const line = lines[i];
3739
3659
  if (/^#{1,6}\s/.test(line)) {
3740
3660
  if (paragraphCount > maxParas) {
3741
- results.push(finding(check34.id, {
3661
+ results.push(finding(check33.id, {
3742
3662
  severity: "info",
3743
3663
  message: `Section has ${paragraphCount} paragraphs (max recommended: ${maxParas})`,
3744
3664
  file,
@@ -3758,7 +3678,7 @@ var check34 = {
3758
3678
  }
3759
3679
  }
3760
3680
  if (paragraphCount > maxParas) {
3761
- results.push(finding(check34.id, {
3681
+ results.push(finding(check33.id, {
3762
3682
  severity: "info",
3763
3683
  message: `Section has ${paragraphCount} paragraphs (max recommended: ${maxParas})`,
3764
3684
  file,
@@ -3766,7 +3686,7 @@ var check34 = {
3766
3686
  }));
3767
3687
  }
3768
3688
  } catch {
3769
- results.push(inspectionFailed(check34.id, `Could not read source file: ${file}`, {
3689
+ results.push(inspectionFailed(check33.id, `Could not read source file: ${file}`, {
3770
3690
  file
3771
3691
  }));
3772
3692
  }
@@ -3774,10 +3694,10 @@ var check34 = {
3774
3694
  return results;
3775
3695
  }
3776
3696
  };
3777
- registerCheck(check34);
3697
+ registerCheck(check33);
3778
3698
 
3779
3699
  // src/checks/heuristic/layer-count.ts
3780
- var check35 = {
3700
+ var check34 = {
3781
3701
  id: "heuristic.decoration.layer-count",
3782
3702
  name: "Layer Count",
3783
3703
  description: "Counts image objects per page",
@@ -3802,7 +3722,7 @@ var check35 = {
3802
3722
  heavyPages.sort((a, b) => a - b);
3803
3723
  return [
3804
3724
  {
3805
- checkId: check35.id,
3725
+ checkId: check34.id,
3806
3726
  severity: "info",
3807
3727
  message: `Pages with many image layers (>${maxLayers}): ${heavyPages.join(", ")}`,
3808
3728
  file: ctx.pdfPath
@@ -3812,10 +3732,10 @@ var check35 = {
3812
3732
  return [];
3813
3733
  }
3814
3734
  };
3815
- registerCheck(check35);
3735
+ registerCheck(check34);
3816
3736
 
3817
3737
  // src/checks/heuristic/placement-variance.ts
3818
- var check36 = {
3738
+ var check35 = {
3819
3739
  id: "heuristic.layout.placement-variance",
3820
3740
  name: "Placement Variance",
3821
3741
  description: "Analyzes text baseline coordinates for layout consistency",
@@ -3833,7 +3753,7 @@ var check36 = {
3833
3753
  const uniqueX = new Set(positions.map((p) => Math.round(p.x)));
3834
3754
  return [
3835
3755
  {
3836
- checkId: check36.id,
3756
+ checkId: check35.id,
3837
3757
  severity: "info",
3838
3758
  message: `Layout analysis: ${uniqueX.size} unique horizontal text positions across ${positions.length} text blocks.`,
3839
3759
  file: ctx.pdfPath
@@ -3841,21 +3761,21 @@ var check36 = {
3841
3761
  ];
3842
3762
  }
3843
3763
  };
3844
- registerCheck(check36);
3764
+ registerCheck(check35);
3845
3765
 
3846
3766
  // src/checks/tool-check.ts
3847
3767
  async function checkToolAvailability(config, opts = {}) {
3848
3768
  const { checks: checks2 } = selectChecks(opts, config);
3849
3769
  const toolToChecks = new Map;
3850
- for (const check37 of checks2) {
3851
- if (!check37.requiredTools?.length)
3770
+ for (const check36 of checks2) {
3771
+ if (!check36.requiredTools?.length)
3852
3772
  continue;
3853
- for (const tool of check37.requiredTools) {
3773
+ for (const tool of check36.requiredTools) {
3854
3774
  const existing = toolToChecks.get(tool);
3855
3775
  if (existing) {
3856
- existing.push(check37.id);
3776
+ existing.push(check36.id);
3857
3777
  } else {
3858
- toolToChecks.set(tool, [check37.id]);
3778
+ toolToChecks.set(tool, [check36.id]);
3859
3779
  }
3860
3780
  }
3861
3781
  }
@@ -3871,11 +3791,11 @@ async function checkToolAvailability(config, opts = {}) {
3871
3791
  const missing = results.filter((r) => !r.found).map((r) => r.tool);
3872
3792
  const missingSet = new Set(missing);
3873
3793
  const skippedChecks = [];
3874
- for (const check37 of checks2) {
3875
- if (!check37.requiredTools?.length)
3794
+ for (const check36 of checks2) {
3795
+ if (!check36.requiredTools?.length)
3876
3796
  continue;
3877
- if (check37.requiredTools.some((t) => missingSet.has(t))) {
3878
- skippedChecks.push(check37.id);
3797
+ if (check36.requiredTools.some((t) => missingSet.has(t))) {
3798
+ skippedChecks.push(check36.id);
3879
3799
  }
3880
3800
  }
3881
3801
  return { available, missing, skippedChecks, toolToChecks };
@@ -3895,7 +3815,7 @@ function reportMissingTools(result) {
3895
3815
  // src/lib/validation-exec.ts
3896
3816
  import { existsSync as existsSync6 } from "node:fs";
3897
3817
  import { readFile as readFile18 } from "node:fs/promises";
3898
- import { dirname as dirname2, join as join2, resolve as resolve4 } from "node:path";
3818
+ import { dirname as dirname3, join as join2, resolve as resolve4 } from "node:path";
3899
3819
 
3900
3820
  // src/lib/output-paths.ts
3901
3821
  import path5 from "node:path";
@@ -4140,8 +4060,7 @@ async function uncommittedAmong(inputDir, files) {
4140
4060
  return files.filter((file) => changed.has(repoSubPath(repoRoot, file)));
4141
4061
  }
4142
4062
  async function applyMarkdownlintFixes(ctx) {
4143
- const sourceConfig = ctx.config.validate.source;
4144
- if (sourceConfig.markdownlint === false) {
4063
+ if (ctx.config.checks["source.markdownlint"] === "off") {
4145
4064
  log.warn("--fix: source.markdownlint is disabled for this book — no files were fixed.");
4146
4065
  return [];
4147
4066
  }
@@ -4150,13 +4069,12 @@ async function applyMarkdownlintFixes(ctx) {
4150
4069
  log.warn("--fix: no markdown files to fix.");
4151
4070
  return [];
4152
4071
  }
4153
- const configPath = typeof sourceConfig.markdownlint === "string" ? sourceConfig.markdownlint : null;
4154
- const resolvedConfig = findConfigFile(ctx.inputDir, CONFIG_NAMES, configPath);
4155
- if (!resolvedConfig && !configPath) {
4156
- log.warn(`--fix: no markdownlint config found in ${ctx.inputDir} (looked for ${CONFIG_NAMES.join(", ")}) — no files were fixed.`);
4072
+ const resolvedConfig = findConfigFile(ctx.inputDir, CONFIG_NAMES);
4073
+ if (!resolvedConfig) {
4074
+ log.warn(`--fix: no markdownlint config found in ${ctx.inputDir} or a folder above it (looked for ${CONFIG_NAMES.join(", ")}) — no files were fixed.`);
4157
4075
  return [];
4158
4076
  }
4159
- const config = resolvedConfig ? await loadConfig(resolvedConfig) : { default: true };
4077
+ const config = await loadConfig(resolvedConfig);
4160
4078
  const results = lint2({ files, config });
4161
4079
  const pending = [];
4162
4080
  for (const [file, violations] of Object.entries(results)) {
@@ -4245,15 +4163,10 @@ function formatLocation(file, line, column) {
4245
4163
 
4246
4164
  // src/checks/runner.ts
4247
4165
  function getCheckSeverityOverride(checkId, config) {
4248
- const entry = config.validate.checks[checkId];
4249
- if (typeof entry === "object" && entry.severity)
4250
- return entry.severity;
4251
- return;
4166
+ const level = config.checks[checkId];
4167
+ return level === "off" || level === "on" ? undefined : level;
4252
4168
  }
4253
4169
  async function runChecks(ctx, opts = {}) {
4254
- if (ctx.config.validate.enabled === false) {
4255
- return emptyReport();
4256
- }
4257
4170
  const { checks: selected, unmatched: unmatchedSelectors } = selectChecks(opts, ctx.config);
4258
4171
  let checks2 = selected;
4259
4172
  if (opts.skipMissingTools && opts.skipMissingTools.length > 0) {
@@ -4271,32 +4184,25 @@ async function runChecks(ctx, opts = {}) {
4271
4184
  }
4272
4185
  const release = retainPdfCache();
4273
4186
  try {
4274
- for (const check37 of checks2) {
4187
+ for (const check36 of checks2) {
4275
4188
  try {
4276
- let results = await check37.run(ctx);
4277
- const severityOverride = getCheckSeverityOverride(check37.id, ctx.config);
4189
+ const results = await check36.run(ctx);
4190
+ const severityOverride = getCheckSeverityOverride(check36.id, ctx.config);
4278
4191
  if (severityOverride) {
4279
4192
  for (const r of results) {
4280
4193
  r.severity = severityOverride;
4281
4194
  }
4282
4195
  }
4283
- const lintLevel = ruleLevel(ctx.config.lint.rules, check37.id);
4284
- if (lintLevel === "off")
4285
- results = [];
4286
- else if (lintLevel) {
4287
- for (const r of results)
4288
- r.severity = lintLevel === "warn" ? "warning" : "error";
4289
- }
4290
4196
  if (results.length === 0) {
4291
- passed.push(check37.id);
4197
+ passed.push(check36.id);
4292
4198
  } else {
4293
4199
  allResults.push(...results);
4294
4200
  }
4295
4201
  } catch (err) {
4296
4202
  allResults.push({
4297
- checkId: check37.id,
4203
+ checkId: check36.id,
4298
4204
  severity: "error",
4299
- message: `Check "${check37.id}" threw: ${err instanceof Error ? err.message : String(err)}`
4205
+ message: `Check "${check36.id}" threw: ${err instanceof Error ? err.message : String(err)}`
4300
4206
  });
4301
4207
  }
4302
4208
  }
@@ -4321,16 +4227,6 @@ async function runChecks(ctx, opts = {}) {
4321
4227
  }
4322
4228
  };
4323
4229
  }
4324
- function emptyReport() {
4325
- return {
4326
- results: [],
4327
- errors: [],
4328
- warnings: [],
4329
- infos: [],
4330
- passed: [],
4331
- summary: { total: 0, errors: 0, warnings: 0, infos: 0, passed: 0 }
4332
- };
4333
- }
4334
4230
 
4335
4231
  // src/lib/validation-exec.ts
4336
4232
  var SHIPPED_ASSET_EXTS = new Set([
@@ -4386,7 +4282,7 @@ async function sharedAssetDirs(manifestDir, relStyles, inputDir) {
4386
4282
  const ext = file.slice(file.lastIndexOf(".")).toLowerCase();
4387
4283
  if (!SHIPPED_ASSET_EXTS.has(ext))
4388
4284
  continue;
4389
- const dir = dirname2(resolve4(file));
4285
+ const dir = dirname3(resolve4(file));
4390
4286
  if (escapesProjectRoot(projectRoot, dir))
4391
4287
  dirs.add(dir);
4392
4288
  }
@@ -4547,7 +4443,7 @@ function planRuns(opts) {
4547
4443
  async function executeValidation(args) {
4548
4444
  const manifestPath = typeof args.manifest === "string" ? args.manifest : undefined;
4549
4445
  const { manifest, manifestDir } = await loadManifestWithPath(manifestPath ?? args.input ?? undefined, { explicit: manifestPath !== undefined });
4550
- const config = resolveConfig(args.skipStylelint ? { validate: { source: { stylelint: false } } } : {}, manifest);
4446
+ const config = resolveConfig(args.skipStylelint ? { checks: { "source.stylelint": "off" } } : {}, manifest);
4551
4447
  const targetIds = resolveTargets(parseCsv(typeof args.target === "string" ? args.target : undefined), config.targets);
4552
4448
  const pdfPath = typeof args.pdf === "string" ? resolve4(args.pdf) : undefined;
4553
4449
  const inputDir = typeof args.input === "string" ? resolve4(args.input) : undefined;
@@ -4580,7 +4476,7 @@ async function executeValidation(args) {
4580
4476
  let htmlPath;
4581
4477
  const outDir = resolveOutputDir(manifestDir, config.title);
4582
4478
  if (inputDir) {
4583
- const relMarkdown = await resolveActiveMarkdownFiles(manifestDir, config.source.files);
4479
+ const relMarkdown = await resolveActiveMarkdownFiles(manifestDir, config.chapters);
4584
4480
  markdownFiles = relMarkdown.map((f) => join2(manifestDir, canonicalChapterId(f)));
4585
4481
  const relStyles = await resolveActiveStyles(manifestDir, config.styles);
4586
4482
  const projectCssFiles = relStyles.map((rel) => resolve4(manifestDir, rel));
@@ -4616,7 +4512,7 @@ async function executeValidation(args) {
4616
4512
  };
4617
4513
  if (args.fix) {
4618
4514
  const selected = selectChecks(runnerOptions, config).checks;
4619
- if (selected.some((check37) => check37.id === MARKDOWNLINT_CHECK_ID)) {
4515
+ if (selected.some((check36) => check36.id === MARKDOWNLINT_CHECK_ID)) {
4620
4516
  await applyMarkdownlintFixes(context);
4621
4517
  } else {
4622
4518
  log.warn(`--fix: ${MARKDOWNLINT_CHECK_ID} is not part of this run — no files were fixed.`);
@@ -4894,16 +4790,16 @@ ${list}
4894
4790
 
4895
4791
  Install the missing tools and re-run, or set GHOSTSCRIPT_PATH, CHROMIUM_PATH, or system PATH so gutterpress can find them. See the User Guide Chapter 7 (System Setup) at examples/gutterpress-user-guide/07-system-setup.md for the full per-feature matrix.`, 2);
4896
4792
  }
4897
- function computeGates(format, opts, config) {
4793
+ function computeGates(format, opts) {
4898
4794
  if (format === "html") {
4899
4795
  if (opts.skipLint || opts.skipPreValidate || opts.skipPostValidate) {
4900
4796
  log.info("Validation/lint flags ignored for --format html (no validation phases apply)");
4901
4797
  }
4902
4798
  return { skipStylelint: false, preValidate: false, postValidate: false };
4903
4799
  }
4904
- const skipStylelint = !!opts.skipLint || config.lint.enabled === false;
4905
- const preValidate = !opts.skipPreValidate && config.validate.enabled !== false;
4906
- const postValidate = format === "pdfx" && !opts.skipPostValidate && config.validate.enabled !== false;
4800
+ const skipStylelint = !!opts.skipLint;
4801
+ const preValidate = !opts.skipPreValidate;
4802
+ const postValidate = format === "pdfx" && !opts.skipPostValidate;
4907
4803
  return { skipStylelint, preValidate, postValidate };
4908
4804
  }
4909
4805
 
@@ -4939,7 +4835,7 @@ async function resolveBuildContext(opts) {
4939
4835
  }, manifest);
4940
4836
  const target = opts.pdfFileOverride ? { kind: "file", file: path7.resolve(opts.pdfFileOverride) } : opts.outDir ? { kind: "directory", dir: opts.outDir } : { kind: "project", dir: resolveOutputDir(manifestDir, config.title) };
4941
4837
  const outDir = target.kind === "file" ? path7.dirname(target.file) : target.dir;
4942
- const gates = computeGates(format, opts, config);
4838
+ const gates = computeGates(format, opts);
4943
4839
  const workDir = target.kind === "project" ? path7.join(path7.dirname(target.dir), `.${path7.basename(target.dir)}-build-${randomBytes(6).toString("hex")}`) : path7.join(os2.tmpdir(), `gutterpress-build-${randomBytes(6).toString("hex")}`);
4944
4840
  return {
4945
4841
  opts,
@@ -4995,8 +4891,8 @@ async function runQualityGates(ctx) {
4995
4891
  }
4996
4892
  async function renderBook(ctx) {
4997
4893
  const { config, gates, renderDir, workDir, opts, format } = ctx;
4998
- if (config.source.files && config.source.files.length > 0) {
4999
- log.info(`Using specified files (${config.source.files.length} total)`);
4894
+ if (config.chapters && config.chapters.length > 0) {
4895
+ log.info(`Using specified files (${config.chapters.length} total)`);
5000
4896
  } else {
5001
4897
  log.info("Using all .md files in alphabetical order");
5002
4898
  }
@@ -5009,7 +4905,7 @@ async function renderBook(ctx) {
5009
4905
  print: config.print,
5010
4906
  printArea: { ...config.page, preset: config.preset, spec: config.spec },
5011
4907
  styles: config.styles,
5012
- files: config.source.files,
4908
+ files: config.chapters,
5013
4909
  plugins,
5014
4910
  pluginStyles,
5015
4911
  onChapterWarnings: (file, warnings) => {
@@ -5160,7 +5056,7 @@ class PdfOutput {
5160
5056
  const rawPdf = pdfxMode ? path7.join(stage, "raw.pdf") : path7.resolve(pdfFile);
5161
5057
  await fsp2.mkdir(path7.dirname(path7.resolve(pdfFile)), { recursive: true });
5162
5058
  log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
5163
- const { buildNativePdf } = await import("./engine-m4y10shc.js");
5059
+ const { buildNativePdf } = await import("./engine-4rabsgwq.js");
5164
5060
  const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
5165
5061
  title: config.title,
5166
5062
  author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
@@ -5197,7 +5093,7 @@ class PdfOutput {
5197
5093
  }
5198
5094
  const flattenPages = config.pdfx.flattenPages;
5199
5095
  if (transparent.length > 0 && config.pdfx.transparency === "preserve-text") {
5200
- const { unsplittableTextReasons } = await import("./pdf-inspect-wnw4za71.js");
5096
+ const { unsplittableTextReasons } = await import("./pdf-inspect-b3mf81ex.js");
5201
5097
  const reasons = await unsplittableTextReasons(rawBytes, transparent).catch((err) => {
5202
5098
  log.warn(`pdfx.transparency: preserve-text could not inspect this PDF's text (${err instanceof Error ? err.message : String(err)}), so every page that uses transparency is flattened whole, as with flatten-page.`);
5203
5099
  return null;
@@ -5499,7 +5395,7 @@ async function generateAndWriteHtml(inputPath, tempDir, config, cssAssets, image
5499
5395
  ...config,
5500
5396
  printArea: config.page && { ...config.page, preset: config.preset, spec: config.spec }
5501
5397
  }, {
5502
- files: config.source?.files ?? null,
5398
+ files: config.chapters ?? null,
5503
5399
  onCssAssets: (copies) => {
5504
5400
  for (const copy of copies)
5505
5401
  nextAssets.set(copy.to, copy.from);
@@ -6457,12 +6353,10 @@ import path12 from "node:path";
6457
6353
  // src/lib/page-size.ts
6458
6354
  import { isMap } from "yaml";
6459
6355
  function writePageBounds(doc, page) {
6460
- const tolerance = page.tolerance ?? numberAt(doc, ["page", "tolerance"]);
6461
6356
  ensurePageMap(doc);
6462
6357
  doc.setIn(["page", "width"], page.width);
6463
6358
  doc.setIn(["page", "height"], page.height);
6464
- if (tolerance !== undefined)
6465
- doc.setIn(["page", "tolerance"], tolerance);
6359
+ doc.deleteIn(["page", "tolerance"]);
6466
6360
  }
6467
6361
  function deletePageBounds(doc) {
6468
6362
  const block = doc.get("page", true);
@@ -6479,20 +6373,16 @@ function ensurePageMap(doc) {
6479
6373
  if (!isMap(doc.get("page", true)))
6480
6374
  doc.set("page", doc.createNode({}));
6481
6375
  }
6482
- function numberAt(doc, keyPath) {
6483
- const v = doc.getIn(keyPath);
6484
- return isPositivePoints(v) ? v : undefined;
6485
- }
6486
6376
 
6487
6377
  // src/lib/project-scaffold.ts
6488
6378
  function starterOverridesCss() {
6489
6379
  return `/**
6490
6380
  * Your book's own styles. Rules here win over your look's.
6491
6381
  *
6492
- * In the app you rarely need this file: Setup > Looks & features adds a
6493
- * look, Setup > Design changes its fonts, colors and sizes (those changes
6494
- * are saved here as :root custom properties), and Setup > Details sets the
6495
- * page size and margins (in the manifest).
6382
+ * In the app you rarely need this file: Setup > Look chooses a look and
6383
+ * changes its fonts and colors (those changes are saved here as :root
6384
+ * custom properties), Setup > Advanced lists every setting, and Setup > Book
6385
+ * sets the page size and margins (in the manifest).
6496
6386
  *
6497
6387
  * To change the look from the command line: gutterpress ext remove <old>
6498
6388
  * <book>, then gutterpress ext add <look> <book>.
@@ -6531,9 +6421,6 @@ function requirePreset(preset, customPage) {
6531
6421
  } else if (customPage && (!isPositivePoints(customPage.width) || !isPositivePoints(customPage.height))) {
6532
6422
  throw new CreateProjectErrorImpl("custom-page-required", "Page overrides need a positive width and height in points (72pt = 1in).");
6533
6423
  }
6534
- if (customPage?.tolerance !== undefined && !isPositivePoints(customPage.tolerance)) {
6535
- throw new CreateProjectErrorImpl("custom-page-required", "Page tolerance must be a positive number of points.");
6536
- }
6537
6424
  return preset;
6538
6425
  }
6539
6426
  function resolveScaffoldTargets(requested, preset) {
@@ -6670,7 +6557,7 @@ async function firstSourceFile(manifestPath) {
6670
6557
  } catch {
6671
6558
  return;
6672
6559
  }
6673
- const filesIdx = text.search(/^\s*files:\s*$/m);
6560
+ const filesIdx = text.search(/^(?:chapters|\s+files):\s*$/m);
6674
6561
  if (filesIdx === -1)
6675
6562
  return;
6676
6563
  const rest = text.slice(filesIdx);
@@ -8935,7 +8822,7 @@ function publishProviderFor(id) {
8935
8822
  }
8936
8823
 
8937
8824
  // src/lib/publish/plugin-provider.ts
8938
- var RESERVED_SETTINGS = new Set(["format", "credential"]);
8825
+ var RESERVED_SETTINGS = new Set(["format", "credential", "enabled"]);
8939
8826
  var isBuiltIn = (id) => listPublishProviders().some((p) => p.id === id);
8940
8827
  var messageOf = (e) => e instanceof Error ? e.message : String(e);
8941
8828
  async function bookExtensions(book) {
@@ -8991,7 +8878,7 @@ async function resolvePublishProvider(id, book) {
8991
8878
  const ext = await bookExtensions(book);
8992
8879
  const npmEntry = ext.extensions.some((c) => !c.path && c.name === id);
8993
8880
  if (npmEntry) {
8994
- const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-tmxtzkm0.js");
8881
+ const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-x3mtn844.js");
8995
8882
  await restoreForCommand2(book.projectDir, { manifestPath: book.manifestPath, failFast: true });
8996
8883
  }
8997
8884
  const publishers = await discover(ext);
@@ -9029,7 +8916,7 @@ function infoFor(p) {
9029
8916
  }
9030
8917
  function pluginProvider(p) {
9031
8918
  let loading;
9032
- const load = () => loading ??= import("./plugins-4vaf27n9.js").then((m) => m.loadPublishFunction(p));
8919
+ const load = () => loading ??= import("./plugins-cfzf26b8.js").then((m) => m.loadPublishFunction(p));
9033
8920
  return {
9034
8921
  info: infoFor(p),
9035
8922
  async authenticate() {
@@ -9098,7 +8985,10 @@ async function requestFor(provider, options, deps) {
9098
8985
  const { manifest, manifestDir } = await loadManifestWithPath(options.manifestPath ?? options.projectDir, { explicit: options.manifestPath !== undefined });
9099
8986
  const config = resolveConfig({}, manifest);
9100
8987
  const publishSettings = manifest.publish ?? {};
9101
- const providerConfig = publishSettings[provider.info.id] ?? {};
8988
+ const providerConfig = {
8989
+ ...publishSettings[provider.info.id] ?? {},
8990
+ ...(await deps.selections?.settings(options.projectDir))?.[provider.info.id] ?? {}
8991
+ };
9102
8992
  const bookAccount = typeof providerConfig.credential === "string" ? providerConfig.credential.trim() : "";
9103
8993
  const effectiveAccount = bookAccount || deps.credentialAccount;
9104
8994
  const effectiveDeps = effectiveAccount ? { ...deps, credentialAccount: effectiveAccount } : deps;
@@ -9275,11 +9165,20 @@ async function connectPublishProvider(options, deps) {
9275
9165
  label: account || info10.label,
9276
9166
  createdAt: Date.now()
9277
9167
  };
9278
- const req = await resolvePublishRequest({
9168
+ const shop = (options.shop ?? "").trim();
9169
+ if (!options.projectDir && info10.id === "shopify" && !shop) {
9170
+ throw new Error("Enter your Shopify store's address (like my-store.myshopify.com) to check the key.");
9171
+ }
9172
+ const req = options.projectDir ? await resolvePublishRequest({
9279
9173
  projectDir: options.projectDir,
9280
9174
  providerId: info10.id,
9281
9175
  ...options.manifestPath ? { manifestPath: options.manifestPath } : {}
9282
- }, deps);
9176
+ }, deps) : {
9177
+ project: { projectDir: "", title: "", authors: [] },
9178
+ config: shop ? { shop } : {},
9179
+ artifact: { path: "", format: info10.format },
9180
+ deps
9181
+ };
9283
9182
  const trialDeps = {
9284
9183
  ...deps,
9285
9184
  env: {},
@@ -9467,7 +9366,7 @@ class PublishSelectionsStore {
9467
9366
  resolve(providerId, projectDir) {
9468
9367
  return this.enqueue(async () => {
9469
9368
  const data = await this.read();
9470
- const proj = projectDir ? data.projects[normalizeProjectKey(projectDir)]?.[providerId] : undefined;
9369
+ const proj = projectDir ? data.projects[normalizeProjectKey(projectDir)]?.[providerId]?.credential : undefined;
9471
9370
  return proj && proj.trim() || data.global[providerId]?.trim() || undefined;
9472
9371
  });
9473
9372
  }
@@ -9475,7 +9374,7 @@ class PublishSelectionsStore {
9475
9374
  return this.enqueue(async () => {
9476
9375
  const data = await this.read();
9477
9376
  const global = data.global[providerId];
9478
- const project = projectDir ? data.projects[normalizeProjectKey(projectDir)]?.[providerId] : undefined;
9377
+ const project = projectDir ? data.projects[normalizeProjectKey(projectDir)]?.[providerId]?.credential : undefined;
9479
9378
  return {
9480
9379
  ...project ? { project } : {},
9481
9380
  ...global ? { global } : {}
@@ -9494,17 +9393,35 @@ class PublishSelectionsStore {
9494
9393
  });
9495
9394
  }
9496
9395
  setProject(projectDir, providerId, account) {
9396
+ return this.setSettings(projectDir, providerId, { credential: account });
9397
+ }
9398
+ settings(projectDir) {
9399
+ return this.enqueue(async () => {
9400
+ const data = await this.read();
9401
+ return data.projects[normalizeProjectKey(projectDir)] ?? {};
9402
+ });
9403
+ }
9404
+ setSettings(projectDir, providerId, values) {
9497
9405
  return this.enqueue(async () => {
9498
9406
  const data = await this.read();
9499
9407
  const key = normalizeProjectKey(projectDir);
9500
- const a = (account ?? "").trim();
9501
- const bucket = data.projects[key] ?? {};
9502
- if (a)
9503
- bucket[providerId] = a;
9408
+ const book = data.projects[key] ?? {};
9409
+ const mine = { ...book[providerId] };
9410
+ for (const [k, v] of Object.entries(values)) {
9411
+ const text = (v ?? "").trim();
9412
+ if (text)
9413
+ mine[k] = text;
9414
+ else
9415
+ delete mine[k];
9416
+ }
9417
+ if (JSON.stringify(mine) === JSON.stringify(book[providerId] ?? {}))
9418
+ return;
9419
+ if (Object.keys(mine).length > 0)
9420
+ book[providerId] = mine;
9504
9421
  else
9505
- delete bucket[providerId];
9506
- if (Object.keys(bucket).length > 0)
9507
- data.projects[key] = bucket;
9422
+ delete book[providerId];
9423
+ if (Object.keys(book).length > 0)
9424
+ data.projects[key] = book;
9508
9425
  else
9509
9426
  delete data.projects[key];
9510
9427
  await this.write(data);