gutterpress 0.11.10-alpha.2 → 0.11.10-alpha.6

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 (59) hide show
  1. package/README.md +24 -46
  2. package/dist/api/index.d.ts +1 -1
  3. package/dist/api/index.js +10 -6
  4. package/dist/{build-dfpvvhys.js → build-npxq1tvm.js} +7 -6
  5. package/dist/cdp-jg95s674.js +15 -0
  6. package/dist/cdp-smdx6mr3.js +16 -0
  7. package/dist/{cli-d8rdk1y7.js → cli-30j93gzt.js} +11 -335
  8. package/dist/{cli-pfczdbyd.js → cli-5qr3z0qa.js} +10 -404
  9. package/dist/{cli-c41yr7he.js → cli-7fkhgtfn.js} +3 -1
  10. package/dist/{cli-k2hwrp7s.js → cli-97bdz5k0.js} +1 -4
  11. package/dist/cli-kkzka31p.js +261 -0
  12. package/dist/{cli-p679pvce.js → cli-vbzkkcbv.js} +2 -2
  13. package/dist/{cli-4xksazfr.js → cli-z8ye91f0.js} +283 -1142
  14. package/dist/cli.js +12 -14
  15. package/dist/{doctor-hheax5yc.js → doctor-ykr6gtpv.js} +3 -3
  16. package/dist/engine/shared/cdp.d.ts +23 -19
  17. package/dist/engine-3gwctsty.js +24 -0
  18. package/dist/engine-mwshptgf.js +25 -0
  19. package/dist/{ext-q5024j6v.js → ext-bna9nr3v.js} +7 -6
  20. package/dist/{index-1a4rx87v.js → index-322fxk25.js} +344 -1130
  21. package/dist/{index-kqftehgy.js → index-dzp0hc2c.js} +4 -2
  22. package/dist/{index-fnhak0nh.js → index-qf7y4d85.js} +10 -404
  23. package/dist/index-r4wvy5v3.js +267 -0
  24. package/dist/{index-t43k5rq1.js → index-rzm1phg0.js} +23 -356
  25. package/dist/index.d.ts +0 -1
  26. package/dist/index.js +12 -87
  27. package/dist/lib/build-error.d.ts +4 -5
  28. package/dist/lib/build-preflight.d.ts +1 -35
  29. package/dist/lib/build-runner.d.ts +27 -44
  30. package/dist/lib/chromium.d.ts +5 -1
  31. package/dist/lib/engine.d.ts +3 -18
  32. package/dist/lib/extension-manager.d.ts +2 -2
  33. package/dist/lib/extension-manifest.d.ts +1 -1
  34. package/dist/lib/markdown/assemble.d.ts +2 -9
  35. package/dist/lib/markdown/index.d.ts +2 -4
  36. package/dist/lib/markdown/plugins.d.ts +0 -3
  37. package/dist/lib/npm-plugin-installer.d.ts +6 -1
  38. package/dist/lib/plugin-vendor.d.ts +10 -78
  39. package/dist/lib/source-provider.d.ts +1 -1
  40. package/dist/lib/validation-exec.d.ts +5 -6
  41. package/dist/{new-6xm4tdxb.js → new-0hv3nwqj.js} +9 -8
  42. package/dist/{preflight-ezt8rvg3.js → preflight-pk0k25fm.js} +7 -6
  43. package/dist/preview/file-watcher.d.ts +4 -43
  44. package/dist/preview/http-server.d.ts +1 -3
  45. package/dist/{preview-hehs46dd.js → preview-8b1fn59h.js} +7 -6
  46. package/dist/{preview-shell-gqnc5xxe.js → preview-shell-tqndvhbx.js} +5 -7
  47. package/dist/{publish-ha505ejq.js → publish-ba5h76tz.js} +7 -6
  48. package/dist/render.d.ts +1 -1
  49. package/dist/render.js +1 -9
  50. package/dist/{source-provider-ta09wegv.js → source-provider-pzmz0br9.js} +1 -1
  51. package/dist/{source-provider-7c2ww3bz.js → source-provider-qbthnmqw.js} +1 -1
  52. package/dist/{validate-je56vdbj.js → validate-4rq2r5b3.js} +7 -6
  53. package/package.json +1 -4
  54. package/dist/audit-v9594a72.js +0 -69
  55. package/dist/engine-qtfrfbpk.js +0 -41
  56. package/dist/engine-trte2tg2.js +0 -40
  57. package/dist/lib/browser-pool.d.ts +0 -35
  58. package/dist/lib/lint-runner.d.ts +0 -29
  59. package/dist/lint-tbywt66a.js +0 -68
package/README.md CHANGED
@@ -133,9 +133,9 @@ The full configuration cascade is `CLI flags > manifest.yaml > preset defaults`.
133
133
 
134
134
  ## Commands
135
135
 
136
- Gutterpress has 10 subcommands. `new`, `preview`, `build`, and `publish` are the
137
- primary author commands; `lint`, `validate`, `audit`, and `preflight` are
138
- CI / advanced checks; `doctor` reports system readiness; and `ext` manages the
136
+ Gutterpress has 8 subcommands. `new`, `preview`, `build`, and `publish` are the
137
+ primary author commands; `validate` and `preflight` are CI / advanced
138
+ checks; `doctor` reports system readiness; and `ext` manages the
139
139
  project's extensions (plugins, looks, component libraries). Every
140
140
  command also accepts `--help` for the authoritative, always-current flag list
141
141
  (`gutterpress <command> --help`) — this section is regenerated from the same
@@ -268,28 +268,6 @@ gutterpress publish --provider gdrive --connect
268
268
  gutterpress publish --provider gdrive ./my-book
269
269
  ```
270
270
 
271
- ### `gutterpress lint`
272
-
273
- Run Gutterpress's PostCSS-based print-safety checks, including remote URLs,
274
- rasterizing effects, and source-level page-containment risks, against the
275
- project's CSS files.
276
-
277
- ```sh
278
- gutterpress lint [files] [options]
279
-
280
- --manifest <path> Path to manifest.yaml
281
- ```
282
-
283
- `files` is a positional: either a project directory containing `manifest.yaml` (its configured stylesheets are linted), or a glob pattern for CSS files to lint directly. There is no `--files` flag — pass the directory/glob as the positional.
284
-
285
- Common findings include remote `url(...)` references, effects that rasterize
286
- print text, and declarations on core page wrappers that could clip or trap
287
- out-of-flow art. Each finding is listed with its file and `line:col`, so you
288
- can see exactly which selectors rasterize text; a property at its initial value
289
- (`filter: none`, `will-change: auto`) is not a finding. The source-level
290
- containment check is an early signal; the build-time `engine.layer.trapped`
291
- diagnostic inspects the authoritative live ancestor chain.
292
-
293
271
  ### `gutterpress validate`
294
272
 
295
273
  Run the validation pipeline (pre-build source checks and/or post-build PDF checks). Tools that aren't installed are skipped with a warning — they don't fail the run. See [User Guide: Chapter 6 — Validation](https://github.com/dimm-city/gutterpress/blob/main/examples/gutterpress-user-guide/06-validation.md) for the full check list and [User Guide: Chapter 7 — System Setup](https://github.com/dimm-city/gutterpress/blob/main/examples/gutterpress-user-guide/07-system-setup.md) for which external tools each check needs.
@@ -324,18 +302,17 @@ It writes only when `source.markdownlint` is actually part of the run, so
324
302
  markdown untouched — `--fix` can never rewrite a file for a check the report
325
303
  does not mention.
326
304
 
327
- ### `gutterpress audit`
328
-
329
- Run asset-only validation checks (image DPI/format/color-space, print-readiness) without the rest of the validation pipeline.
305
+ Two narrowed runs replace the former `lint` and `audit` commands (removed in
306
+ 0.11.10 — each was a thin alias over this same pipeline):
330
307
 
331
308
  ```sh
332
- gutterpress audit [dir] [options]
309
+ # CSS print-safety only — remote url(), rasterizing effects, page containment
310
+ # (the check `gutterpress lint <dir>` used to run; findings list file and line:col)
311
+ gutterpress validate my-book --only source.stylelint
333
312
 
334
- --input <dir> Asset directory (overrides the positional directory)
335
- --manifest <path> Path to manifest.yaml
336
- --only <ids> Run only these check IDs/selectors (comma-separated)
337
- --skip <ids> Skip these check IDs/selectors (comma-separated)
338
- --format <fmt> text (default) | json
313
+ # Asset checks only — image DPI / format / color space, fonts
314
+ # (what `gutterpress audit <dir>` used to run)
315
+ gutterpress validate my-book --category asset --phase pre
339
316
  ```
340
317
 
341
318
  ### `gutterpress preflight`
@@ -398,9 +375,9 @@ Add an extension. What `SOURCE` is decides what happens:
398
375
 
399
376
  - an **npm package** (`name` or `name@version`) is downloaded straight from
400
377
  the registry along with its runtime dependencies, hash-verified, vendored
401
- into the project under `plugins/npm/` with a receipt, load-tested, and
402
- written back pinned as `name@<exact version>`. This does not invoke npm,
403
- Bun, Node.js tooling, or package install scripts;
378
+ into the project under `plugins/npm/`, load-tested, and written back pinned
379
+ as `name@<exact version>`. This does not invoke npm, Bun, Node.js tooling,
380
+ or package install scripts;
404
381
  - a **bundled feature** (`markdown-it-mark`, `markdown-it-sub`,
405
382
  `markdown-it-sup`, `markdown-it-abbr`, `gutterpress-gfm-alerts`) is simply
406
383
  listed — nothing to install, works offline;
@@ -488,11 +465,11 @@ Every command follows the same exit-code contract, so CI can branch on the resul
488
465
  | Code | Meaning |
489
466
  |---|---|
490
467
  | `0` | Clean — no findings, nothing to fix. |
491
- | `1` | Findings — the command ran fine but reported findings/validation failures (`lint` CSS errors, `validate`/`preflight`/`audit` findings, a `build` quality-gate rejection). |
468
+ | `1` | Findings — the command ran fine but reported findings/validation failures (`validate`/`preflight` findings, a `build` quality-gate rejection). |
492
469
  | `2` | Usage — the invocation itself was wrong: a bad flag, positional argument, preset, or value. |
493
470
  | `3` | Pipeline — the build/render/export pipeline itself failed for a reason unrelated to usage or findings (I/O error, missing tool, renderer crash). |
494
471
 
495
- This applies uniformly across `build`, `preview`, `lint`, `validate`, `preflight`, `audit`, `publish`, `ext`, `new`, and `doctor`.
472
+ This applies uniformly across `build`, `preview`, `validate`, `preflight`, `publish`, `ext`, `new`, and `doctor`.
496
473
 
497
474
  ## Extensions
498
475
 
@@ -539,13 +516,14 @@ An extension folder (or npm package) describes itself in its **`package.json`**
539
516
 
540
517
  Order is load order: a later entry's markdown runs after earlier entries' (and sees their output) and its CSS wins ties — each extension's stylesheets are wrapped in their own cascade layer (`@layer ext.<name>`), declared in list order, so this holds however an extension writes its CSS; the project's own `styles:` stay unlayered and load after every extension, beating all of them at any specificity. There is no `priority` and no `path:`/`name:` wrapper — a manifest still carrying `plugins:` fails with a message that prints the same entries rewritten as `extensions:`. The `engine:` and `engineStyles:` keys are gone too (there is one engine; move any `engineStyles` entries to the end of `styles:`).
541
518
 
542
- Pinned npm packages and their runtime dependencies live under `plugins/npm/`,
543
- with a receipt that records the exact graph and hashes the complete tree. They
544
- travel with the project and builds never fetch from the registry. Install/build
545
- scripts, native addon compilation, bundled `node_modules`, and non-registry
546
- dependency selectors are intentionally unsupported. Only install packages you
547
- trust: extensions run unsandboxed with the process's full filesystem and network
548
- privileges.
519
+ Pinned npm packages and their runtime dependencies live under `plugins/npm/`
520
+ as a plain nested `node_modules` tree, which Node's own module resolution loads.
521
+ They travel with the project and builds never fetch from the registry; each
522
+ tarball's integrity is checked against the registry's hash when it is
523
+ installed. Install/build scripts, native addon compilation, bundled
524
+ `node_modules`, and non-registry dependency selectors are intentionally
525
+ unsupported. Only install packages you trust: extensions run unsandboxed with
526
+ the process's full filesystem and network privileges.
549
527
 
550
528
  Use the entry's `export` field, or `ext add --export <name>`, for packages
551
529
  that expose a named plugin function instead of a default export.
@@ -11,7 +11,7 @@
11
11
  * await runBuild({ inputDir: "./book", format: "pdf", outDir: "./out", rawArgs: {} });
12
12
  */
13
13
  export { runBuild, splitOutPath, BuildError, type BuildFormat, type PdfxFlavor, type BuildRunnerOptions, type BuildRunnerResult, type SplitOutPath, type EngineBrowser, type EngineSession, } from "../lib/build-runner";
14
- export { DEFAULT_PRINT_OPTS, readyProbeExpr } from "../engine/shared/cdp";
14
+ export { DEFAULT_PRINT_OPTS, readyProbeExpr, assertMilestone } from "../engine/shared/cdp";
15
15
  export { startPreviewServer, type PreviewServerHandle, type StartPreviewServerOptions, } from "../server";
16
16
  export type { PreviewServerOptions } from "../types";
17
17
  export { loadManifestWithPath, resolveConfig, MANIFEST_FILENAMES, hasProjectManifest, } from "../lib/manifest";
package/dist/api/index.js CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  BUILT_IN_STYLE_SET_IDS,
8
8
  BUILT_IN_TEMPLATE_IDS,
9
9
  BUNDLED_EXTENSIONS,
10
+ DEFAULT_NPM_REGISTRY,
10
11
  EXTENSIONS_DIR,
11
12
  EXTENSION_KINDS,
12
13
  EXTENSION_MANIFEST_FILENAME,
@@ -75,6 +76,7 @@ import {
75
76
  listRepoBooks,
76
77
  listSnippets,
77
78
  loadManifestWithPath,
79
+ npmRegistryUrl,
78
80
  parseExtensionSpecifier,
79
81
  parseRemoteOrigin,
80
82
  pathEscapesFolder,
@@ -125,15 +127,17 @@ import {
125
127
  syncProject,
126
128
  testRemoteAccess,
127
129
  validateProjectExtensions
128
- } from "../index-1a4rx87v.js";
130
+ } from "../index-322fxk25.js";
131
+ import {
132
+ BuildError
133
+ } from "../index-r4wvy5v3.js";
129
134
  import {
130
- BuildError,
131
135
  DEFAULT_PRINT_OPTS,
136
+ assertMilestone,
132
137
  readyProbeExpr
133
- } from "../index-t43k5rq1.js";
138
+ } from "../index-rzm1phg0.js";
134
139
  import {
135
140
  AUTO_SNAPSHOT_MESSAGE,
136
- DEFAULT_NPM_REGISTRY,
137
141
  HISTORY_PAGE_LIMIT,
138
142
  PLUGINS_DIR,
139
143
  RESTORE_BACKUP_MESSAGE,
@@ -141,13 +145,12 @@ import {
141
145
  countUnversionedChanges,
142
146
  isNoChangesError,
143
147
  listLocalBranches,
144
- npmRegistryUrl,
145
148
  providerFor,
146
149
  resolveLogger,
147
150
  restoreVersionWithBackup,
148
151
  switchBranch,
149
152
  whenGitIdle
150
- } from "../index-fnhak0nh.js";
153
+ } from "../index-qf7y4d85.js";
151
154
  import {
152
155
  capabilitiesFor,
153
156
  detectProjectSource,
@@ -264,6 +267,7 @@ export {
264
267
  capabilitiesFor,
265
268
  autoSyncDelayMs,
266
269
  autoSnapshotDelayMs,
270
+ assertMilestone,
267
271
  assertExtensionContained,
268
272
  adoptFolder,
269
273
  addExtension,
@@ -1,23 +1,24 @@
1
1
  import {
2
2
  runBuild,
3
3
  splitOutPath
4
- } from "./cli-4xksazfr.js";
4
+ } from "./cli-z8ye91f0.js";
5
5
  import {
6
6
  log
7
- } from "./cli-p679pvce.js";
7
+ } from "./cli-vbzkkcbv.js";
8
8
  import {
9
9
  UsageError,
10
10
  parseFormat,
11
11
  parsePdfxFlavor,
12
12
  rejectExtraPositionals,
13
13
  rejectUnknownFlags
14
- } from "./cli-k2hwrp7s.js";
15
- import"./cli-d8rdk1y7.js";
16
- import"./cli-c41yr7he.js";
14
+ } from "./cli-97bdz5k0.js";
15
+ import"./cli-30j93gzt.js";
17
16
  import {
18
17
  BuildError
19
18
  } from "./cli-46ycxe6r.js";
20
- import"./cli-pfczdbyd.js";
19
+ import"./cli-kkzka31p.js";
20
+ import"./cli-7fkhgtfn.js";
21
+ import"./cli-5qr3z0qa.js";
21
22
  import"./cli-v5mp7a6q.js";
22
23
  import"./cli-37x76zdn.js";
23
24
 
@@ -0,0 +1,15 @@
1
+ import {
2
+ DEFAULT_PRINT_OPTS,
3
+ REQUIRED_MILESTONE,
4
+ assertMilestone,
5
+ launchChromium,
6
+ readyProbeExpr
7
+ } from "./index-rzm1phg0.js";
8
+ import"./index-37x76zdn.js";
9
+ export {
10
+ readyProbeExpr,
11
+ launchChromium,
12
+ assertMilestone,
13
+ REQUIRED_MILESTONE,
14
+ DEFAULT_PRINT_OPTS
15
+ };
@@ -0,0 +1,16 @@
1
+ import {
2
+ DEFAULT_PRINT_OPTS,
3
+ REQUIRED_MILESTONE,
4
+ assertMilestone,
5
+ launchChromium,
6
+ readyProbeExpr
7
+ } from "./cli-kkzka31p.js";
8
+ import"./cli-7fkhgtfn.js";
9
+ import"./cli-37x76zdn.js";
10
+ export {
11
+ readyProbeExpr,
12
+ launchChromium,
13
+ assertMilestone,
14
+ REQUIRED_MILESTONE,
15
+ DEFAULT_PRINT_OPTS
16
+ };
@@ -1,330 +1,6 @@
1
1
  import {
2
- requireChromiumExecutable
3
- } from "./cli-c41yr7he.js";
4
- import {
5
- __require
6
- } from "./cli-37x76zdn.js";
7
-
8
- // src/lib/browser-pool.ts
9
- var RENDER_TIMEOUT_MS = 60 * 60 * 1000;
10
- var browserPromise = null;
11
- async function launchBrowser(timeoutMs) {
12
- const executablePath = await requireChromiumExecutable();
13
- const puppeteer = (await import("puppeteer-core")).default;
14
- const extraChromiumArgs = (process.env.GUTTERPRESS_CHROMIUM_ARGS ?? "").split(/\s+/).filter(Boolean);
15
- return puppeteer.launch({
16
- headless: true,
17
- executablePath,
18
- args: extraChromiumArgs,
19
- protocolTimeout: timeoutMs
20
- });
21
- }
22
- function prewarmBrowser(timeoutMs) {
23
- if (browserPromise)
24
- return;
25
- const p = launchBrowser(timeoutMs);
26
- browserPromise = p;
27
- p.then((browser) => {
28
- browser.on("disconnected", () => {
29
- if (browserPromise === p)
30
- browserPromise = null;
31
- });
32
- }).catch(() => {
33
- if (browserPromise === p)
34
- browserPromise = null;
35
- });
36
- }
37
- async function getBrowser(timeoutMs) {
38
- if (!browserPromise)
39
- prewarmBrowser(timeoutMs);
40
- return browserPromise;
41
- }
42
- async function closeBrowser() {
43
- const p = browserPromise;
44
- browserPromise = null;
45
- if (!p)
46
- return;
47
- try {
48
- const b = await p;
49
- await b.close();
50
- } catch {}
51
- }
52
-
53
- // src/engine/shared/cdp.ts
54
- import { spawn } from "node:child_process";
55
- import { existsSync, mkdtempSync, rmSync } from "node:fs";
56
- import { tmpdir } from "node:os";
57
- import { join } from "node:path";
58
- import WebSocket from "ws";
59
- var CANDIDATES = [
60
- process.env.GUTTERPRESS_CHROMIUM,
61
- process.env.PUPPETEER_EXECUTABLE_PATH,
62
- "/opt/pw-browsers/chromium",
63
- "/usr/bin/chromium",
64
- "/usr/bin/chromium-browser",
65
- "/usr/bin/google-chrome",
66
- "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
67
- ].filter(Boolean);
68
- function findChromium() {
69
- for (const c of CANDIDATES)
70
- if (existsSync(c))
71
- return c;
72
- throw new Error(`No Chromium found. Set GUTTERPRESS_CHROMIUM. Looked in:
73
- ${CANDIDATES.join(`
74
- `)}`);
75
- }
76
- var REQUIRED_MILESTONE = 148;
77
- function assertMilestone(product, origin, hint = "") {
78
- const milestone = Number(/Chrome\/(\d+)/.exec(product)?.[1] ?? 0);
79
- if (milestone < REQUIRED_MILESTONE) {
80
- throw new Error(`The Gutterpress engine requires Chromium ${REQUIRED_MILESTONE}+; found ${product} ${origin}.` + (hint ? `
81
- ${hint}` : ""));
82
- }
83
- }
84
- function readyProbeExpr(timeoutMs) {
85
- return `(async () => {
86
- await document.fonts.ready;
87
- if (window.__gpReadyPending) {
88
- await new Promise((res) => {
89
- const t = setTimeout(res, ${timeoutMs});
90
- document.addEventListener('gp:ready', () => { clearTimeout(t); res(); }, { once: true });
91
- });
92
- }
93
- // two rAFs: let layout settle after fonts swap
94
- await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r)));
95
- return true;
96
- })()`;
97
- }
98
- var DEFAULT_PRINT_OPTS = {
99
- printBackground: true,
100
- preferCSSPageSize: true,
101
- generateTaggedPDF: true,
102
- generateDocumentOutline: true
103
- };
104
- async function launchChromium(opts = {}) {
105
- const bin = findChromium();
106
- const userDataDir = mkdtempSync(join(tmpdir(), "gp-cdp-"));
107
- const args = [
108
- "--remote-debugging-port=0",
109
- `--user-data-dir=${userDataDir}`,
110
- "--no-first-run",
111
- "--no-default-browser-check",
112
- "--disable-gpu",
113
- "--no-sandbox",
114
- "--hide-scrollbars",
115
- "--allow-file-access-from-files",
116
- "--font-render-hinting=none",
117
- ...opts.headless === false ? [] : ["--headless=new"],
118
- ...opts.args ?? [],
119
- "about:blank"
120
- ];
121
- const proc = spawn(bin, args, { stdio: ["ignore", "pipe", "pipe"] });
122
- const wsUrl = await readDevToolsUrl(proc);
123
- const conn = await Connection.open(wsUrl);
124
- const teardown = async () => {
125
- const exited = new Promise((r) => proc.once("exit", () => r()));
126
- try {
127
- await Promise.race([
128
- conn.send("Browser.close").then(() => exited),
129
- new Promise((_, rej) => setTimeout(() => rej(new Error("Browser.close timed out")), 5000))
130
- ]);
131
- } catch {
132
- proc.kill("SIGKILL");
133
- await exited;
134
- }
135
- conn.close();
136
- rmSync(userDataDir, { recursive: true, force: true });
137
- };
138
- return checkMilestoneAndWrap(conn, wsUrl, `at ${bin}`, teardown);
139
- }
140
- async function connectChromium(wsUrl) {
141
- const conn = await Connection.open(wsUrl);
142
- return checkMilestoneAndWrap(conn, wsUrl, "via connected browser", async () => {
143
- conn.close();
144
- }, `Set CHROMIUM_PATH (or PUPPETEER_EXECUTABLE_PATH) to a ${REQUIRED_MILESTONE}+ binary.`);
145
- }
146
- async function checkMilestoneAndWrap(conn, wsUrl, origin, teardown, overrideHint = `Set GUTTERPRESS_CHROMIUM to a ${REQUIRED_MILESTONE}+ binary.`) {
147
- const version = await conn.send("Browser.getVersion", {});
148
- try {
149
- assertMilestone(version.product, origin, overrideHint);
150
- } catch (e) {
151
- await teardown();
152
- throw e;
153
- }
154
- const milestone = Number(/Chrome\/(\d+)/.exec(version.product)?.[1] ?? 0);
155
- return {
156
- wsUrl,
157
- version: version.product,
158
- milestone,
159
- async newPage() {
160
- const { targetId } = await conn.send("Target.createTarget", { url: "about:blank" });
161
- const { sessionId } = await conn.send("Target.attachToTarget", { targetId, flatten: true });
162
- const s = new SessionImpl(conn, sessionId, targetId);
163
- await s.send("Page.enable");
164
- await s.send("Runtime.enable");
165
- return s;
166
- },
167
- close: teardown
168
- };
169
- }
170
- function readDevToolsUrl(proc) {
171
- return new Promise((resolve, reject) => {
172
- let buf = "";
173
- const timer = setTimeout(() => reject(new Error(`Chromium did not report a DevTools URL:
174
- ${buf}`)), 60000);
175
- proc.stderr.on("data", (d) => {
176
- buf += String(d);
177
- const m = /ws:\/\/[^\s]+/.exec(buf);
178
- if (m) {
179
- clearTimeout(timer);
180
- resolve(m[0]);
181
- }
182
- });
183
- proc.once("exit", (code) => {
184
- clearTimeout(timer);
185
- reject(new Error(`Chromium exited (${code}) before listening:
186
- ${buf}`));
187
- });
188
- });
189
- }
190
-
191
- class Connection {
192
- ws;
193
- id = 0;
194
- pending = new Map;
195
- listeners = new Map;
196
- constructor(ws) {
197
- this.ws = ws;
198
- ws.on("message", (raw) => this.dispatch(JSON.parse(String(raw))));
199
- }
200
- static async open(url) {
201
- const ws = new WebSocket(url, { maxPayload: 512 * 1024 * 1024 });
202
- await new Promise((res, rej) => {
203
- ws.once("open", () => res());
204
- ws.once("error", rej);
205
- });
206
- return new Connection(ws);
207
- }
208
- dispatch(msg) {
209
- if (msg.id !== undefined) {
210
- const p = this.pending.get(msg.id);
211
- if (!p)
212
- return;
213
- this.pending.delete(msg.id);
214
- if (msg.error)
215
- p.reject(new Error(`${msg.error.message} (${msg.error.code})`));
216
- else
217
- p.resolve(msg.result);
218
- return;
219
- }
220
- const key = msg.sessionId ? `${msg.sessionId}:${msg.method}` : msg.method;
221
- for (const fn of this.listeners.get(key) ?? [])
222
- fn(msg.params);
223
- for (const fn of this.listeners.get(msg.method) ?? [])
224
- fn(msg.params);
225
- }
226
- send(method, params = {}, sessionId) {
227
- const id = ++this.id;
228
- const payload = { id, method, params };
229
- if (sessionId)
230
- payload.sessionId = sessionId;
231
- return new Promise((resolve, reject) => {
232
- this.pending.set(id, { resolve, reject });
233
- this.ws.send(JSON.stringify(payload));
234
- });
235
- }
236
- on(key, fn) {
237
- let set = this.listeners.get(key);
238
- if (!set)
239
- this.listeners.set(key, set = new Set);
240
- set.add(fn);
241
- return () => set.delete(fn);
242
- }
243
- close() {
244
- this.ws.close();
245
- }
246
- }
247
-
248
- class SessionImpl {
249
- conn;
250
- sessionId;
251
- targetId;
252
- constructor(conn, sessionId, targetId) {
253
- this.conn = conn;
254
- this.sessionId = sessionId;
255
- this.targetId = targetId;
256
- }
257
- send(method, params = {}) {
258
- return this.conn.send(method, params, this.sessionId);
259
- }
260
- on(event, fn) {
261
- return this.conn.on(`${this.sessionId}:${event}`, fn);
262
- }
263
- async evaluate(expression) {
264
- const res = await this.send("Runtime.evaluate", {
265
- expression,
266
- returnByValue: true,
267
- awaitPromise: true
268
- });
269
- if (res.exceptionDetails) {
270
- const e = res.exceptionDetails;
271
- throw new Error(`evaluate failed: ${e.exception?.description ?? e.text}`);
272
- }
273
- return res.result.value;
274
- }
275
- async waitForLoad(fn) {
276
- const done = new Promise((resolve) => {
277
- const off = this.on("Page.loadEventFired", () => {
278
- off();
279
- resolve();
280
- });
281
- });
282
- await fn();
283
- await done;
284
- }
285
- async setContent(html, baseUrl = "http://gutterpress.spike/") {
286
- await this.waitForLoad(async () => {
287
- const { frameTree } = await this.send("Page.getFrameTree");
288
- await this.send("Page.setDocumentContent", {
289
- frameId: frameTree.frame.id,
290
- html
291
- });
292
- });
293
- }
294
- async navigate(url) {
295
- await this.waitForLoad(async () => {
296
- await this.send("Page.navigate", { url });
297
- });
298
- }
299
- async waitForReady(timeoutMs = 15000) {
300
- await this.evaluate(readyProbeExpr(timeoutMs));
301
- }
302
- async printToPDF(opts = {}) {
303
- const res = await this.send("Page.printToPDF", {
304
- ...DEFAULT_PRINT_OPTS,
305
- transferMode: "ReturnAsStream",
306
- ...opts
307
- });
308
- if (!res.stream)
309
- return Uint8Array.from(Buffer.from(res.data, "base64"));
310
- const chunks = [];
311
- try {
312
- for (;; ) {
313
- const c = await this.send("IO.read", { handle: res.stream, size: 8 * 1024 * 1024 });
314
- if (c.data)
315
- chunks.push(Buffer.from(c.data, c.base64Encoded ? "base64" : "binary"));
316
- if (c.eof)
317
- break;
318
- }
319
- } finally {
320
- await this.send("IO.close", { handle: res.stream }).catch(() => {});
321
- }
322
- return new Uint8Array(Buffer.concat(chunks));
323
- }
324
- async close() {
325
- await this.conn.send("Target.closeTarget", { targetId: this.targetId });
326
- }
327
- }
2
+ launchChromium
3
+ } from "./cli-kkzka31p.js";
328
4
 
329
5
  // src/engine/compiler/build.ts
330
6
  import { readFile as readFile2 } from "node:fs/promises";
@@ -1420,10 +1096,10 @@ async function inspectPdf(bytes) {
1420
1096
  }
1421
1097
 
1422
1098
  // src/lib/embedded-assets.ts
1423
- import { existsSync as existsSync2 } from "node:fs";
1099
+ import { existsSync } from "node:fs";
1424
1100
  import { mkdtemp, mkdir, writeFile, readFile } from "node:fs/promises";
1425
- import { tmpdir as tmpdir2 } from "node:os";
1426
- import { dirname, join as join2, resolve } from "node:path";
1101
+ import { tmpdir } from "node:os";
1102
+ import { dirname, join, resolve } from "node:path";
1427
1103
  import { fileURLToPath } from "node:url";
1428
1104
 
1429
1105
  // src/assets/favicon.ico
@@ -1439,7 +1115,7 @@ var preview_interface_default = "./preview-interface-9rwz21yw.js";
1439
1115
  var preview_bridge_default = "./preview-bridge-b4jbtb79.js";
1440
1116
 
1441
1117
  // src/assets/preview/scripts/preview-shell.js
1442
- var preview_shell_default = "./preview-shell-gqnc5xxe.js";
1118
+ var preview_shell_default = "./preview-shell-tqndvhbx.js";
1443
1119
 
1444
1120
  // profiles/CGATS21_CRPC1.icc
1445
1121
  var CGATS21_CRPC1_default = "./CGATS21_CRPC1-g0e3k7kr.icc";
@@ -1586,9 +1262,9 @@ var EMBEDDED_ASSETS = {
1586
1262
  };
1587
1263
  var extractPromise = null;
1588
1264
  async function extractAssets() {
1589
- const root = await mkdtemp(join2(tmpdir2(), "gutterpress-assets-"));
1265
+ const root = await mkdtemp(join(tmpdir(), "gutterpress-assets-"));
1590
1266
  for (const [relPath, srcPath] of Object.entries(EMBEDDED_ASSETS)) {
1591
- const dest = join2(root, relPath);
1267
+ const dest = join(root, relPath);
1592
1268
  await mkdir(dirname(dest), { recursive: true });
1593
1269
  const bytes = await readFile(srcPath);
1594
1270
  await writeFile(dest, bytes);
@@ -1600,7 +1276,7 @@ async function getAssetsDir() {
1600
1276
  if (extractPromise) {
1601
1277
  try {
1602
1278
  const root = await extractPromise;
1603
- if (existsSync2(join2(root, SENTINEL_ASSET))) {
1279
+ if (existsSync(join(root, SENTINEL_ASSET))) {
1604
1280
  return root;
1605
1281
  }
1606
1282
  } catch {}
@@ -1611,7 +1287,7 @@ async function getAssetsDir() {
1611
1287
  }
1612
1288
  async function getAssetPath(relPath) {
1613
1289
  const root = await getAssetsDir();
1614
- return join2(root, relPath);
1290
+ return join(root, relPath);
1615
1291
  }
1616
1292
 
1617
1293
  // src/engine/compiler/tier2.ts
@@ -2921,4 +2597,4 @@ ${lines.length ? lines.join(`
2921
2597
  `);
2922
2598
  }
2923
2599
 
2924
- export { RENDER_TIMEOUT_MS, prewarmBrowser, getBrowser, closeBrowser, getAssetsDir, getAssetPath, MARGIN_BOX_IGNORED_PROPERTIES, REQUIRED_MILESTONE, assertMilestone, connectChromium, build };
2600
+ export { getAssetsDir, getAssetPath, MARGIN_BOX_IGNORED_PROPERTIES, build };