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
@@ -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-989eg8jz.js";
7
+ } from "./cli-ah93yyzb.js";
7
8
  import {
8
9
  resolveGhostscript
9
- } from "./cli-vhav8g82.js";
10
+ } from "./cli-rybz2dfs.js";
10
11
  import"./cli-ht1bcqdd.js";
11
- import"./cli-k087gj0p.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-31anr0r9.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-e31jshz6.js";
26
- import"./cli-ttj95aex.js";
27
- import"./cli-1fy1pm9d.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-s1zt779w.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-a4j3xcfp.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-ttj95aex.js";
12
- import"./cli-1fy1pm9d.js";
13
- import"./cli-s1zt779w.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-989eg8jz.js";
5
- import"./cli-vhav8g82.js";
4
+ } from "./cli-ah93yyzb.js";
5
+ import"./cli-rybz2dfs.js";
6
6
  import"./cli-ht1bcqdd.js";
7
- import"./cli-k087gj0p.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-31anr0r9.js";
11
+ import"./cli-eymdsefg.js";
12
12
  import"./cli-v5mp7a6q.js";
13
13
  import {
14
14
  publishTargetFor
15
- } from "./cli-e31jshz6.js";
16
- import"./cli-ttj95aex.js";
15
+ } from "./cli-5zbdb6mt.js";
16
+ import"./cli-7mt0dftw.js";
17
17
  import {
18
18
  log
19
- } from "./cli-1fy1pm9d.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-s1zt779w.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-989eg8jz.js";
7
- import"./cli-vhav8g82.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-k087gj0p.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-31anr0r9.js";
16
+ import"./cli-eymdsefg.js";
17
17
  import"./cli-v5mp7a6q.js";
18
- import"./cli-e31jshz6.js";
19
- import"./cli-ttj95aex.js";
18
+ import"./cli-5zbdb6mt.js";
19
+ import"./cli-7mt0dftw.js";
20
20
  import {
21
21
  log
22
- } from "./cli-1fy1pm9d.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-s1zt779w.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-989eg8jz.js";
13
+ } from "./cli-ah93yyzb.js";
14
14
  import {
15
15
  FileTokenStore
16
- } from "./cli-vhav8g82.js";
16
+ } from "./cli-rybz2dfs.js";
17
17
  import"./cli-ht1bcqdd.js";
18
- import"./cli-k087gj0p.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-31anr0r9.js";
22
+ import"./cli-eymdsefg.js";
23
23
  import"./cli-v5mp7a6q.js";
24
24
  import {
25
25
  loadManifestWithPath
26
- } from "./cli-e31jshz6.js";
27
- import"./cli-ttj95aex.js";
26
+ } from "./cli-5zbdb6mt.js";
27
+ import"./cli-7mt0dftw.js";
28
28
  import {
29
29
  log
30
- } from "./cli-1fy1pm9d.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-s1zt779w.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
@@ -1431,8 +1431,9 @@ img.gp-shape {
1431
1431
 
1432
1432
  /* Math (the bundled gutterpress-math feature, math.ts): MathJax's own rules
1433
1433
  for the <mjx-container> SVG output it emits, from its SVG output jax's
1434
- stylesheet, less the ones for its interactive menu and tooltips. Inert in
1435
- a book without formulas. */
1434
+ stylesheet, less the ones for its interactive menu and tooltips, plus one
1435
+ bound of ours on the hidden MathML copy (#469, below). Inert in a book
1436
+ without formulas. */
1436
1437
  mjx-container[jax="SVG"] { direction: ltr; }
1437
1438
  mjx-container[jax="SVG"] > svg { overflow: visible; min-height: 1px; min-width: 1px; }
1438
1439
  mjx-container[jax="SVG"] > svg a { fill: blue; stroke: blue; }
@@ -1449,6 +1450,15 @@ mjx-assistive-mml {
1449
1450
  border: 0px !important;
1450
1451
  display: block !important;
1451
1452
  width: auto !important;
1453
+ /* Ours (#469). The browser lays the copy out in whatever math font it has,
1454
+ so it can be wider than the formula's SVG; ending a line, it crossed the
1455
+ column edge and Chromium shrank the whole print to fit. MathJax makes the
1456
+ container position: relative with the copy at its top left, so 100% is
1457
+ the formula's width. Clip and overflow still hide the copy and its MathML
1458
+ still reaches screen readers; only its box changes. Not the 1px
1459
+ visually-hidden box MathJax 2 used: its docs note VoiceOver on iOS could
1460
+ not reach a formula by touch in it. */
1461
+ max-width: 100% !important;
1452
1462
  overflow: hidden !important;
1453
1463
  user-select: none;
1454
1464
  }
@@ -2179,22 +2189,39 @@ function gpTable(md, options) {
2179
2189
  }
2180
2190
 
2181
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 = /\+-|\.\.|\?\?\?\?|!!!!|,,|--/;
2182
2197
  var EM_DASH = /(^|[^-])---(?=[^-]|$)/gm;
2183
2198
  var EN_DASH_SPACED = /(^|\s)--(?=\s|$)/gm;
2184
2199
  var EN_DASH = /(^|[^-\s])--(?=[^-\s]|$)/gm;
2185
- var ELLIPSIS = /\.\.\./g;
2186
- var CANDIDATE = /--|\.\.\./;
2187
- 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) {
2188
2205
  let insideAutolink = 0;
2189
- for (let i = children.length - 1;i >= 0; i--) {
2190
- const token = children[i];
2191
- if (token.type === "text" && !insideAutolink && CANDIDATE.test(token.content)) {
2192
- token.content = token.content.replace(ELLIPSIS, "…").replace(EM_DASH, "$1—").replace(EN_DASH_SPACED, "$1–").replace(EN_DASH, "$1–");
2193
- }
2194
- if (token.type === "link_close" && token.info === "auto")
2195
- insideAutolink++;
2206
+ for (const token of children) {
2196
2207
  if (token.type === "link_open" && token.info === "auto")
2208
+ insideAutolink++;
2209
+ if (token.type === "link_close" && token.info === "auto")
2197
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);
2198
2225
  }
2199
2226
  }
2200
2227
  var QUOTES = {
@@ -2221,10 +2248,11 @@ function quotesFor(language) {
2221
2248
  function gpTypography(md) {
2222
2249
  md.disable("replacements");
2223
2250
  md.core.ruler.after("linkify", "gp_typography", (state) => {
2251
+ const seen = new Set;
2224
2252
  for (const token of state.tokens) {
2225
2253
  if (token.type !== "inline" || !token.children || !CANDIDATE.test(token.content))
2226
2254
  continue;
2227
- replaceInText(token.children);
2255
+ replaceInText(token.children, seen);
2228
2256
  }
2229
2257
  });
2230
2258
  }
@@ -3088,6 +3116,14 @@ ${TABLE_ALIGN_CSS.trim()}`),
3088
3116
  ${pageGeometry}`)
3089
3117
  ];
3090
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
+ }
3091
3127
  async function assembleBookHtml(opts) {
3092
3128
  const title = opts.title ?? "Document";
3093
3129
  const projectCss = opts.projectCss ?? "";
@@ -3100,6 +3136,7 @@ async function assembleBookHtml(opts) {
3100
3136
  const md = createMarkdownRenderer(opts.plugins, { language });
3101
3137
  let bodyContent = "";
3102
3138
  const imageRefs = new Set;
3139
+ const oldFootnoteIds = new Map;
3103
3140
  for (const file of files) {
3104
3141
  const chapterId = canonicalChapterId(file);
3105
3142
  let content;
@@ -3118,9 +3155,14 @@ async function assembleBookHtml(opts) {
3118
3155
  }
3119
3156
  for (const ref of env.imageRefs ?? [])
3120
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
+ }
3121
3162
  bodyContent += rendered + `
3122
3163
  `;
3123
3164
  }
3165
+ bodyContent = resolveOldFootnoteLinks(bodyContent, oldFootnoteIds);
3124
3166
  if (opts.onImageRefs) {
3125
3167
  for (const ref of collectHtmlImageRefs(bodyContent))
3126
3168
  imageRefs.add(ref);