gutterpress 0.11.19 → 0.11.20-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/api/index.js +2 -2
  2. package/dist/{build-czbaj4qf.js → build-qmjg9r2d.js} +4 -4
  3. package/dist/checks/pdf/index.d.ts +1 -0
  4. package/dist/checks/pdf/safe-margins.d.ts +3 -0
  5. package/dist/{cli-cgbzdrwz.js → cli-7z29z4wz.js} +1 -1
  6. package/dist/{cli-dzw28t3s.js → cli-gh0ym80r.js} +2 -1
  7. package/dist/{cli-xx94a1k6.js → cli-j802s31j.js} +5 -5
  8. package/dist/{cli-aw614ztv.js → cli-zacevwcy.js} +299 -184
  9. package/dist/cli.js +12 -12
  10. package/dist/{doctor-6e9perj7.js → doctor-fe7tcs4v.js} +2 -2
  11. package/dist/{engine-fe0n7v9p.js → engine-9xb1ky8d.js} +1 -1
  12. package/dist/{engine-zehw6tkv.js → engine-yax79k9m.js} +2 -2
  13. package/dist/{ext-kavfk1zn.js → ext-ahwxt6gv.js} +4 -4
  14. package/dist/{gutterpress-viewer-k4mpqjh0.js → gutterpress-viewer-retj6ym2.js} +515 -281
  15. package/dist/{index-jt552wtf.js → index-3nr5rzzp.js} +5 -5
  16. package/dist/{index-b866g2ph.js → index-6xwtb7cw.js} +1 -1
  17. package/dist/{index-g7vszjqf.js → index-razpty47.js} +298 -182
  18. package/dist/index.js +3 -3
  19. package/dist/lib/ghostscript.d.ts +7 -0
  20. package/dist/lib/presets.d.ts +3 -1
  21. package/dist/{manifest.schema-5pzhscqh.json → manifest.schema-74s1ykyv.json} +20 -1
  22. package/dist/{new-ckpas1ya.js → new-ftd4fec4.js} +4 -4
  23. package/dist/{preflight-yh57q9nn.js → preflight-8sqarcsr.js} +4 -4
  24. package/dist/preview/file-watcher.d.ts +16 -2
  25. package/dist/{preview-bridge-evecsh4w.js → preview-bridge-8wjcjec3.js} +3 -2
  26. package/dist/{preview-interface-2n1d9pbf.js → preview-interface-nnmrxyqm.js} +37 -41
  27. package/dist/{preview-a4x2ezjp.js → preview-q76xn95h.js} +4 -4
  28. package/dist/{preview-shell-hyp7g158.js → preview-shell-wk9k3gcd.js} +18 -6
  29. package/dist/{publish-sfn5hmnx.js → publish-7gdy6gbf.js} +4 -4
  30. package/dist/schema/manifest.types.d.ts +38 -3
  31. package/dist/{validate-281rsdsv.js → validate-e3ryegce.js} +4 -4
  32. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -154,14 +154,14 @@ import {
154
154
  testRemoteAccess,
155
155
  updateExtensions,
156
156
  validateProjectExtensions
157
- } from "./index-g7vszjqf.js";
157
+ } from "./index-razpty47.js";
158
158
  import"./index-ht1bcqdd.js";
159
159
  import {
160
160
  BUILD_DIAGNOSTIC_CODES
161
- } from "./index-b866g2ph.js";
161
+ } from "./index-6xwtb7cw.js";
162
162
  import {
163
163
  BuildError
164
- } from "./index-jt552wtf.js";
164
+ } from "./index-3nr5rzzp.js";
165
165
  import {
166
166
  DEFAULT_PRINT_OPTS,
167
167
  assertMilestone,
@@ -100,5 +100,12 @@ export declare function convertToPdfxCmyk(inputPdf: string, outPdf: string, conf
100
100
  title?: string;
101
101
  maxTac?: number;
102
102
  stagingDir: string;
103
+ /**
104
+ * Resolution of the picture Ghostscript makes of a page it flattens
105
+ * (`pdfx.rasterDpi`). Unset keeps Ghostscript's own default (720 DPI).
106
+ * pdfwrite uses it only for rendering it must do, such as transparency
107
+ * flattening: vector content is unaffected.
108
+ */
109
+ rasterDpi?: number;
103
110
  }): Promise<void>;
104
111
  export {};
@@ -8,7 +8,9 @@ import type { ResolvedConfig } from "../schema/manifest.types";
8
8
  * Every preset value is overridable from the manifest, leaf by leaf
9
9
  * (resolveConfig's mergeShape; precedence cli > manifest > target > preset).
10
10
  */
11
- export interface VendorPreset extends Omit<ResolvedConfig, "title" | "authors" | "targets" | "page"> {
11
+ export interface VendorPreset extends Omit<ResolvedConfig, "title" | "authors" | "preset" | "targets" | "page"> {
12
+ /** This preset's id: what the manifest's `preset:` names and a resolved config reports. */
13
+ id: PresetId;
12
14
  /**
13
15
  * Base page geometry in points, or `null` for `custom` — the one preset
14
16
  * with no built-in trim, which therefore REQUIRES the manifest to supply
@@ -154,6 +154,13 @@
154
154
  "description": "How near-black text is separated. `icc` converts it through the ICC profile (rich, four-colour black). `k-only` prints it on the black plate alone (100% K), which print vendors such as DriveThruRPG require for small text. Non-text black (rules, panels) is unaffected. Preset defaults: dtrpg `k-only`, book `icc`.",
155
155
  "enum": ["icc", "k-only"],
156
156
  "default": "icc"
157
+ },
158
+ "rasterDpi": {
159
+ "type": "integer",
160
+ "description": "Resolution (DPI) of the picture Ghostscript makes of a page it flattens in a PDF/X build because the page uses transparency (PDF/X-1a and X-3 cannot hold it). Lower is smaller and softer; vector content on other pages and the book's own images are not resampled. Unset: Ghostscript's default, 720.",
161
+ "minimum": 72,
162
+ "maximum": 1200,
163
+ "examples": [300]
157
164
  }
158
165
  }
159
166
  },
@@ -203,9 +210,21 @@
203
210
  },
204
211
  "bleed": {
205
212
  "type": "number",
206
- "description": "A bleed, in points, that the page width x height ALREADY CONTAINS on the top, bottom and OUTER edges (none on the binding edge) — how DriveThruRPG's interior file is cut (8.625 x 11.25in for an 8.5 x 11in book). Preview overlay only: it tells the margin & bleed overlay where the trim is and changes nothing in the PDF. CSS `@page { bleed }` wins when the stylesheet declares one. Preset default: dtrpg 9 (0.125in); book and custom none.",
213
+ "description": "A bleed, in points, that the page width x height ALREADY CONTAINS on the top, bottom and OUTER edges (none on the binding edge) — how DriveThruRPG's interior file is cut (8.625 x 11.25in for an 8.5 x 11in book). It tells the preview's safe area & bleed overlay and the `pdf.print.safe-margins` check where the trim is, and changes nothing in the PDF. Preset default: dtrpg 9 (0.125in); book and custom none.",
207
214
  "minimum": 0,
208
215
  "examples": [9]
216
+ },
217
+ "safe": {
218
+ "type": "number",
219
+ "description": "The TEXT rule, in points: how far inside the trim glyphs must stay, on every edge. For DriveThruRPG it is the \"text at least 0.5in inside the trim\" rule. The preview's overlay outlines it (dashed) and flags text outside it, and the `pdf.print.safe-margins` check fails a PDF whose text is closer. It changes nothing in the PDF, and no book CSS moves it. Preset default: dtrpg 36 (0.5in), book 18 (0.25in); custom none.",
220
+ "minimum": 0,
221
+ "examples": [18, 36]
222
+ },
223
+ "artSafe": {
224
+ "type": "number",
225
+ "description": "The ART rule, in points: how far inside the trim art that does not bleed (images, backgrounds, borders, rules) must stay on the top, bottom and OUTER edge; at the binding edge art uses `safe`. For DriveThruRPG it is the \"non-bleeding art at least 0.25in from the outside edges (0.5in at the binding)\" rule. Art that runs out to the page's edge is a bleed and is not judged on that edge. The preview's overlay outlines it (dotted) and flags art outside it. Preview overlay only: it changes nothing in the PDF. Absent = the same as `safe`. Preset default: dtrpg 18 (0.25in); book and custom none.",
226
+ "minimum": 0,
227
+ "examples": [18]
209
228
  }
210
229
  }
211
230
  },
@@ -7,17 +7,17 @@ import {
7
7
  TARGET_IDS,
8
8
  scaffoldExtension,
9
9
  scaffoldProject
10
- } from "./cli-aw614ztv.js";
10
+ } from "./cli-zacevwcy.js";
11
11
  import {
12
12
  resolveGhostscript
13
- } from "./cli-dzw28t3s.js";
13
+ } from "./cli-gh0ym80r.js";
14
14
  import {
15
15
  UsageError,
16
16
  rejectExtraPositionals,
17
17
  rejectUnknownFlags
18
- } from "./cli-cgbzdrwz.js";
18
+ } from "./cli-7z29z4wz.js";
19
19
  import"./cli-ht1bcqdd.js";
20
- import"./cli-xx94a1k6.js";
20
+ import"./cli-j802s31j.js";
21
21
  import {
22
22
  EXIT_CODES
23
23
  } from "./cli-46ycxe6r.js";
@@ -2,17 +2,17 @@ import {
2
2
  executeValidation,
3
3
  publishTargetFor,
4
4
  reportMissingTools
5
- } from "./cli-aw614ztv.js";
5
+ } from "./cli-zacevwcy.js";
6
6
  import {
7
7
  log
8
- } from "./cli-dzw28t3s.js";
8
+ } from "./cli-gh0ym80r.js";
9
9
  import {
10
10
  UsageError,
11
11
  rejectExtraPositionals,
12
12
  rejectUnknownFlags
13
- } from "./cli-cgbzdrwz.js";
13
+ } from "./cli-7z29z4wz.js";
14
14
  import"./cli-ht1bcqdd.js";
15
- import"./cli-xx94a1k6.js";
15
+ import"./cli-j802s31j.js";
16
16
  import {
17
17
  BuildError,
18
18
  EXIT_CODES
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import { type FSWatcher } from 'chokidar';
8
8
  import type { ServerState } from './server-context';
9
- import type { ResolvedExtensionConfig } from '../schema/manifest.types';
9
+ import type { PrintSpec, ResolvedExtensionConfig } from '../schema/manifest.types';
10
10
  import type { PrintPadding } from '../engine/shared/synthesis.ts';
11
11
  /**
12
12
  * Rewrite rendered book HTML for the live preview: inject the Gutterpress
@@ -22,7 +22,15 @@ import type { PrintPadding } from '../engine/shared/synthesis.ts';
22
22
  * no per-source wrappers or forced breaks are added, so preview pagination
23
23
  * never diverges from the PDF where a source file begins mid-page.
24
24
  */
25
- export declare function injectPreviewScripts(html: string, insetBleedPt?: number): string;
25
+ export declare function injectPreviewScripts(html: string, page?: {
26
+ width: number;
27
+ height: number;
28
+ bleed?: number;
29
+ safe?: number;
30
+ artSafe?: number;
31
+ preset?: string;
32
+ spec?: PrintSpec;
33
+ }): string;
26
34
  /**
27
35
  * Generate HTML from markdown and write book.html to the temp directory.
28
36
  * The desktop's iframe loads `book.html` via a relative URL — same name in
@@ -46,8 +54,14 @@ export declare function generateAndWriteHtml(inputPath: string, tempDir: string,
46
54
  extensions?: ResolvedExtensionConfig[];
47
55
  print?: PrintPadding;
48
56
  page?: {
57
+ width: number;
58
+ height: number;
49
59
  bleed?: number;
60
+ safe?: number;
61
+ artSafe?: number;
50
62
  };
63
+ preset?: string;
64
+ spec?: PrintSpec;
51
65
  }, cssAssets: Map<string, string>, imageRefs?: Set<string>): Promise<void>;
52
66
  /**
53
67
  * Chokidar 5's `ignored` matcher (regex or function) is tested against the
@@ -14,7 +14,7 @@
14
14
  //
15
15
  // Commands map 1:1 to previewAPI methods: getTotalPages, getCurrentPage,
16
16
  // goToPage, firstPage, prevPage, nextPage, lastPage, setViewMode, setZoom,
17
- // toggleDebugMode, setMarginOverlay(on, {color, strength}). Plus a synthetic 'print' command that calls window.print().
17
+ // toggleDebugMode, setMarginOverlay(state, {strength, colors}). Plus a synthetic 'print' command that calls window.print().
18
18
  //
19
19
  // Additional messages:
20
20
  // parent -> iframe: { type: 'gutterpress:inject-styles', id: <attr-name>, css: <string> }
@@ -82,7 +82,8 @@
82
82
  window.addEventListener('contextMenuRequested', function (e) {
83
83
  post({ type: 'gutterpress:event', name: 'contextMenuRequested', detail: e.detail });
84
84
  });
85
- // Margin & bleed overlay result (protocol v9): {on, issues, intended, bleedPt}.
85
+ // Margin & bleed overlay result (protocol v9): {on, issues, intended, bleedPt,
86
+ // safePt, artSafePt, counts}.
86
87
  window.addEventListener('overlayChanged', function (e) {
87
88
  post({ type: 'gutterpress:event', name: 'overlayChanged', detail: e.detail });
88
89
  });
@@ -1098,27 +1098,43 @@
1098
1098
  // "Edit this block" action and nothing else; a v8 SPA feature-detects on
1099
1099
  // the version before offering it.
1100
1100
  // v9: ADDED setMarginOverlay()/toggleMarginOverlay()/getMarginOverlay() and
1101
- // the overlayChanged event (margin & bleed overlay, engine/viewer/
1102
- // overlay.ts). A v9 lib with a pre-v9 SPA simply never turns it on; a v9
1103
- // SPA feature-detects on the version before offering the toggle.
1101
+ // the overlayChanged event (print overlays, engine/viewer/overlay.ts). A
1102
+ // v9 lib with a pre-v9 SPA simply never turns it on; a v9 SPA
1103
+ // feature-detects on the version before offering the toggle.
1104
1104
  // (v9 is unreleased as of this writing, so setMarginOverlay's optional
1105
- // second argument — the look, below — is part of v9, not a bump.)
1105
+ // second argument — the look, below — and its layer object are part of
1106
+ // v9, not a bump: a plain boolean still works and means all four layers.)
1106
1107
  getProtocolVersion: function () { return 9; },
1107
1108
 
1108
- // Margin & bleed overlay. Viewer chrome only — it adds no box to the book
1109
- // and no attribute to its elements, so pagination is identical on or off.
1110
- // Returns the summary {on, issues, intended, bleedPt}, or null when the
1111
- // viewer predates it. `style` ({color: '#rrggbb', strength: 'subtle' |
1112
- // 'normal' | 'strong'}) is optional: it only sets the viewer's own
1113
- // `--gp-ov-*` tokens, and a call that carries it while the overlay is
1114
- // already on restyles without repainting.
1115
- setMarginOverlay: function (on, style) {
1109
+ // Print overlays: four layers (bleed, safe = the text safe area, art = the
1110
+ // art safe area, margins), each independent. Viewer chrome only — it adds
1111
+ // no box to the book and no attribute to its elements, so pagination is
1112
+ // identical on or off. `state` is a boolean (all four layers) or {bleed,
1113
+ // safe, art, margins} naming the layers that are on (one it leaves out is
1114
+ // off). Returns the summary {on, layers: {bleed, safe, art, margins},
1115
+ // issues, intended, bleedPt, safePt, artSafePt, counts: {text, art, bleed,
1116
+ // offPage, intended}}, or null when the viewer predates it. `style`
1117
+ // ({strength: 'subtle' | 'normal' | 'strong', colors: {bleed, safe, art,
1118
+ // margins} as '#rrggbb', color: an alias of colors.safe}) is optional: it
1119
+ // only sets the overlay's own tokens, and a call that carries it while the
1120
+ // same layers are already on restyles without repainting.
1121
+ setMarginOverlay: function (state, style) {
1116
1122
  var d = window.Gutterpress && window.Gutterpress.decoration;
1117
- return d && typeof d.setOverlay === 'function' ? d.setOverlay(!!on, style) : null;
1123
+ return d && typeof d.setOverlay === 'function' ? d.setOverlay(state, style) : null;
1118
1124
  },
1125
+ // Hide the overlay, or bring back the layers it was last showing (the
1126
+ // viewer's record on <body>; all four the first time).
1119
1127
  toggleMarginOverlay: function () {
1120
1128
  var d = window.Gutterpress && window.Gutterpress.decoration;
1121
- return d && typeof d.setOverlay === 'function' ? d.setOverlay(document.body.dataset.overlay !== 'on') : null;
1129
+ if (!d || typeof d.setOverlay !== 'function') return null;
1130
+ if (document.body.dataset.overlay === 'on') return d.setOverlay(false);
1131
+ var last = (document.body.dataset.overlayLayers || 'bleed,safe,art,margins').split(',');
1132
+ return d.setOverlay({
1133
+ bleed: last.indexOf('bleed') >= 0,
1134
+ safe: last.indexOf('safe') >= 0,
1135
+ art: last.indexOf('art') >= 0,
1136
+ margins: last.indexOf('margins') >= 0
1137
+ });
1122
1138
  },
1123
1139
  getMarginOverlay: function () {
1124
1140
  var d = window.Gutterpress && window.Gutterpress.decoration;
@@ -1629,43 +1645,23 @@
1629
1645
  // completes (engine/viewer/index.ts's mount()).
1630
1646
  window.addEventListener('gp:layout', onRenderingComplete);
1631
1647
 
1632
- // Margin & bleed overlay: relay the viewer's result as 'overlayChanged' (the
1633
- // bridge posts it to a host toolbar) and, where no host toolbar exists, give
1634
- // the standalone CLI preview its own switch: Alt+M, plus a small status pill.
1648
+ // Print overlays: relay the viewer's result as 'overlayChanged' (the bridge
1649
+ // posts it to a host toolbar) and, where no host toolbar exists, give the
1650
+ // standalone CLI preview its own switch: Alt+M. The viewer's legend carries
1651
+ // the rest — what each layer is, what was found — so there is no badge here.
1635
1652
  // "Standalone" = the shell is top level (the CLI); under the desktop app the
1636
1653
  // shell's parent is the app, which owns the toggle and the count.
1637
1654
  var standalone = false;
1638
1655
  try { standalone = window.parent === window || window.parent.parent === window.parent; } catch (_e) {}
1639
1656
 
1640
- function updateOverlayBadge(summary) {
1641
- var badge = document.getElementById('gp-ov-badge');
1642
- if (!standalone || !summary || !summary.on) {
1643
- if (badge) badge.remove();
1644
- return;
1645
- }
1646
- if (!badge) {
1647
- badge = document.createElement('div');
1648
- badge.id = 'gp-ov-badge';
1649
- badge.setAttribute('role', 'status');
1650
- badge.style.cssText = 'position:fixed;top:8px;right:8px;z-index:2147483000;pointer-events:none;' +
1651
- 'background:rgba(20,20,24,.88);color:#fff;font:600 11px/1.4 ui-sans-serif,system-ui,sans-serif;' +
1652
- 'padding:4px 10px;border-radius:999px;box-shadow:0 1px 6px rgba(0,0,0,.4)';
1653
- document.documentElement.appendChild(badge);
1654
- }
1655
- var parts = ['Margins & bleed'];
1656
- parts.push(summary.issues ? summary.issues + ' overflowing' : 'nothing overflows');
1657
- if (summary.intended) parts.push(summary.intended + ' placed on purpose');
1658
- if (summary.bleedInSheet) parts.push('bleed inside the page (print preset)');
1659
- if (!summary.bleedPt) parts.push('no bleed set \u2014 add @page { bleed: 0.125in } to see the bleed edge');
1660
- badge.textContent = parts.join(' \u00b7 ') + ' (Alt+M hides)';
1661
- }
1662
-
1663
1657
  window.addEventListener('gp:overlay', function (e) {
1664
- updateOverlayBadge(e.detail);
1665
1658
  window.dispatchEvent(new CustomEvent('overlayChanged', { detail: e.detail }));
1666
1659
  });
1667
1660
 
1668
1661
  if (standalone) {
1662
+ // The legend ends "Alt+M hides" only where this key is bound: the viewer
1663
+ // reads the key from here.
1664
+ document.documentElement.dataset.overlayKey = 'Alt+M';
1669
1665
  document.addEventListener('keydown', function (e) {
1670
1666
  if (e.code !== 'KeyM' || !e.altKey || e.ctrlKey || e.metaKey || e.defaultPrevented) return;
1671
1667
  e.preventDefault();
@@ -6,10 +6,10 @@ import {
6
6
  runBuild,
7
7
  splitOutPath,
8
8
  startPreviewServer
9
- } from "./cli-aw614ztv.js";
9
+ } from "./cli-zacevwcy.js";
10
10
  import {
11
11
  log
12
- } from "./cli-dzw28t3s.js";
12
+ } from "./cli-gh0ym80r.js";
13
13
  import {
14
14
  UsageError,
15
15
  parseFormat,
@@ -17,9 +17,9 @@ import {
17
17
  rejectExtraPositionals,
18
18
  rejectUnknownFlags,
19
19
  resolvePort
20
- } from "./cli-cgbzdrwz.js";
20
+ } from "./cli-7z29z4wz.js";
21
21
  import"./cli-ht1bcqdd.js";
22
- import"./cli-xx94a1k6.js";
22
+ import"./cli-j802s31j.js";
23
23
  import {
24
24
  BuildError
25
25
  } from "./cli-46ycxe6r.js";
@@ -106,13 +106,25 @@
106
106
  else if (sourceBody.classList.contains('view-spread')) api.setViewMode('spread', true);
107
107
  else if (sourceBody.classList.contains('view-two-column')) api.setViewMode('two-column', true);
108
108
  if (sourceBody.classList.contains('debug')) api.toggleDebugMode();
109
- // The margin & bleed overlay is a review aid the author switched on: a
110
- // hot reload must not drop it.
111
- // Its look (colour, strength) travels with it.
109
+ // The print overlays are a review aid the author switched on: a hot
110
+ // reload must not drop them. The layers that were showing and their look
111
+ // (a colour per layer, strength) travel with them, as the viewer
112
+ // recorded them on <body>.
112
113
  if (sourceBody.dataset.overlay === 'on' && api.setMarginOverlay) {
113
- api.setMarginOverlay(true, {
114
- color: sourceBody.style.getPropertyValue('--gp-ov-color').trim(),
115
- strength: sourceBody.dataset.overlayStrength
114
+ var shown = (sourceBody.dataset.overlayLayers || '').split(',');
115
+ api.setMarginOverlay({
116
+ bleed: shown.indexOf('bleed') >= 0,
117
+ safe: shown.indexOf('safe') >= 0,
118
+ art: shown.indexOf('art') >= 0,
119
+ margins: shown.indexOf('margins') >= 0
120
+ }, {
121
+ strength: sourceBody.dataset.overlayStrength,
122
+ colors: {
123
+ bleed: sourceBody.dataset.overlayBleedColor,
124
+ safe: sourceBody.dataset.overlayColor,
125
+ art: sourceBody.dataset.overlayArtColor,
126
+ margins: sourceBody.dataset.overlayMarginsColor
127
+ }
116
128
  });
117
129
  }
118
130
  }
@@ -11,18 +11,18 @@ import {
11
11
  publishProviderFor,
12
12
  resolvePublishFormat,
13
13
  runPublish
14
- } from "./cli-aw614ztv.js";
14
+ } from "./cli-zacevwcy.js";
15
15
  import {
16
16
  FileTokenStore,
17
17
  log
18
- } from "./cli-dzw28t3s.js";
18
+ } from "./cli-gh0ym80r.js";
19
19
  import {
20
20
  UsageError,
21
21
  rejectExtraPositionals,
22
22
  rejectUnknownFlags
23
- } from "./cli-cgbzdrwz.js";
23
+ } from "./cli-7z29z4wz.js";
24
24
  import"./cli-ht1bcqdd.js";
25
- import"./cli-xx94a1k6.js";
25
+ import"./cli-j802s31j.js";
26
26
  import {
27
27
  EXIT_CODES
28
28
  } from "./cli-46ycxe6r.js";
@@ -118,6 +118,11 @@ export interface GutterpressManifest {
118
118
  stripAnnotations?: boolean;
119
119
  /** `k-only` prints near-black text on the black plate alone (#331). */
120
120
  blackText?: "icc" | "k-only";
121
+ /**
122
+ * Resolution (DPI) of the picture Ghostscript makes of a page it flattens
123
+ * because the page uses transparency. Unset: Ghostscript's default (720).
124
+ */
125
+ rasterDpi?: number;
121
126
  };
122
127
  /**
123
128
  * Native-engine print-production options with no other manifest home
@@ -150,11 +155,27 @@ export interface GutterpressManifest {
150
155
  * A bleed (pt) the page `width` x `height` ALREADY CONTAINS, on the top,
151
156
  * bottom and OUTER edges only (the binding edge has none) — how
152
157
  * DriveThruRPG's interior file is cut (8.625 x 11.25in for an 8.5 x 11in
153
- * book). It changes nothing in the PDF: it only tells the preview's margin
154
- * & bleed overlay where the trim is. CSS `@page { bleed }` (symmetric,
155
- * grows the page) wins when the stylesheet declares one.
158
+ * book). It changes nothing in the PDF: it only tells the preview's safe
159
+ * area & bleed overlay and `pdf.print.safe-margins` where the trim is.
156
160
  */
157
161
  bleed?: number;
162
+ /**
163
+ * The TEXT rule (pt): glyphs stay at least this far inside the trim on
164
+ * EVERY edge — DriveThruRPG's "keep text 0.5in inside the trim" (`dtrpg`
165
+ * sets 36). The preview's overlay outlines it and flags text outside it,
166
+ * and `pdf.print.safe-margins` fails a built PDF whose text is closer. Like
167
+ * `bleed`, it changes nothing in the PDF, and nothing in a book's CSS moves
168
+ * it.
169
+ */
170
+ safe?: number;
171
+ /**
172
+ * The ART rule (pt): art that does not bleed — images, backgrounds,
173
+ * borders, rules — stays at least this far inside the trim on the top,
174
+ * bottom and OUTER edge; at the binding edge it uses `safe`. DriveThruRPG's
175
+ * "keep non-bleeding art 0.25in from the outside edges" (`dtrpg` sets 18).
176
+ * Absent = the same as `safe`.
177
+ */
178
+ artSafe?: number;
158
179
  };
159
180
  ink?: {
160
181
  maxTac?: number;
@@ -236,6 +257,11 @@ export interface ResolvedExtensionConfig {
236
257
  export?: string;
237
258
  options: Record<string, unknown>;
238
259
  }
260
+ /** The printer's published specification that a preset's numbers come from. */
261
+ export interface PrintSpec {
262
+ label: string;
263
+ url: string;
264
+ }
239
265
  /**
240
266
  * Fully-resolved config. Every field is a concrete default with one
241
267
  * deliberate exception: `styles`. There is no preset
@@ -247,6 +273,10 @@ export interface ResolvedExtensionConfig {
247
273
  export interface ResolvedConfig {
248
274
  title: string;
249
275
  authors: string[];
276
+ /** The id of the preset this book resolved against (`dtrpg`, `book`, `custom`). */
277
+ preset: string;
278
+ /** The printer spec that preset follows, when it follows one: how a host credits the numbers it draws. */
279
+ spec?: PrintSpec;
250
280
  /** Validated publish-target ids for this book (may be empty). */
251
281
  targets: string[];
252
282
  styles?: string[];
@@ -260,6 +290,7 @@ export interface ResolvedConfig {
260
290
  icc: string;
261
291
  stripAnnotations: boolean;
262
292
  blackText: "icc" | "k-only";
293
+ rasterDpi?: number;
263
294
  };
264
295
  print: {
265
296
  signature: number;
@@ -272,6 +303,10 @@ export interface ResolvedConfig {
272
303
  tolerance: number;
273
304
  /** In-sheet bleed in pt (top, bottom, outer edge; see the manifest field); absent = none. */
274
305
  bleed?: number;
306
+ /** The text rule's inset from the trim in pt, every edge (see the manifest field); absent = none. */
307
+ safe?: number;
308
+ /** The art rule's inset from the trim in pt, top/bottom/outer edge (see the manifest field); absent = same as `safe`. */
309
+ artSafe?: number;
275
310
  };
276
311
  ink: {
277
312
  maxTac: number;
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  executeAndReport
3
- } from "./cli-aw614ztv.js";
3
+ } from "./cli-zacevwcy.js";
4
4
  import {
5
5
  log
6
- } from "./cli-dzw28t3s.js";
6
+ } from "./cli-gh0ym80r.js";
7
7
  import {
8
8
  UsageError,
9
9
  rejectExtraPositionals,
10
10
  rejectUnknownFlags
11
- } from "./cli-cgbzdrwz.js";
11
+ } from "./cli-7z29z4wz.js";
12
12
  import"./cli-ht1bcqdd.js";
13
- import"./cli-xx94a1k6.js";
13
+ import"./cli-j802s31j.js";
14
14
  import {
15
15
  BuildError,
16
16
  EXIT_CODES
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gutterpress",
3
- "version": "0.11.19",
3
+ "version": "0.11.20-alpha.2",
4
4
  "description": "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
5
5
  "author": "itlackey",
6
6
  "license": "MPL-2.0",