gutterpress 0.11.23-beta.2 → 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 (58) hide show
  1. package/README.md +12 -2
  2. package/dist/api/index.d.ts +5 -5
  3. package/dist/api/index.js +19 -7
  4. package/dist/{build-3e18wnqj.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-88arpdke.js → cli-5zbdb6mt.js} +296 -65
  9. package/dist/{cli-tgnyvra3.js → cli-7mt0dftw.js} +35 -16
  10. package/dist/{cli-pnrararp.js → cli-ah93yyzb.js} +162 -55
  11. package/dist/{cli-v0evdpdf.js → cli-eymdsefg.js} +1 -1
  12. package/dist/{cli-9n9kg58f.js → cli-fh685nqs.js} +1 -1
  13. package/dist/{cli-pd2cje5b.js → cli-fsjre61x.js} +1 -1
  14. package/dist/{cli-x7gcdg6w.js → cli-q7t04gjt.js} +1 -1
  15. package/dist/{cli-0ep11b0q.js → cli-rybz2dfs.js} +1 -1
  16. package/dist/cli.js +12 -12
  17. package/dist/{doctor-2f4s9dyn.js → doctor-tg9ht1n3.js} +3 -3
  18. package/dist/{engine-c4pxz79g.js → engine-17v87vq5.js} +1 -1
  19. package/dist/{engine-cs5g2ez0.js → engine-y9fnarfa.js} +2 -2
  20. package/dist/{ext-70gv86v5.js → ext-esz03jz4.js} +27 -10
  21. package/dist/{extension-restore-chj5nx3t.js → extension-restore-91gy1e28.js} +3 -3
  22. package/dist/{extension-restore-pd87p8r2.js → extension-restore-q70wqah5.js} +5 -5
  23. package/dist/{index-80vg3ed6.js → index-67g8f7r4.js} +35 -16
  24. package/dist/{index-swfdgn2n.js → index-d9w3r89w.js} +1 -1
  25. package/dist/{index-ytjkvwy5.js → index-fntpr44x.js} +321 -66
  26. package/dist/{index-5x42amh8.js → index-g3te5ey1.js} +2 -1
  27. package/dist/{index-7j3hkwya.js → index-kw4tbthz.js} +1 -1
  28. package/dist/{index-2t1gdma7.js → index-santcs4q.js} +1 -1
  29. package/dist/{index-0k43evt0.js → index-z6vzj3s5.js} +186 -60
  30. package/dist/index.js +35 -8
  31. package/dist/lib/check-options.d.ts +70 -0
  32. package/dist/lib/extension-manager.d.ts +16 -1
  33. package/dist/lib/extension-scaffold.d.ts +15 -2
  34. package/dist/lib/extension-specifier.d.ts +8 -1
  35. package/dist/lib/manifest-config.d.ts +3 -1
  36. package/dist/lib/manifest-old-spellings.d.ts +32 -9
  37. package/dist/lib/markdown/math.d.ts +1 -1
  38. package/dist/lib/markdown/typography.d.ts +1 -0
  39. package/dist/lib/page-size.d.ts +12 -4
  40. package/dist/lib/plugin-vendor.d.ts +6 -0
  41. package/dist/lib/presets.d.ts +2 -2
  42. package/dist/lib/root-tokens.d.ts +2 -1
  43. package/dist/lib/style-resolver.d.ts +2 -1
  44. package/dist/lib/version-changes.d.ts +9 -3
  45. package/dist/{manifest.schema-0jgj0jt1.json → manifest.schema-5cm13vr3.json} +215 -5
  46. package/dist/{new-d61n5cn0.js → new-rmfyb7va.js} +22 -15
  47. package/dist/{plugins-0hhw6s17.js → plugins-gs21xz5s.js} +2 -2
  48. package/dist/{plugins-e0n46s6m.js → plugins-tqv1s16f.js} +4 -4
  49. package/dist/{preflight-fjayhjr5.js → preflight-bjyeeq0d.js} +9 -9
  50. package/dist/{preview-h815jrfb.js → preview-ke03fk5d.js} +9 -9
  51. package/dist/{publish-ft39zgma.js → publish-wpnz0qng.js} +9 -9
  52. package/dist/render.js +43 -11
  53. package/dist/schema/manifest.types.d.ts +45 -7
  54. package/dist/{source-provider-j1w7byeq.js → source-provider-3g3yrn1f.js} +2 -2
  55. package/dist/{source-provider-tjaf303m.js → source-provider-azg9ywhb.js} +2 -2
  56. package/dist/{validate-b201dbrb.js → validate-zcwykb43.js} +9 -9
  57. package/package.json +1 -1
  58. /package/dist/{cli-y28j019d.js → cli-1dha1nxk.js} +0 -0
@@ -44,7 +44,7 @@
44
44
  },
45
45
  "styles": {
46
46
  "type": "array",
47
- "description": "Project-relative CSS files to <link> into the rendered book, applied in order. If omitted, Gutterpress discovers one: styles/book.css (what `gutterpress new` scaffolds), else the first .css file found in the project root, styles/ or css/, else none. New projects should set this explicitly or use styles/book.css.",
47
+ "description": "Project-relative CSS files to <link> into the rendered book, applied in order. If omitted, Gutterpress discovers one: styles/book.css (what `gutterpress new` scaffolds), else the older conventional names css/print.css, css/index.css, css/style.css, css/main.css (in that order), else the first .css file found in the project root, styles/ or css/, else none. New projects should set this explicitly or use styles/book.css.",
48
48
  "items": {
49
49
  "type": "string",
50
50
  "minLength": 1,
@@ -124,11 +124,215 @@
124
124
  },
125
125
  "checks": {
126
126
  "type": "object",
127
- "description": "Per-check and per-rule levels, keyed by a check id (pdf.print.image-resolution, source.markdownlint, …) or a lint rule id (printsafe/no-risky-print-effects). `off` switches it off; `on` switches on a check the preset leaves off, at its own severity; `info`, `warn` and `error` set the severity its findings are reported at. The numbers the checks measure against come from the preset and the publish targets. Linter config files (.markdownlint.yaml, .htmlhintrc, .gutterpress/css-contract.yaml) are found by name in the book's folder or a folder above it, up to the repository.",
127
+ "description": "Per-check and per-rule levels, keyed by a check id (pdf.print.image-resolution, source.markdownlint, …) or a lint rule id (printsafe/no-risky-print-effects). `off` switches it off; `on` switches on a check the preset leaves off, at its own severity; `info`, `warn` and `error` set the severity its findings are reported at. A check that measures against a number or a list takes it as an option in the same entry, written as an object: `pdf.print.ink-coverage: { maxTac: 300 }`, or `{ level: error, maxTac: 300 }` to set its level too. The preset and the publish targets set every option a book leaves out. Linter config files (.markdownlint.yaml, .htmlhintrc, .gutterpress/css-contract.yaml) are found by name in the book's folder or a folder above it, up to the repository.",
128
+ "properties": {
129
+ "pdf.print.ink-coverage": {
130
+ "description": "Total ink coverage of each page of a PDF/X build.",
131
+ "oneOf": [
132
+ {"$ref": "#/definitions/checkLevel"},
133
+ {
134
+ "type": "object",
135
+ "description": "Its `level` (optional) and its options.",
136
+ "additionalProperties": false,
137
+ "properties": {
138
+ "level": {"$ref": "#/definitions/checkLevel"},
139
+ "maxTac": {
140
+ "type": "number",
141
+ "minimum": 0,
142
+ "description": "The total ink limit in percent: what the check measures against and what the PDF/X conversion holds the ink to. Preset defaults: dtrpg 240, book 400.",
143
+ "examples": [240, 300]
144
+ },
145
+ "tacTolerance": {
146
+ "type": "number",
147
+ "minimum": 0,
148
+ "description": "How far over `maxTac` a page may measure before it is reported (percent). Default 0.5.",
149
+ "examples": [0.5]
150
+ }
151
+ }
152
+ }
153
+ ]
154
+ },
155
+ "pdf.print.page-size": {
156
+ "description": "The built PDF's page size against the manifest's (page.width x page.height).",
157
+ "oneOf": [
158
+ {"$ref": "#/definitions/checkLevel"},
159
+ {
160
+ "type": "object",
161
+ "description": "Its `level` (optional) and its options.",
162
+ "additionalProperties": false,
163
+ "properties": {
164
+ "level": {"$ref": "#/definitions/checkLevel"},
165
+ "tolerance": {
166
+ "type": "number",
167
+ "minimum": 0,
168
+ "description": "How far (points) the built page may differ from the size. Default 0.5.",
169
+ "examples": [0.5, 1]
170
+ }
171
+ }
172
+ }
173
+ ]
174
+ },
175
+ "pdf.print.image-resolution": {
176
+ "description": "The resolution each placed image prints at.",
177
+ "oneOf": [
178
+ {"$ref": "#/definitions/checkLevel"},
179
+ {
180
+ "type": "object",
181
+ "description": "Its `level` (optional) and its options.",
182
+ "additionalProperties": false,
183
+ "properties": {
184
+ "level": {"$ref": "#/definitions/checkLevel"},
185
+ "minImageResolution": {
186
+ "type": "number",
187
+ "minimum": 0,
188
+ "description": "The lowest DPI an image may print at; 0 = no floor. Default 300 (itch.io: 0).",
189
+ "examples": [300, 150]
190
+ }
191
+ }
192
+ }
193
+ ]
194
+ },
195
+ "pdf.print.bleed": {
196
+ "description": "The bleed around the trim of a built PDF (off in every preset).",
197
+ "oneOf": [
198
+ {"$ref": "#/definitions/checkLevel"},
199
+ {
200
+ "type": "object",
201
+ "description": "Its `level` (optional) and its options.",
202
+ "additionalProperties": false,
203
+ "properties": {
204
+ "level": {"$ref": "#/definitions/checkLevel"},
205
+ "bleedSize": {
206
+ "type": "number",
207
+ "minimum": 0,
208
+ "description": "The bleed (points) each side must have. Default 9 (0.125in).",
209
+ "examples": [9]
210
+ }
211
+ }
212
+ }
213
+ ]
214
+ },
215
+ "asset.image.file-size": {
216
+ "description": "The size of each image file the book ships.",
217
+ "oneOf": [
218
+ {"$ref": "#/definitions/checkLevel"},
219
+ {
220
+ "type": "object",
221
+ "description": "Its `level` (optional) and its options.",
222
+ "additionalProperties": false,
223
+ "properties": {
224
+ "level": {"$ref": "#/definitions/checkLevel"},
225
+ "maxImageSize": {
226
+ "type": "number",
227
+ "minimum": 0,
228
+ "description": "The largest image file in bytes; 0 = no limit. Default 10000000 (itch.io: 0).",
229
+ "examples": [10000000]
230
+ }
231
+ }
232
+ }
233
+ ]
234
+ },
235
+ "asset.font.approved-files": {
236
+ "description": "The font files the book ships, against an approved list.",
237
+ "oneOf": [
238
+ {"$ref": "#/definitions/checkLevel"},
239
+ {
240
+ "type": "object",
241
+ "description": "Its `level` (optional) and its options.",
242
+ "additionalProperties": false,
243
+ "properties": {
244
+ "level": {"$ref": "#/definitions/checkLevel"},
245
+ "approvedFontFiles": {
246
+ "type": "array",
247
+ "description": "Glob patterns, relative to the book, of the font files it may ship. A font file no pattern matches is reported. Empty (the default) approves every font.",
248
+ "items": {"type": "string"},
249
+ "examples": [["fonts/*.woff2"]]
250
+ }
251
+ }
252
+ }
253
+ ]
254
+ },
255
+ "heuristic.decoration.layer-count": {
256
+ "description": "Decorative layers on each page.",
257
+ "oneOf": [
258
+ {"$ref": "#/definitions/checkLevel"},
259
+ {
260
+ "type": "object",
261
+ "description": "Its `level` (optional) and its options.",
262
+ "additionalProperties": false,
263
+ "properties": {
264
+ "level": {"$ref": "#/definitions/checkLevel"},
265
+ "maxDecorativeLayers": {
266
+ "type": "number",
267
+ "minimum": 0,
268
+ "description": "The most decorative layers on one page. Default 5.",
269
+ "examples": [5]
270
+ }
271
+ }
272
+ }
273
+ ]
274
+ },
275
+ "heuristic.whitespace.text-density": {
276
+ "description": "The characters each page carries.",
277
+ "oneOf": [
278
+ {"$ref": "#/definitions/checkLevel"},
279
+ {
280
+ "type": "object",
281
+ "description": "Its `level` (optional) and its options.",
282
+ "additionalProperties": false,
283
+ "properties": {
284
+ "level": {"$ref": "#/definitions/checkLevel"},
285
+ "textDensityRange": {
286
+ "type": "object",
287
+ "description": "The characters a page should carry: `min` and `max`, either or both. Default { min: 200, max: 5000 }.",
288
+ "additionalProperties": false,
289
+ "properties": {"min": {"type": "number", "minimum": 0}, "max": {"type": "number", "minimum": 0}}
290
+ }
291
+ }
292
+ }
293
+ ]
294
+ },
295
+ "heuristic.chunking.section-density": {
296
+ "description": "Paragraphs in each section.",
297
+ "oneOf": [
298
+ {"$ref": "#/definitions/checkLevel"},
299
+ {
300
+ "type": "object",
301
+ "description": "Its `level` (optional) and its options.",
302
+ "additionalProperties": false,
303
+ "properties": {
304
+ "level": {"$ref": "#/definitions/checkLevel"},
305
+ "maxParagraphsPerSection": {
306
+ "type": "number",
307
+ "minimum": 0,
308
+ "description": "The most paragraphs in one section. Default 10.",
309
+ "examples": [10]
310
+ }
311
+ }
312
+ }
313
+ ]
314
+ }
315
+ },
128
316
  "additionalProperties": {
129
- "enum": ["off", "on", "info", "warn", "warning", "error", true, false]
317
+ "oneOf": [
318
+ {"$ref": "#/definitions/checkLevel"},
319
+ {
320
+ "type": "object",
321
+ "description": "A check's level as an object; a check with no options takes only `level`.",
322
+ "additionalProperties": false,
323
+ "properties": {"level": {"$ref": "#/definitions/checkLevel"}}
324
+ }
325
+ ]
130
326
  },
131
- "examples": [{ "pdf.structure.qpdf": "off", "heuristic.whitespace.text-density": "info", "pdf.nav.bookmarks": "warn" }]
327
+ "examples": [
328
+ {
329
+ "pdf.structure.qpdf": "off",
330
+ "heuristic.whitespace.text-density": "info",
331
+ "pdf.nav.bookmarks": "warn",
332
+ "pdf.print.ink-coverage": {"maxTac": 300},
333
+ "pdf.print.image-resolution": {"level": "error", "minImageResolution": 200}
334
+ }
335
+ ]
132
336
  },
133
337
  "pdfx": {
134
338
  "type": "object",
@@ -202,7 +406,7 @@
202
406
  },
203
407
  "page": {
204
408
  "type": "object",
205
- "description": "Page geometry, in POINTS (1in = 72pt): the trim size the book prints at and, with `margin`, the margins. The build writes them as the `@page` rule after every stylesheet, so a `size` in a stylesheet's own `@page` is overridden (the print-safety check reports it); the `pdf.print.page-size` check compares the produced PDF against these numbers. A bleed-inclusive page size legitimately differs from the trim recorded here.",
409
+ "description": "Page geometry, in POINTS (1in = 72pt): the trim size the book prints at and, with `margin`, the margins. The build writes them as the `@page` rule after every stylesheet, so a `size` in a stylesheet's own `@page` is overridden (the print-safety check reports it); the `pdf.print.page-size` check compares the produced PDF against these numbers, allowing the `tolerance` set in its `checks:` entry (0.5pt by default). A bleed-inclusive page size legitimately differs from the trim recorded here.",
206
410
  "properties": {
207
411
  "width": {
208
412
  "type": "number",
@@ -376,6 +580,12 @@
376
580
  }
377
581
  }
378
582
  },
583
+ "definitions": {
584
+ "checkLevel": {
585
+ "description": "off, on (at the check's own severity), info, warn or error; `warning` is read as `warn`, true as on and false as off.",
586
+ "enum": ["off", "on", "info", "warn", "warning", "error", true, false]
587
+ }
588
+ },
379
589
  "examples": [
380
590
  {
381
591
  "title": "My Book",
@@ -1,20 +1,21 @@
1
1
  import {
2
2
  BUILT_IN_TEMPLATE_IDS,
3
3
  EXTENSION_KINDS,
4
+ extensionKindFor,
4
5
  scaffoldExtension,
5
6
  scaffoldProject
6
- } from "./cli-pnrararp.js";
7
+ } from "./cli-ah93yyzb.js";
7
8
  import {
8
9
  resolveGhostscript
9
- } from "./cli-0ep11b0q.js";
10
+ } from "./cli-rybz2dfs.js";
10
11
  import"./cli-ht1bcqdd.js";
11
- import"./cli-pd2cje5b.js";
12
+ import"./cli-fsjre61x.js";
12
13
  import"./cli-5crpmz42.js";
13
14
  import"./cli-eyyggect.js";
14
15
  import {
15
16
  isToolAvailable
16
17
  } from "./cli-asap4t1z.js";
17
- import"./cli-v0evdpdf.js";
18
+ import"./cli-eymdsefg.js";
18
19
  import"./cli-v5mp7a6q.js";
19
20
  import {
20
21
  PRESET_IDS,
@@ -22,20 +23,20 @@ import {
22
23
  TARGET_IDS,
23
24
  loadManifest,
24
25
  resolveConfig
25
- } from "./cli-88arpdke.js";
26
- import"./cli-tgnyvra3.js";
27
- import"./cli-9n9kg58f.js";
26
+ } from "./cli-5zbdb6mt.js";
27
+ import"./cli-7mt0dftw.js";
28
+ import"./cli-fh685nqs.js";
28
29
  import {
29
30
  UsageError,
30
31
  rejectExtraPositionals,
31
32
  rejectUnknownFlags
32
33
  } from "./cli-d8xjns66.js";
33
- import"./cli-x7gcdg6w.js";
34
+ import"./cli-q7t04gjt.js";
34
35
  import"./cli-65gy8ask.js";
35
36
  import {
36
37
  EXIT_CODES
37
38
  } from "./cli-46ycxe6r.js";
38
- import"./cli-y28j019d.js";
39
+ import"./cli-1dha1nxk.js";
39
40
  import"./cli-37x76zdn.js";
40
41
 
41
42
  // src/commands/new.ts
@@ -49,7 +50,7 @@ var newArgs = {
49
50
  },
50
51
  kind: {
51
52
  type: "string",
52
- description: `What to create: book (default), ${EXTENSION_KINDS.join(", ")}`
53
+ description: `What to create: book (default), ${EXTENSION_KINDS.join(", ")} (theme is look's older name)`
53
54
  },
54
55
  prefix: {
55
56
  type: "string",
@@ -91,6 +92,10 @@ var newArgs = {
91
92
  type: "string",
92
93
  description: "Trim height in points, 72pt = 1in (required with --preset custom; optional override otherwise)"
93
94
  },
95
+ "page-tolerance": {
96
+ type: "string",
97
+ description: "Allowed trim deviation in points when validating a built PDF (default: 0.5); with --page-width/--page-height, written as checks: { pdf.print.page-size: { tolerance } }"
98
+ },
94
99
  git: {
95
100
  type: "boolean",
96
101
  description: "Keep version history on this computer (default: true; use --no-git to skip)",
@@ -119,6 +124,7 @@ var BOOK_ONLY_FLAGS = [
119
124
  "template",
120
125
  "page-width",
121
126
  "page-height",
127
+ "page-tolerance",
122
128
  "git"
123
129
  ];
124
130
  var EXTENSION_ONLY_FLAGS = ["prefix", "description"];
@@ -204,12 +210,12 @@ var new_default = defineCommand({
204
210
  }
205
211
  const name = String(args.name);
206
212
  const parentDir = resolve(typeof args.dir === "string" && args.dir ? args.dir : process.cwd());
207
- const rawKind = typeof args.kind === "string" && args.kind ? args.kind : "book";
208
- if (rawKind !== "book" && !EXTENSION_KINDS.includes(rawKind)) {
209
- console.error(`Unknown kind "${rawKind}". Choose one of: book, ${EXTENSION_KINDS.join(", ")}.`);
213
+ const givenKind = typeof args.kind === "string" && args.kind ? args.kind : "book";
214
+ const kind = givenKind === "book" ? "book" : extensionKindFor(givenKind);
215
+ if (!kind) {
216
+ console.error(`Unknown kind "${givenKind}". Choose one of: book, ${EXTENSION_KINDS.join(", ")}.`);
210
217
  process.exit(EXIT_CODES.USAGE);
211
218
  }
212
- const kind = rawKind;
213
219
  rejectFlagsForKind(rawArgs, kind);
214
220
  if (kind !== "book") {
215
221
  await runExtensionScaffold(kind, name, parentDir, args);
@@ -239,7 +245,8 @@ var new_default = defineCommand({
239
245
  }
240
246
  const pageWidth = parsePoints(args["page-width"], "--page-width");
241
247
  const pageHeight = parsePoints(args["page-height"], "--page-height");
242
- const customPage = pageWidth !== undefined && pageHeight !== undefined ? { width: pageWidth, height: pageHeight } : undefined;
248
+ const pageTolerance = parsePoints(args["page-tolerance"], "--page-tolerance");
249
+ const customPage = pageWidth !== undefined && pageHeight !== undefined ? { width: pageWidth, height: pageHeight, ...pageTolerance !== undefined ? { tolerance: pageTolerance } : {} } : undefined;
243
250
  if (preset === "custom" && !customPage) {
244
251
  console.error("The custom preset needs a trim size: --page-width and --page-height in points (72pt = 1in — e.g. US Letter is 612 x 792).");
245
252
  process.exit(EXIT_CODES.USAGE);
@@ -8,8 +8,8 @@ import {
8
8
  loadPlugins,
9
9
  loadPluginsWithCss,
10
10
  loadPublishFunction
11
- } from "./index-80vg3ed6.js";
12
- import"./index-5x42amh8.js";
11
+ } from "./index-67g8f7r4.js";
12
+ import"./index-g3te5ey1.js";
13
13
  import"./index-37x76zdn.js";
14
14
  export {
15
15
  loadPublishFunction,
@@ -8,10 +8,10 @@ import {
8
8
  loadPlugins,
9
9
  loadPluginsWithCss,
10
10
  loadPublishFunction
11
- } from "./cli-tgnyvra3.js";
12
- import"./cli-9n9kg58f.js";
13
- import"./cli-x7gcdg6w.js";
14
- import"./cli-y28j019d.js";
11
+ } from "./cli-7mt0dftw.js";
12
+ import"./cli-fh685nqs.js";
13
+ import"./cli-q7t04gjt.js";
14
+ import"./cli-1dha1nxk.js";
15
15
  import"./cli-37x76zdn.js";
16
16
  export {
17
17
  loadPublishFunction,
@@ -1,34 +1,34 @@
1
1
  import {
2
2
  executeValidation,
3
3
  reportMissingTools
4
- } from "./cli-pnrararp.js";
5
- import"./cli-0ep11b0q.js";
4
+ } from "./cli-ah93yyzb.js";
5
+ import"./cli-rybz2dfs.js";
6
6
  import"./cli-ht1bcqdd.js";
7
- import"./cli-pd2cje5b.js";
7
+ import"./cli-fsjre61x.js";
8
8
  import"./cli-5crpmz42.js";
9
9
  import"./cli-eyyggect.js";
10
10
  import"./cli-asap4t1z.js";
11
- import"./cli-v0evdpdf.js";
11
+ import"./cli-eymdsefg.js";
12
12
  import"./cli-v5mp7a6q.js";
13
13
  import {
14
14
  publishTargetFor
15
- } from "./cli-88arpdke.js";
16
- import"./cli-tgnyvra3.js";
15
+ } from "./cli-5zbdb6mt.js";
16
+ import"./cli-7mt0dftw.js";
17
17
  import {
18
18
  log
19
- } from "./cli-9n9kg58f.js";
19
+ } from "./cli-fh685nqs.js";
20
20
  import {
21
21
  UsageError,
22
22
  rejectExtraPositionals,
23
23
  rejectUnknownFlags
24
24
  } from "./cli-d8xjns66.js";
25
- import"./cli-x7gcdg6w.js";
25
+ import"./cli-q7t04gjt.js";
26
26
  import"./cli-65gy8ask.js";
27
27
  import {
28
28
  BuildError,
29
29
  EXIT_CODES
30
30
  } from "./cli-46ycxe6r.js";
31
- import"./cli-y28j019d.js";
31
+ import"./cli-1dha1nxk.js";
32
32
  import"./cli-37x76zdn.js";
33
33
 
34
34
  // src/commands/preflight.ts
@@ -3,23 +3,23 @@ import {
3
3
  runBuild,
4
4
  splitOutPath,
5
5
  startPreviewServer
6
- } from "./cli-pnrararp.js";
7
- import"./cli-0ep11b0q.js";
6
+ } from "./cli-ah93yyzb.js";
7
+ import"./cli-rybz2dfs.js";
8
8
  import {
9
9
  previewArgs
10
10
  } from "./cli-75qkn0k5.js";
11
11
  import"./cli-ht1bcqdd.js";
12
- import"./cli-pd2cje5b.js";
12
+ import"./cli-fsjre61x.js";
13
13
  import"./cli-5crpmz42.js";
14
14
  import"./cli-eyyggect.js";
15
15
  import"./cli-asap4t1z.js";
16
- import"./cli-v0evdpdf.js";
16
+ import"./cli-eymdsefg.js";
17
17
  import"./cli-v5mp7a6q.js";
18
- import"./cli-88arpdke.js";
19
- import"./cli-tgnyvra3.js";
18
+ import"./cli-5zbdb6mt.js";
19
+ import"./cli-7mt0dftw.js";
20
20
  import {
21
21
  log
22
- } from "./cli-9n9kg58f.js";
22
+ } from "./cli-fh685nqs.js";
23
23
  import {
24
24
  UsageError,
25
25
  parseFormat,
@@ -28,12 +28,12 @@ import {
28
28
  rejectUnknownFlags,
29
29
  resolvePort
30
30
  } from "./cli-d8xjns66.js";
31
- import"./cli-x7gcdg6w.js";
31
+ import"./cli-q7t04gjt.js";
32
32
  import"./cli-65gy8ask.js";
33
33
  import {
34
34
  BuildError
35
35
  } from "./cli-46ycxe6r.js";
36
- import"./cli-y28j019d.js";
36
+ import"./cli-1dha1nxk.js";
37
37
  import"./cli-37x76zdn.js";
38
38
 
39
39
  // src/commands/preview.ts
@@ -10,36 +10,36 @@ import {
10
10
  resolvePublishFormat,
11
11
  resolvePublishProvider,
12
12
  runPublish
13
- } from "./cli-pnrararp.js";
13
+ } from "./cli-ah93yyzb.js";
14
14
  import {
15
15
  FileTokenStore
16
- } from "./cli-0ep11b0q.js";
16
+ } from "./cli-rybz2dfs.js";
17
17
  import"./cli-ht1bcqdd.js";
18
- import"./cli-pd2cje5b.js";
18
+ import"./cli-fsjre61x.js";
19
19
  import"./cli-5crpmz42.js";
20
20
  import"./cli-eyyggect.js";
21
21
  import"./cli-asap4t1z.js";
22
- import"./cli-v0evdpdf.js";
22
+ import"./cli-eymdsefg.js";
23
23
  import"./cli-v5mp7a6q.js";
24
24
  import {
25
25
  loadManifestWithPath
26
- } from "./cli-88arpdke.js";
27
- import"./cli-tgnyvra3.js";
26
+ } from "./cli-5zbdb6mt.js";
27
+ import"./cli-7mt0dftw.js";
28
28
  import {
29
29
  log
30
- } from "./cli-9n9kg58f.js";
30
+ } from "./cli-fh685nqs.js";
31
31
  import {
32
32
  UsageError,
33
33
  rejectExtraPositionals,
34
34
  rejectUnknownFlags
35
35
  } from "./cli-d8xjns66.js";
36
- import"./cli-x7gcdg6w.js";
36
+ import"./cli-q7t04gjt.js";
37
37
  import"./cli-65gy8ask.js";
38
38
  import {
39
39
  BuildError,
40
40
  EXIT_CODES
41
41
  } from "./cli-46ycxe6r.js";
42
- import"./cli-y28j019d.js";
42
+ import"./cli-1dha1nxk.js";
43
43
  import"./cli-37x76zdn.js";
44
44
 
45
45
  // src/commands/publish.ts
package/dist/render.js CHANGED
@@ -2189,22 +2189,39 @@ function gpTable(md, options) {
2189
2189
  }
2190
2190
 
2191
2191
  // src/lib/markdown/typography.ts
2192
+ var SCOPED = /\((c|tm|r)\)/gi;
2193
+ var SYMBOLS = { c: "©", r: "®", tm: "™" };
2194
+ var LABEL_BEFORE = { c: "(b)", C: "(B)", r: "(q)", R: "(Q)" };
2195
+ var LABELS = /\((b|q)\)/gi;
2196
+ var RARE = /\+-|\.\.|\?\?\?\?|!!!!|,,|--/;
2192
2197
  var EM_DASH = /(^|[^-])---(?=[^-]|$)/gm;
2193
2198
  var EN_DASH_SPACED = /(^|\s)--(?=\s|$)/gm;
2194
2199
  var EN_DASH = /(^|[^-\s])--(?=[^-\s]|$)/gm;
2195
- var ELLIPSIS = /\.\.\./g;
2196
- var CANDIDATE = /--|\.\.\./;
2197
- function replaceInText(children) {
2200
+ var CANDIDATE = /\((?:c|tm|r|b|q)\)|\+-|\.\.|\?\?\?\?|!!!!|,,|--/i;
2201
+ function replaceRare(text) {
2202
+ return text.replace(/\+-/g, "±").replace(/\.{2,}/g, "…").replace(/([?!])…/g, "$1..").replace(/([?!]){4,}/g, "$1$1$1").replace(/,{2,}/g, ",").replace(EM_DASH, "$1—").replace(EN_DASH_SPACED, "$1–").replace(EN_DASH, "$1–");
2203
+ }
2204
+ function replaceInText(children, seen) {
2198
2205
  let insideAutolink = 0;
2199
- for (let i = children.length - 1;i >= 0; i--) {
2200
- const token = children[i];
2201
- if (token.type === "text" && !insideAutolink && CANDIDATE.test(token.content)) {
2202
- token.content = token.content.replace(ELLIPSIS, "…").replace(EM_DASH, "$1—").replace(EN_DASH_SPACED, "$1–").replace(EN_DASH, "$1–");
2203
- }
2204
- if (token.type === "link_close" && token.info === "auto")
2205
- insideAutolink++;
2206
+ for (const token of children) {
2206
2207
  if (token.type === "link_open" && token.info === "auto")
2208
+ insideAutolink++;
2209
+ if (token.type === "link_close" && token.info === "auto")
2207
2210
  insideAutolink--;
2211
+ if (token.type !== "text")
2212
+ continue;
2213
+ const typed = token.content;
2214
+ if (!insideAutolink) {
2215
+ let text = typed.replace(SCOPED, (match, name, offset) => {
2216
+ const label = LABEL_BEFORE[name];
2217
+ return label && (seen.has(label) || typed.slice(0, offset).includes(label)) ? match : SYMBOLS[name.toLowerCase()];
2218
+ });
2219
+ if (RARE.test(text))
2220
+ text = replaceRare(text);
2221
+ token.content = text;
2222
+ }
2223
+ for (const [label] of typed.matchAll(LABELS))
2224
+ seen.add(label);
2208
2225
  }
2209
2226
  }
2210
2227
  var QUOTES = {
@@ -2231,10 +2248,11 @@ function quotesFor(language) {
2231
2248
  function gpTypography(md) {
2232
2249
  md.disable("replacements");
2233
2250
  md.core.ruler.after("linkify", "gp_typography", (state) => {
2251
+ const seen = new Set;
2234
2252
  for (const token of state.tokens) {
2235
2253
  if (token.type !== "inline" || !token.children || !CANDIDATE.test(token.content))
2236
2254
  continue;
2237
- replaceInText(token.children);
2255
+ replaceInText(token.children, seen);
2238
2256
  }
2239
2257
  });
2240
2258
  }
@@ -3098,6 +3116,14 @@ ${TABLE_ALIGN_CSS.trim()}`),
3098
3116
  ${pageGeometry}`)
3099
3117
  ];
3100
3118
  }
3119
+ function resolveOldFootnoteLinks(html, ids) {
3120
+ if (ids.size === 0)
3121
+ return html;
3122
+ return html.replace(/ href=(["'])#(fn(?:ref)?\d+(?::\d+)?)\1/g, (link, quote, old) => {
3123
+ const id = ids.get(old);
3124
+ return id && !html.includes(` id="${old}"`) ? ` href=${quote}#${id}${quote}` : link;
3125
+ });
3126
+ }
3101
3127
  async function assembleBookHtml(opts) {
3102
3128
  const title = opts.title ?? "Document";
3103
3129
  const projectCss = opts.projectCss ?? "";
@@ -3110,6 +3136,7 @@ async function assembleBookHtml(opts) {
3110
3136
  const md = createMarkdownRenderer(opts.plugins, { language });
3111
3137
  let bodyContent = "";
3112
3138
  const imageRefs = new Set;
3139
+ const oldFootnoteIds = new Map;
3113
3140
  for (const file of files) {
3114
3141
  const chapterId = canonicalChapterId(file);
3115
3142
  let content;
@@ -3128,9 +3155,14 @@ async function assembleBookHtml(opts) {
3128
3155
  }
3129
3156
  for (const ref of env.imageRefs ?? [])
3130
3157
  imageRefs.add(ref);
3158
+ for (const [, kind, n] of rendered.matchAll(new RegExp(` id="(fn|fnref)-${env.docId}-(\\d+(?::\\d+)?)"`, "g"))) {
3159
+ if (!oldFootnoteIds.has(`${kind}${n}`))
3160
+ oldFootnoteIds.set(`${kind}${n}`, `${kind}-${env.docId}-${n}`);
3161
+ }
3131
3162
  bodyContent += rendered + `
3132
3163
  `;
3133
3164
  }
3165
+ bodyContent = resolveOldFootnoteLinks(bodyContent, oldFootnoteIds);
3134
3166
  if (opts.onImageRefs) {
3135
3167
  for (const ref of collectHtmlImageRefs(bodyContent))
3136
3168
  imageRefs.add(ref);