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.
- package/README.md +24 -46
- package/dist/api/index.d.ts +1 -1
- package/dist/api/index.js +10 -6
- package/dist/{build-dfpvvhys.js → build-npxq1tvm.js} +7 -6
- package/dist/cdp-jg95s674.js +15 -0
- package/dist/cdp-smdx6mr3.js +16 -0
- package/dist/{cli-d8rdk1y7.js → cli-30j93gzt.js} +11 -335
- package/dist/{cli-pfczdbyd.js → cli-5qr3z0qa.js} +10 -404
- package/dist/{cli-c41yr7he.js → cli-7fkhgtfn.js} +3 -1
- package/dist/{cli-k2hwrp7s.js → cli-97bdz5k0.js} +1 -4
- package/dist/cli-kkzka31p.js +261 -0
- package/dist/{cli-p679pvce.js → cli-vbzkkcbv.js} +2 -2
- package/dist/{cli-4xksazfr.js → cli-z8ye91f0.js} +283 -1142
- package/dist/cli.js +12 -14
- package/dist/{doctor-hheax5yc.js → doctor-ykr6gtpv.js} +3 -3
- package/dist/engine/shared/cdp.d.ts +23 -19
- package/dist/engine-3gwctsty.js +24 -0
- package/dist/engine-mwshptgf.js +25 -0
- package/dist/{ext-q5024j6v.js → ext-bna9nr3v.js} +7 -6
- package/dist/{index-1a4rx87v.js → index-322fxk25.js} +344 -1130
- package/dist/{index-kqftehgy.js → index-dzp0hc2c.js} +4 -2
- package/dist/{index-fnhak0nh.js → index-qf7y4d85.js} +10 -404
- package/dist/index-r4wvy5v3.js +267 -0
- package/dist/{index-t43k5rq1.js → index-rzm1phg0.js} +23 -356
- package/dist/index.d.ts +0 -1
- package/dist/index.js +12 -87
- package/dist/lib/build-error.d.ts +4 -5
- package/dist/lib/build-preflight.d.ts +1 -35
- package/dist/lib/build-runner.d.ts +27 -44
- package/dist/lib/chromium.d.ts +5 -1
- package/dist/lib/engine.d.ts +3 -18
- package/dist/lib/extension-manager.d.ts +2 -2
- package/dist/lib/extension-manifest.d.ts +1 -1
- package/dist/lib/markdown/assemble.d.ts +2 -9
- package/dist/lib/markdown/index.d.ts +2 -4
- package/dist/lib/markdown/plugins.d.ts +0 -3
- package/dist/lib/npm-plugin-installer.d.ts +6 -1
- package/dist/lib/plugin-vendor.d.ts +10 -78
- package/dist/lib/source-provider.d.ts +1 -1
- package/dist/lib/validation-exec.d.ts +5 -6
- package/dist/{new-6xm4tdxb.js → new-0hv3nwqj.js} +9 -8
- package/dist/{preflight-ezt8rvg3.js → preflight-pk0k25fm.js} +7 -6
- package/dist/preview/file-watcher.d.ts +4 -43
- package/dist/preview/http-server.d.ts +1 -3
- package/dist/{preview-hehs46dd.js → preview-8b1fn59h.js} +7 -6
- package/dist/{preview-shell-gqnc5xxe.js → preview-shell-tqndvhbx.js} +5 -7
- package/dist/{publish-ha505ejq.js → publish-ba5h76tz.js} +7 -6
- package/dist/render.d.ts +1 -1
- package/dist/render.js +1 -9
- package/dist/{source-provider-ta09wegv.js → source-provider-pzmz0br9.js} +1 -1
- package/dist/{source-provider-7c2ww3bz.js → source-provider-qbthnmqw.js} +1 -1
- package/dist/{validate-je56vdbj.js → validate-4rq2r5b3.js} +7 -6
- package/package.json +1 -4
- package/dist/audit-v9594a72.js +0 -69
- package/dist/engine-qtfrfbpk.js +0 -41
- package/dist/engine-trte2tg2.js +0 -40
- package/dist/lib/browser-pool.d.ts +0 -35
- package/dist/lib/lint-runner.d.ts +0 -29
- 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
|
|
137
|
-
primary author commands; `
|
|
138
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
335
|
-
|
|
336
|
-
|
|
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
|
|
402
|
-
|
|
403
|
-
|
|
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 (`
|
|
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`, `
|
|
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
|
-
|
|
544
|
-
travel with the project and builds never fetch from the registry
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
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.
|
package/dist/api/index.d.ts
CHANGED
|
@@ -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-
|
|
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-
|
|
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-
|
|
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-
|
|
4
|
+
} from "./cli-z8ye91f0.js";
|
|
5
5
|
import {
|
|
6
6
|
log
|
|
7
|
-
} from "./cli-
|
|
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-
|
|
15
|
-
import"./cli-
|
|
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-
|
|
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
|
-
|
|
3
|
-
} from "./cli-
|
|
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
|
|
1099
|
+
import { existsSync } from "node:fs";
|
|
1424
1100
|
import { mkdtemp, mkdir, writeFile, readFile } from "node:fs/promises";
|
|
1425
|
-
import { tmpdir
|
|
1426
|
-
import { dirname, join
|
|
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-
|
|
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(
|
|
1265
|
+
const root = await mkdtemp(join(tmpdir(), "gutterpress-assets-"));
|
|
1590
1266
|
for (const [relPath, srcPath] of Object.entries(EMBEDDED_ASSETS)) {
|
|
1591
|
-
const dest =
|
|
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 (
|
|
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
|
|
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 {
|
|
2600
|
+
export { getAssetsDir, getAssetPath, MARGIN_BOX_IGNORED_PROPERTIES, build };
|