@elaraai/e3-ui-cli 1.0.28
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/CLA.md +26 -0
- package/CONTRIBUTING.md +28 -0
- package/LICENSE.md +31 -0
- package/README.md +158 -0
- package/bin/e3-ui.mjs +13 -0
- package/dist/app/assets/dm-sans-latin-ext-wght-normal-BOFOeGcA.woff2 +0 -0
- package/dist/app/assets/dm-sans-latin-wght-normal-Xz1IZZA0.woff2 +0 -0
- package/dist/app/assets/engine-Daqj4eDD-BQb68g_1.js +4 -0
- package/dist/app/assets/index-30g1JIHt.js +2255 -0
- package/dist/app/assets/index-CYR-0Grb.css +1 -0
- package/dist/app/assets/inter-tight-cyrillic-ext-wght-normal-okcGN4Nq.woff2 +0 -0
- package/dist/app/assets/inter-tight-cyrillic-wght-normal-BS41q_Tv.woff2 +0 -0
- package/dist/app/assets/inter-tight-greek-ext-wght-normal-DQgQPNk4.woff2 +0 -0
- package/dist/app/assets/inter-tight-greek-wght-normal-sS1B39LI.woff2 +0 -0
- package/dist/app/assets/inter-tight-latin-ext-wght-normal-B4u9PlvR.woff2 +0 -0
- package/dist/app/assets/inter-tight-latin-wght-normal-DX-nOvPD.woff2 +0 -0
- package/dist/app/assets/inter-tight-vietnamese-wght-normal-TKKdAiBA.woff2 +0 -0
- package/dist/app/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/dist/app/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/dist/app/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/dist/app/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/dist/app/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- package/dist/app/index.html +13 -0
- package/dist/browser.d.ts +88 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +249 -0
- package/dist/browser.js.map +1 -0
- package/dist/capture.d.ts +80 -0
- package/dist/capture.d.ts.map +1 -0
- package/dist/capture.js +275 -0
- package/dist/capture.js.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +70 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/shot.d.ts +42 -0
- package/dist/commands/shot.d.ts.map +1 -0
- package/dist/commands/shot.js +134 -0
- package/dist/commands/shot.js.map +1 -0
- package/dist/e3-server.d.ts +21 -0
- package/dist/e3-server.d.ts.map +1 -0
- package/dist/e3-server.js +34 -0
- package/dist/e3-server.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/load-source.d.ts +21 -0
- package/dist/load-source.d.ts.map +1 -0
- package/dist/load-source.js +163 -0
- package/dist/load-source.js.map +1 -0
- package/dist/payload.d.ts +26 -0
- package/dist/payload.d.ts.map +1 -0
- package/dist/payload.js +87 -0
- package/dist/payload.js.map +1 -0
- package/dist/render.d.ts +80 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +79 -0
- package/dist/render.js.map +1 -0
- package/dist/shot-payload.d.ts +31 -0
- package/dist/shot-payload.d.ts.map +1 -0
- package/dist/shot-payload.js +6 -0
- package/dist/shot-payload.js.map +1 -0
- package/package.json +82 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@font-face{font-family:DM Sans Variable;font-style:normal;font-display:swap;font-weight:100 1000;src:url(./dm-sans-latin-ext-wght-normal-BOFOeGcA.woff2) format("woff2-variations");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:DM Sans Variable;font-style:normal;font-display:swap;font-weight:100 1000;src:url(./dm-sans-latin-wght-normal-Xz1IZZA0.woff2) format("woff2-variations");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter Tight Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./inter-tight-cyrillic-ext-wght-normal-okcGN4Nq.woff2) format("woff2-variations");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter Tight Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./inter-tight-cyrillic-wght-normal-BS41q_Tv.woff2) format("woff2-variations");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter Tight Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./inter-tight-greek-ext-wght-normal-DQgQPNk4.woff2) format("woff2-variations");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter Tight Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./inter-tight-greek-wght-normal-sS1B39LI.woff2) format("woff2-variations");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter Tight Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./inter-tight-vietnamese-wght-normal-TKKdAiBA.woff2) format("woff2-variations");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter Tight Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./inter-tight-latin-ext-wght-normal-B4u9PlvR.woff2) format("woff2-variations");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter Tight Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./inter-tight-latin-wght-normal-DX-nOvPD.woff2) format("woff2-variations");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(data:font/woff2;base64,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) format("woff2-variations");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(./jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2) format("woff2-variations");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(./jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2) format("woff2-variations");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(./jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2) format("woff2-variations");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(./jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2) format("woff2-variations");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(./jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2) format("woff2-variations");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>e3-ui shot</title>
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-30g1JIHt.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="./assets/index-CYR-0Grb.css">
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="root"></div>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import { type Browser } from 'playwright-core';
|
|
6
|
+
/** The env vars honored as an explicit browser override, in precedence order. */
|
|
7
|
+
export declare const BROWSER_ENV_VARS: readonly ["E3_UI_CHROMIUM_PATH", "PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH"];
|
|
8
|
+
/**
|
|
9
|
+
* Return the explicit browser override from the environment, if any.
|
|
10
|
+
*
|
|
11
|
+
* @param env - Environment to read (injectable for tests)
|
|
12
|
+
* @returns The overriding executable path, or `null` when unset
|
|
13
|
+
*/
|
|
14
|
+
export declare function envBrowserPath(env?: NodeJS.ProcessEnv): string | null;
|
|
15
|
+
/**
|
|
16
|
+
* Candidate system-browser executables for a platform, most-preferred first.
|
|
17
|
+
*
|
|
18
|
+
* @param platform - `process.platform` value (injectable for tests)
|
|
19
|
+
* @param env - Environment for Windows `%ProgramFiles%`-style roots
|
|
20
|
+
* @returns Absolute candidate paths (existence NOT yet checked)
|
|
21
|
+
*/
|
|
22
|
+
export declare function systemBrowserCandidates(platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): string[];
|
|
23
|
+
/**
|
|
24
|
+
* Whether a candidate is a real browser binary rather than Ubuntu's snap shim.
|
|
25
|
+
* Rejects a path whose realpath resolves under `/snap/`, or whose file starts
|
|
26
|
+
* with `#!` (`/usr/bin/chromium-browser` on Ubuntu is a `#!/bin/sh` script
|
|
27
|
+
* that execs the confined snap — useless for automation).
|
|
28
|
+
*
|
|
29
|
+
* @param executablePath - Existing candidate path to vet
|
|
30
|
+
* @returns True when the candidate is launchable
|
|
31
|
+
*/
|
|
32
|
+
export declare function isRealBrowserBinary(executablePath: string): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Find the first usable system browser.
|
|
35
|
+
*
|
|
36
|
+
* @param platform - `process.platform` value (injectable for tests)
|
|
37
|
+
* @param env - Environment for Windows roots
|
|
38
|
+
* @returns The executable path, or `null` when none is usable
|
|
39
|
+
*/
|
|
40
|
+
export declare function findSystemBrowser(platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): string | null;
|
|
41
|
+
/** How the launched browser was obtained (surfaced by `doctor` and errors). */
|
|
42
|
+
export type BrowserSource = {
|
|
43
|
+
kind: 'env';
|
|
44
|
+
executablePath: string;
|
|
45
|
+
} | {
|
|
46
|
+
kind: 'managed';
|
|
47
|
+
} | {
|
|
48
|
+
kind: 'system';
|
|
49
|
+
executablePath: string;
|
|
50
|
+
};
|
|
51
|
+
/** One-line remediation block shared by the launch error and `doctor`. */
|
|
52
|
+
export declare function launchRemediation(): string;
|
|
53
|
+
/**
|
|
54
|
+
* Launch headless Chromium via the acquisition cascade.
|
|
55
|
+
*
|
|
56
|
+
* @param env - Environment to read overrides from (injectable for tests)
|
|
57
|
+
* @returns The browser plus which source of the cascade provided it
|
|
58
|
+
* @throws When no browser can be launched; the message carries the full
|
|
59
|
+
* remediation (install-browser / E3_UI_CHROMIUM_PATH / doctor)
|
|
60
|
+
*/
|
|
61
|
+
export declare function launchBrowser(env?: NodeJS.ProcessEnv): Promise<{
|
|
62
|
+
browser: Browser;
|
|
63
|
+
source: BrowserSource;
|
|
64
|
+
}>;
|
|
65
|
+
/**
|
|
66
|
+
* Download the version-matched `chromium-headless-shell` into playwright's
|
|
67
|
+
* managed cache (honors `PLAYWRIGHT_BROWSERS_PATH`), by spawning the bundled
|
|
68
|
+
* playwright-core CLI: `install --only-shell chromium`. The shell build is the
|
|
69
|
+
* one a bare headless launch selects, and is ~100 MB lighter than full
|
|
70
|
+
* Chromium with no X11/D-Bus system libraries.
|
|
71
|
+
*
|
|
72
|
+
* @param opts - `withDeps` also installs OS packages (Linux only; skipped with
|
|
73
|
+
* a note elsewhere — Windows/macOS need no system libraries)
|
|
74
|
+
* @returns The spawned process exit code
|
|
75
|
+
*/
|
|
76
|
+
export declare function installBrowser(opts?: {
|
|
77
|
+
withDeps?: boolean;
|
|
78
|
+
}): Promise<number>;
|
|
79
|
+
/**
|
|
80
|
+
* Diagnose the browser setup: report env overrides, run the real launch
|
|
81
|
+
* cascade against `about:blank`, and print what worked — or per-OS remediation
|
|
82
|
+
* for what didn't.
|
|
83
|
+
*
|
|
84
|
+
* @param env - Environment to diagnose (injectable for tests)
|
|
85
|
+
* @returns Process exit code (0 healthy, 1 not)
|
|
86
|
+
*/
|
|
87
|
+
export declare function doctor(env?: NodeJS.ProcessEnv): Promise<number>;
|
|
88
|
+
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA6BH,OAAO,EAAY,KAAK,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAMzD,iFAAiF;AACjF,eAAO,MAAM,gBAAgB,yEAA0E,CAAC;AAExG;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,IAAI,CAMlF;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACnC,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACrC,MAAM,EAAE,CA8BV;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAcnE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC7B,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACrC,MAAM,GAAG,IAAI,CAKf;AAED,+EAA+E;AAC/E,MAAM,MAAM,aAAa,GACnB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,0EAA0E;AAC1E,wBAAgB,iBAAiB,IAAI,MAAM,CAQ1C;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAC/B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACrC,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,CAAC,CAsCtD;AAMD;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAAC,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAevF;AAED;;;;;;;GAOG;AACH,wBAAsB,MAAM,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6BlF"}
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Browser acquisition and launch for headless capture.
|
|
7
|
+
*
|
|
8
|
+
* The launch cascade (in order):
|
|
9
|
+
* 1. `E3_UI_CHROMIUM_PATH` / `PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH` — an
|
|
10
|
+
* explicit executable wins outright.
|
|
11
|
+
* 2. A bare `chromium.launch({ headless: true })` — playwright-core resolves
|
|
12
|
+
* its own managed cache (the `chromium-headless-shell` build installed by
|
|
13
|
+
* `e3-ui install-browser`, or a full build; honors
|
|
14
|
+
* `PLAYWRIGHT_BROWSERS_PATH`). `chromium.executablePath()` must NEVER be
|
|
15
|
+
* fed back into `launch()` here: it always names the FULL chromium
|
|
16
|
+
* binary, which does not exist after an `--only-shell` install.
|
|
17
|
+
* 3. A system-installed Chromium-family browser, per platform — skipping
|
|
18
|
+
* Ubuntu's snap shims (`/usr/bin/chromium-browser` is a shell script that
|
|
19
|
+
* execs the confined snap, which breaks automation).
|
|
20
|
+
*
|
|
21
|
+
* Sandboxing: playwright launches Chromium with `--no-sandbox` by default
|
|
22
|
+
* (`chromiumSandbox` defaults to false) — correct for rendering trusted local
|
|
23
|
+
* components, and why running as root just works.
|
|
24
|
+
*
|
|
25
|
+
* @packageDocumentation
|
|
26
|
+
*/
|
|
27
|
+
import { spawn } from 'node:child_process';
|
|
28
|
+
import { createRequire } from 'node:module';
|
|
29
|
+
import { existsSync, openSync, readSync, closeSync, realpathSync } from 'node:fs';
|
|
30
|
+
import * as path from 'node:path';
|
|
31
|
+
import { chromium } from 'playwright-core';
|
|
32
|
+
/** Chromium args shared by every launch — `--disable-gpu` matches the in-repo
|
|
33
|
+
* snapshot pipeline so CLI captures are pixel-comparable with it. */
|
|
34
|
+
const LAUNCH_ARGS = ['--disable-gpu'];
|
|
35
|
+
/** The env vars honored as an explicit browser override, in precedence order. */
|
|
36
|
+
export const BROWSER_ENV_VARS = ['E3_UI_CHROMIUM_PATH', 'PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH'];
|
|
37
|
+
/**
|
|
38
|
+
* Return the explicit browser override from the environment, if any.
|
|
39
|
+
*
|
|
40
|
+
* @param env - Environment to read (injectable for tests)
|
|
41
|
+
* @returns The overriding executable path, or `null` when unset
|
|
42
|
+
*/
|
|
43
|
+
export function envBrowserPath(env = process.env) {
|
|
44
|
+
for (const name of BROWSER_ENV_VARS) {
|
|
45
|
+
const value = env[name];
|
|
46
|
+
if (value)
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Candidate system-browser executables for a platform, most-preferred first.
|
|
53
|
+
*
|
|
54
|
+
* @param platform - `process.platform` value (injectable for tests)
|
|
55
|
+
* @param env - Environment for Windows `%ProgramFiles%`-style roots
|
|
56
|
+
* @returns Absolute candidate paths (existence NOT yet checked)
|
|
57
|
+
*/
|
|
58
|
+
export function systemBrowserCandidates(platform = process.platform, env = process.env) {
|
|
59
|
+
switch (platform) {
|
|
60
|
+
case 'linux':
|
|
61
|
+
return [
|
|
62
|
+
'/opt/google/chrome/chrome',
|
|
63
|
+
'/usr/bin/google-chrome-stable',
|
|
64
|
+
'/usr/bin/google-chrome',
|
|
65
|
+
'/usr/bin/chromium',
|
|
66
|
+
'/usr/bin/chromium-browser',
|
|
67
|
+
];
|
|
68
|
+
case 'darwin':
|
|
69
|
+
return [
|
|
70
|
+
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
71
|
+
'/Applications/Chromium.app/Contents/MacOS/Chromium',
|
|
72
|
+
'/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',
|
|
73
|
+
];
|
|
74
|
+
case 'win32': {
|
|
75
|
+
const roots = [
|
|
76
|
+
env['ProgramFiles'],
|
|
77
|
+
env['ProgramFiles(x86)'],
|
|
78
|
+
env['LocalAppData'],
|
|
79
|
+
].filter((r) => !!r);
|
|
80
|
+
return [
|
|
81
|
+
...roots.map(r => path.join(r, 'Google', 'Chrome', 'Application', 'chrome.exe')),
|
|
82
|
+
...roots.map(r => path.join(r, 'Microsoft', 'Edge', 'Application', 'msedge.exe')),
|
|
83
|
+
];
|
|
84
|
+
}
|
|
85
|
+
default:
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Whether a candidate is a real browser binary rather than Ubuntu's snap shim.
|
|
91
|
+
* Rejects a path whose realpath resolves under `/snap/`, or whose file starts
|
|
92
|
+
* with `#!` (`/usr/bin/chromium-browser` on Ubuntu is a `#!/bin/sh` script
|
|
93
|
+
* that execs the confined snap — useless for automation).
|
|
94
|
+
*
|
|
95
|
+
* @param executablePath - Existing candidate path to vet
|
|
96
|
+
* @returns True when the candidate is launchable
|
|
97
|
+
*/
|
|
98
|
+
export function isRealBrowserBinary(executablePath) {
|
|
99
|
+
try {
|
|
100
|
+
if (realpathSync(executablePath).split(path.sep).includes('snap'))
|
|
101
|
+
return false;
|
|
102
|
+
const fd = openSync(executablePath, 'r');
|
|
103
|
+
try {
|
|
104
|
+
const head = Buffer.alloc(2);
|
|
105
|
+
const n = readSync(fd, head, 0, 2, 0);
|
|
106
|
+
return !(n === 2 && head[0] === 0x23 && head[1] === 0x21); // "#!"
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
closeSync(fd);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Find the first usable system browser.
|
|
118
|
+
*
|
|
119
|
+
* @param platform - `process.platform` value (injectable for tests)
|
|
120
|
+
* @param env - Environment for Windows roots
|
|
121
|
+
* @returns The executable path, or `null` when none is usable
|
|
122
|
+
*/
|
|
123
|
+
export function findSystemBrowser(platform = process.platform, env = process.env) {
|
|
124
|
+
for (const candidate of systemBrowserCandidates(platform, env)) {
|
|
125
|
+
if (existsSync(candidate) && isRealBrowserBinary(candidate))
|
|
126
|
+
return candidate;
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
/** One-line remediation block shared by the launch error and `doctor`. */
|
|
131
|
+
export function launchRemediation() {
|
|
132
|
+
return (` - Run \`e3-ui install-browser\` to download a version-matched headless Chromium` +
|
|
133
|
+
` (add --with-deps on a fresh Linux server to also install system libraries).\n` +
|
|
134
|
+
` - Or set E3_UI_CHROMIUM_PATH to a Chrome/Chromium/Edge executable` +
|
|
135
|
+
` (not Ubuntu's snap chromium — its confinement breaks automation).\n` +
|
|
136
|
+
` - Run \`e3-ui doctor\` for a full diagnosis.`);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Launch headless Chromium via the acquisition cascade.
|
|
140
|
+
*
|
|
141
|
+
* @param env - Environment to read overrides from (injectable for tests)
|
|
142
|
+
* @returns The browser plus which source of the cascade provided it
|
|
143
|
+
* @throws When no browser can be launched; the message carries the full
|
|
144
|
+
* remediation (install-browser / E3_UI_CHROMIUM_PATH / doctor)
|
|
145
|
+
*/
|
|
146
|
+
export async function launchBrowser(env = process.env) {
|
|
147
|
+
const override = envBrowserPath(env);
|
|
148
|
+
if (override) {
|
|
149
|
+
try {
|
|
150
|
+
const browser = await chromium.launch({ headless: true, executablePath: override, args: LAUNCH_ARGS });
|
|
151
|
+
return { browser, source: { kind: 'env', executablePath: override } };
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
throw new Error(`Could not launch the browser set by ${BROWSER_ENV_VARS.find(v => env[v]) ?? BROWSER_ENV_VARS[0]} ` +
|
|
155
|
+
`(${override}): ${firstLine(err)}\n${launchRemediation()}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
let managedError;
|
|
159
|
+
try {
|
|
160
|
+
const browser = await chromium.launch({ headless: true, args: LAUNCH_ARGS });
|
|
161
|
+
return { browser, source: { kind: 'managed' } };
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
managedError = err;
|
|
165
|
+
}
|
|
166
|
+
const system = findSystemBrowser();
|
|
167
|
+
if (system) {
|
|
168
|
+
try {
|
|
169
|
+
const browser = await chromium.launch({ headless: true, executablePath: system, args: LAUNCH_ARGS });
|
|
170
|
+
return { browser, source: { kind: 'system', executablePath: system } };
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
throw new Error(`No managed browser (${firstLine(managedError)}), and the system browser at ${system} ` +
|
|
174
|
+
`failed to launch: ${firstLine(err)}\n${launchRemediation()}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
throw new Error(`Could not launch headless Chromium: ${firstLine(managedError)}\n${launchRemediation()}`);
|
|
178
|
+
}
|
|
179
|
+
function firstLine(err) {
|
|
180
|
+
return (err instanceof Error ? err.message : String(err)).split('\n')[0] ?? 'unknown error';
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Download the version-matched `chromium-headless-shell` into playwright's
|
|
184
|
+
* managed cache (honors `PLAYWRIGHT_BROWSERS_PATH`), by spawning the bundled
|
|
185
|
+
* playwright-core CLI: `install --only-shell chromium`. The shell build is the
|
|
186
|
+
* one a bare headless launch selects, and is ~100 MB lighter than full
|
|
187
|
+
* Chromium with no X11/D-Bus system libraries.
|
|
188
|
+
*
|
|
189
|
+
* @param opts - `withDeps` also installs OS packages (Linux only; skipped with
|
|
190
|
+
* a note elsewhere — Windows/macOS need no system libraries)
|
|
191
|
+
* @returns The spawned process exit code
|
|
192
|
+
*/
|
|
193
|
+
export async function installBrowser(opts = {}) {
|
|
194
|
+
// playwright-core exports no `./cli` subpath — resolve cli.js at the
|
|
195
|
+
// package root via the always-exported package.json.
|
|
196
|
+
const require = createRequire(import.meta.url);
|
|
197
|
+
const cliJs = path.join(path.dirname(require.resolve('playwright-core/package.json')), 'cli.js');
|
|
198
|
+
const withDeps = (opts.withDeps ?? false) && process.platform === 'linux';
|
|
199
|
+
if (opts.withDeps && !withDeps) {
|
|
200
|
+
console.log('(--with-deps is only needed on Linux — skipped.)');
|
|
201
|
+
}
|
|
202
|
+
const args = [cliJs, 'install', '--only-shell', ...(withDeps ? ['--with-deps'] : []), 'chromium'];
|
|
203
|
+
const child = spawn(process.execPath, args, { stdio: 'inherit' });
|
|
204
|
+
return await new Promise((resolve, reject) => {
|
|
205
|
+
child.on('error', reject);
|
|
206
|
+
child.on('exit', code => resolve(code ?? 1));
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Diagnose the browser setup: report env overrides, run the real launch
|
|
211
|
+
* cascade against `about:blank`, and print what worked — or per-OS remediation
|
|
212
|
+
* for what didn't.
|
|
213
|
+
*
|
|
214
|
+
* @param env - Environment to diagnose (injectable for tests)
|
|
215
|
+
* @returns Process exit code (0 healthy, 1 not)
|
|
216
|
+
*/
|
|
217
|
+
export async function doctor(env = process.env) {
|
|
218
|
+
for (const name of BROWSER_ENV_VARS) {
|
|
219
|
+
console.log(`${name}: ${env[name] ?? '(unset)'}`);
|
|
220
|
+
}
|
|
221
|
+
console.log(`PLAYWRIGHT_BROWSERS_PATH: ${env['PLAYWRIGHT_BROWSERS_PATH'] ?? '(default cache)'}`);
|
|
222
|
+
let result;
|
|
223
|
+
try {
|
|
224
|
+
result = await launchBrowser(env);
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
console.error(`\nBrowser launch: FAILED\n${err instanceof Error ? err.message : String(err)}`);
|
|
228
|
+
return 1;
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
const page = await result.browser.newPage();
|
|
232
|
+
await page.goto('about:blank');
|
|
233
|
+
const version = result.browser.version();
|
|
234
|
+
const source = result.source.kind === 'managed'
|
|
235
|
+
? 'playwright-managed cache'
|
|
236
|
+
: `${result.source.kind === 'env' ? 'env override' : 'system browser'} at ${result.source.executablePath}`;
|
|
237
|
+
console.log(`\nBrowser launch: OK (Chromium ${version}, ${source})`);
|
|
238
|
+
console.log('e3-ui shot is ready to render.');
|
|
239
|
+
return 0;
|
|
240
|
+
}
|
|
241
|
+
catch (err) {
|
|
242
|
+
console.error(`\nBrowser launched but failed to open a page: ${err instanceof Error ? err.message : String(err)}`);
|
|
243
|
+
return 1;
|
|
244
|
+
}
|
|
245
|
+
finally {
|
|
246
|
+
await result.browser.close();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import type { ShotPayload } from './payload.js';
|
|
6
|
+
/** Default capture parameters — single source of truth (CLI help text in
|
|
7
|
+
* `cli.ts` documents these values; keep them in sync). */
|
|
8
|
+
export declare const CAPTURE_DEFAULTS: {
|
|
9
|
+
readonly viewport: {
|
|
10
|
+
readonly width: 1280;
|
|
11
|
+
readonly height: 900;
|
|
12
|
+
};
|
|
13
|
+
readonly deviceScaleFactor: 2;
|
|
14
|
+
readonly settleMs: 300;
|
|
15
|
+
readonly timeoutMs: 30000;
|
|
16
|
+
readonly storageKey: "shot";
|
|
17
|
+
readonly statusPollMs: 100;
|
|
18
|
+
readonly skeletonPollMs: 200;
|
|
19
|
+
readonly errorTextLimit: 600;
|
|
20
|
+
};
|
|
21
|
+
/** How the screenshot is framed. */
|
|
22
|
+
export type CaptureMode = {
|
|
23
|
+
kind: 'frame';
|
|
24
|
+
} | {
|
|
25
|
+
kind: 'full-page';
|
|
26
|
+
} | {
|
|
27
|
+
kind: 'element';
|
|
28
|
+
selector: string;
|
|
29
|
+
};
|
|
30
|
+
/** Options for a single capture. */
|
|
31
|
+
export interface CaptureOptions {
|
|
32
|
+
/** Directory of the prebuilt app bundle (the built `dist/app`). */
|
|
33
|
+
appDir: string;
|
|
34
|
+
/** The render payload (base64 IR). */
|
|
35
|
+
payload: ShotPayload;
|
|
36
|
+
/** Output PNG path. */
|
|
37
|
+
outPng: string;
|
|
38
|
+
/** When set, also write a self-contained HTML snapshot here. */
|
|
39
|
+
outHtml?: string | undefined;
|
|
40
|
+
/** Storage key prefix for persisted component state. */
|
|
41
|
+
storageKey?: string;
|
|
42
|
+
/** Chromium viewport. Default 1280×900. */
|
|
43
|
+
viewport?: {
|
|
44
|
+
width: number;
|
|
45
|
+
height: number;
|
|
46
|
+
};
|
|
47
|
+
/** Device scale factor (DPR). Default 2. */
|
|
48
|
+
deviceScaleFactor?: number;
|
|
49
|
+
/** Framing. Default `{ kind: 'frame' }`. */
|
|
50
|
+
mode?: CaptureMode;
|
|
51
|
+
/** Grace period (ms) after skeletons clear before capture. Default 300. */
|
|
52
|
+
settleMs?: number;
|
|
53
|
+
/** Per-navigation timeout (ms). Default 30000. */
|
|
54
|
+
timeoutMs?: number;
|
|
55
|
+
}
|
|
56
|
+
/** Serve the prebuilt app directory over a random localhost port. */
|
|
57
|
+
/**
|
|
58
|
+
* Resolve a URL pathname to a file within `root`, or `null` if it would escape
|
|
59
|
+
* (path traversal). Uses a separator-boundary check so a sibling dir sharing the
|
|
60
|
+
* root's prefix cannot pass. Exported for unit tests.
|
|
61
|
+
*/
|
|
62
|
+
export declare function resolveWithinRoot(root: string, urlPathname: string): string | null;
|
|
63
|
+
/** Escape text for safe inclusion in HTML. Exported for unit tests. */
|
|
64
|
+
export declare function escapeHtml(s: string): string;
|
|
65
|
+
/**
|
|
66
|
+
* Inline `url(...woff2)` font references in CSS as base64 data URIs (read from
|
|
67
|
+
* the app's built `assets/`), so the standalone HTML renders with the brand
|
|
68
|
+
* fonts over `file://` with no server. A font that cannot be read is left as its
|
|
69
|
+
* original (server-relative) URL and a warning is emitted — a silently broken
|
|
70
|
+
* `--html` is worse than a visible warning. Exported for unit tests.
|
|
71
|
+
*/
|
|
72
|
+
export declare function inlineFonts(css: string, appDir: string): Promise<string>;
|
|
73
|
+
/**
|
|
74
|
+
* Render a component payload to a PNG (and optionally a standalone HTML).
|
|
75
|
+
*
|
|
76
|
+
* @param opts - Capture options
|
|
77
|
+
* @throws If the app reports a compile/render error, or capture times out
|
|
78
|
+
*/
|
|
79
|
+
export declare function capture(opts: CaptureOptions): Promise<void>;
|
|
80
|
+
//# sourceMappingURL=capture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAsBH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD;2DAC2D;AAC3D,eAAO,MAAM,gBAAgB;;;;;;;;;;;;CASnB,CAAC;AAEX,oCAAoC;AACpC,MAAM,MAAM,WAAW,GACjB;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5C,oCAAoC;AACpC,MAAM,WAAW,cAAc;IAC3B,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,OAAO,EAAE,WAAW,CAAC;IACrB,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,4CAA4C;IAC5C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4CAA4C;IAC5C,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAgBD,qEAAqE;AACrE;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMlF;AA8BD,uEAAuE;AACvE,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAI5C;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAmB9E;AA4CD;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAqHjE"}
|