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
@@ -0,0 +1,261 @@
1
+ import {
2
+ requireChromiumExecutable
3
+ } from "./cli-7fkhgtfn.js";
4
+
5
+ // src/engine/shared/cdp.ts
6
+ import { spawn } from "node:child_process";
7
+ import { mkdtempSync, rmSync } from "node:fs";
8
+ import { tmpdir } from "node:os";
9
+ import { join } from "node:path";
10
+ import WebSocket from "ws";
11
+ var REQUIRED_MILESTONE = 148;
12
+ function assertMilestone(product, origin, hint = "") {
13
+ const milestone = Number(/Chrome\/(\d+)/.exec(product)?.[1] ?? 0);
14
+ if (milestone < REQUIRED_MILESTONE) {
15
+ throw new Error(`The Gutterpress engine requires Chromium ${REQUIRED_MILESTONE}+; found ${product} ${origin}.` + (hint ? `
16
+ ${hint}` : ""));
17
+ }
18
+ }
19
+ function readyProbeExpr(timeoutMs) {
20
+ return `(async () => {
21
+ await document.fonts.ready;
22
+ if (window.__gpReadyPending) {
23
+ await new Promise((res) => {
24
+ const t = setTimeout(res, ${timeoutMs});
25
+ document.addEventListener('gp:ready', () => { clearTimeout(t); res(); }, { once: true });
26
+ });
27
+ }
28
+ // two rAFs: let layout settle after fonts swap
29
+ await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r)));
30
+ return true;
31
+ })()`;
32
+ }
33
+ var DEFAULT_PRINT_OPTS = {
34
+ printBackground: true,
35
+ preferCSSPageSize: true,
36
+ generateTaggedPDF: true,
37
+ generateDocumentOutline: true
38
+ };
39
+ var DEFAULT_ARGS = [
40
+ "--headless=new",
41
+ "--no-first-run",
42
+ "--no-default-browser-check",
43
+ "--disable-gpu",
44
+ "--no-sandbox",
45
+ "--hide-scrollbars",
46
+ "--allow-file-access-from-files",
47
+ "--font-render-hinting=none"
48
+ ];
49
+ async function launchChromium(opts = {}) {
50
+ const bin = await requireChromiumExecutable();
51
+ const userDataDir = mkdtempSync(join(tmpdir(), "gp-cdp-"));
52
+ const envArgs = (process.env.GUTTERPRESS_CHROMIUM_ARGS ?? "").split(/\s+/).filter(Boolean);
53
+ const ignored = new Set(opts.ignoreDefaultArgs ?? []);
54
+ const args = [
55
+ "--remote-debugging-port=0",
56
+ `--user-data-dir=${userDataDir}`,
57
+ ...DEFAULT_ARGS.filter((a) => !ignored.has(a)),
58
+ ...envArgs,
59
+ ...opts.args ?? [],
60
+ "about:blank"
61
+ ];
62
+ const proc = spawn(bin, args, { stdio: ["ignore", "pipe", "pipe"] });
63
+ const wsUrl = await readDevToolsUrl(proc);
64
+ const conn = await Connection.open(wsUrl);
65
+ const teardown = async () => {
66
+ const exited = new Promise((r) => proc.once("exit", () => r()));
67
+ try {
68
+ await Promise.race([
69
+ conn.send("Browser.close").then(() => exited),
70
+ new Promise((_, rej) => setTimeout(() => rej(new Error("Browser.close timed out")), 5000))
71
+ ]);
72
+ } catch {
73
+ proc.kill("SIGKILL");
74
+ await exited;
75
+ }
76
+ conn.close();
77
+ rmSync(userDataDir, { recursive: true, force: true });
78
+ };
79
+ const version = await conn.send("Browser.getVersion", {});
80
+ try {
81
+ assertMilestone(version.product, `at ${bin}`, `Install a newer Chrome, Chromium, or Edge, or point CHROMIUM_PATH at a ${REQUIRED_MILESTONE}+ binary.`);
82
+ } catch (e) {
83
+ await teardown();
84
+ throw e;
85
+ }
86
+ const milestone = Number(/Chrome\/(\d+)/.exec(version.product)?.[1] ?? 0);
87
+ return {
88
+ wsUrl,
89
+ version: version.product,
90
+ milestone,
91
+ async newPage() {
92
+ const { targetId } = await conn.send("Target.createTarget", { url: "about:blank" });
93
+ const { sessionId } = await conn.send("Target.attachToTarget", { targetId, flatten: true });
94
+ const s = new SessionImpl(conn, sessionId, targetId);
95
+ await s.send("Page.enable");
96
+ await s.send("Runtime.enable");
97
+ return s;
98
+ },
99
+ close: teardown
100
+ };
101
+ }
102
+ function readDevToolsUrl(proc) {
103
+ return new Promise((resolve, reject) => {
104
+ let buf = "";
105
+ const timer = setTimeout(() => reject(new Error(`Chromium did not report a DevTools URL:
106
+ ${buf}`)), 60000);
107
+ proc.stderr.on("data", (d) => {
108
+ buf += String(d);
109
+ const m = /ws:\/\/[^\s]+/.exec(buf);
110
+ if (m) {
111
+ clearTimeout(timer);
112
+ resolve(m[0]);
113
+ }
114
+ });
115
+ proc.once("exit", (code) => {
116
+ clearTimeout(timer);
117
+ reject(new Error(`Chromium exited (${code}) before listening:
118
+ ${buf}`));
119
+ });
120
+ });
121
+ }
122
+
123
+ class Connection {
124
+ ws;
125
+ id = 0;
126
+ pending = new Map;
127
+ listeners = new Map;
128
+ constructor(ws) {
129
+ this.ws = ws;
130
+ ws.on("message", (raw) => this.dispatch(JSON.parse(String(raw))));
131
+ }
132
+ static async open(url) {
133
+ const ws = new WebSocket(url, { maxPayload: 512 * 1024 * 1024 });
134
+ await new Promise((res, rej) => {
135
+ ws.once("open", () => res());
136
+ ws.once("error", rej);
137
+ });
138
+ return new Connection(ws);
139
+ }
140
+ dispatch(msg) {
141
+ if (msg.id !== undefined) {
142
+ const p = this.pending.get(msg.id);
143
+ if (!p)
144
+ return;
145
+ this.pending.delete(msg.id);
146
+ if (msg.error)
147
+ p.reject(new Error(`${msg.error.message} (${msg.error.code})`));
148
+ else
149
+ p.resolve(msg.result);
150
+ return;
151
+ }
152
+ const key = msg.sessionId ? `${msg.sessionId}:${msg.method}` : msg.method;
153
+ for (const fn of this.listeners.get(key) ?? [])
154
+ fn(msg.params);
155
+ for (const fn of this.listeners.get(msg.method) ?? [])
156
+ fn(msg.params);
157
+ }
158
+ send(method, params = {}, sessionId) {
159
+ const id = ++this.id;
160
+ const payload = { id, method, params };
161
+ if (sessionId)
162
+ payload.sessionId = sessionId;
163
+ return new Promise((resolve, reject) => {
164
+ this.pending.set(id, { resolve, reject });
165
+ this.ws.send(JSON.stringify(payload));
166
+ });
167
+ }
168
+ on(key, fn) {
169
+ let set = this.listeners.get(key);
170
+ if (!set)
171
+ this.listeners.set(key, set = new Set);
172
+ set.add(fn);
173
+ return () => set.delete(fn);
174
+ }
175
+ close() {
176
+ this.ws.close();
177
+ }
178
+ }
179
+
180
+ class SessionImpl {
181
+ conn;
182
+ sessionId;
183
+ targetId;
184
+ constructor(conn, sessionId, targetId) {
185
+ this.conn = conn;
186
+ this.sessionId = sessionId;
187
+ this.targetId = targetId;
188
+ }
189
+ send(method, params = {}) {
190
+ return this.conn.send(method, params, this.sessionId);
191
+ }
192
+ on(event, fn) {
193
+ return this.conn.on(`${this.sessionId}:${event}`, fn);
194
+ }
195
+ async evaluate(expression) {
196
+ const res = await this.send("Runtime.evaluate", {
197
+ expression,
198
+ returnByValue: true,
199
+ awaitPromise: true
200
+ });
201
+ if (res.exceptionDetails) {
202
+ const e = res.exceptionDetails;
203
+ throw new Error(`evaluate failed: ${e.exception?.description ?? e.text}`);
204
+ }
205
+ return res.result.value;
206
+ }
207
+ async waitForLoad(fn) {
208
+ const done = new Promise((resolve) => {
209
+ const off = this.on("Page.loadEventFired", () => {
210
+ off();
211
+ resolve();
212
+ });
213
+ });
214
+ await fn();
215
+ await done;
216
+ }
217
+ async setContent(html, baseUrl = "http://gutterpress.spike/") {
218
+ await this.waitForLoad(async () => {
219
+ const { frameTree } = await this.send("Page.getFrameTree");
220
+ await this.send("Page.setDocumentContent", {
221
+ frameId: frameTree.frame.id,
222
+ html
223
+ });
224
+ });
225
+ }
226
+ async navigate(url) {
227
+ await this.waitForLoad(async () => {
228
+ await this.send("Page.navigate", { url });
229
+ });
230
+ }
231
+ async waitForReady(timeoutMs = 15000) {
232
+ await this.evaluate(readyProbeExpr(timeoutMs));
233
+ }
234
+ async printToPDF(opts = {}) {
235
+ const res = await this.send("Page.printToPDF", {
236
+ ...DEFAULT_PRINT_OPTS,
237
+ transferMode: "ReturnAsStream",
238
+ ...opts
239
+ });
240
+ if (!res.stream)
241
+ return Uint8Array.from(Buffer.from(res.data, "base64"));
242
+ const chunks = [];
243
+ try {
244
+ for (;; ) {
245
+ const c = await this.send("IO.read", { handle: res.stream, size: 8 * 1024 * 1024 });
246
+ if (c.data)
247
+ chunks.push(Buffer.from(c.data, c.base64Encoded ? "base64" : "binary"));
248
+ if (c.eof)
249
+ break;
250
+ }
251
+ } finally {
252
+ await this.send("IO.close", { handle: res.stream }).catch(() => {});
253
+ }
254
+ return new Uint8Array(Buffer.concat(chunks));
255
+ }
256
+ async close() {
257
+ await this.conn.send("Target.closeTarget", { targetId: this.targetId });
258
+ }
259
+ }
260
+
261
+ export { REQUIRED_MILESTONE, assertMilestone, readyProbeExpr, DEFAULT_PRINT_OPTS, launchChromium };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  package_default
3
- } from "./cli-k2hwrp7s.js";
3
+ } from "./cli-97bdz5k0.js";
4
4
  import {
5
5
  execCapture,
6
6
  findTool,
@@ -8,7 +8,7 @@ import {
8
8
  isToolAvailable,
9
9
  resolveChromiumExecutable,
10
10
  run
11
- } from "./cli-c41yr7he.js";
11
+ } from "./cli-7fkhgtfn.js";
12
12
  import {
13
13
  __require
14
14
  } from "./cli-37x76zdn.js";