@liebstoeckel/thumbnails 0.3.6 → 0.3.7
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/package.json +2 -2
- package/src/capture.ts +66 -10
- package/src/index.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liebstoeckel/thumbnails",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"description": "Slide thumbnail capture for liebstoeckel decks via headless Chromium.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"liebstoeckel",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"./cli": "./src/cli.ts"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@liebstoeckel/engine": "^0.3.
|
|
48
|
+
"@liebstoeckel/engine": "^0.3.7",
|
|
49
49
|
"citty": "^0.2.2",
|
|
50
50
|
"playwright-core": "1.60.0"
|
|
51
51
|
}
|
package/src/capture.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
2
5
|
import { chromium, type Page } from "playwright-core";
|
|
3
6
|
import {
|
|
4
7
|
CAPTURE_EVENT,
|
|
@@ -13,6 +16,14 @@ import type { ThumbnailManifest } from "@liebstoeckel/engine/build/thumbnails";
|
|
|
13
16
|
|
|
14
17
|
export type ThumbnailFormat = "webp" | "jpeg" | "png";
|
|
15
18
|
|
|
19
|
+
/** The exact `playwright-core` version this package resolves browsers through.
|
|
20
|
+
* `chromium.executablePath()` looks for one specific bundled revision, so any
|
|
21
|
+
* install must use the *matching* npm release. `doctor --install-chromium` pins
|
|
22
|
+
* `playwright@<this>`. An unpinned `playwright install` resolves to registry-latest
|
|
23
|
+
* and drops a newer revision into a different dir, which this version can't find
|
|
24
|
+
* (the install "succeeds" yet capture still reports no Chromium). */
|
|
25
|
+
export const playwrightCoreVersion: string = createRequire(import.meta.url)("playwright-core/package.json").version;
|
|
26
|
+
|
|
16
27
|
/** Thumbnail capture options, the slide driver's options (ADR 0042) plus the
|
|
17
28
|
* image-encoding policy specific to the thumbnail sink. Default width 640 ×
|
|
18
29
|
* scale 2 = 1280×720, the native authoring canvas, so the overview is never
|
|
@@ -54,23 +65,68 @@ const DEFAULT_ARGS = [
|
|
|
54
65
|
"--no-zygote",
|
|
55
66
|
];
|
|
56
67
|
|
|
57
|
-
/**
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
68
|
+
/** Well-known Chrome/Chromium locations to probe when no binary is set explicitly,
|
|
69
|
+
* so a machine that already has Chrome "just works" without LIEBSTOECKEL_CHROMIUM
|
|
70
|
+
* Order = preference; the caller verifies each exists on disk. Pure (env-driven). */
|
|
71
|
+
export function systemChromiumCandidates(env: Record<string, string | undefined> = process.env): string[] {
|
|
72
|
+
const out: string[] = [];
|
|
73
|
+
// De-facto standard env vars other Chrome-driving tools honor.
|
|
74
|
+
if (env.PUPPETEER_EXECUTABLE_PATH) out.push(env.PUPPETEER_EXECUTABLE_PATH);
|
|
75
|
+
if (env.CHROME_PATH) out.push(env.CHROME_PATH);
|
|
76
|
+
// Puppeteer's install cache (`bunx puppeteer browsers install chrome`).
|
|
77
|
+
const pcache = join(homedir(), ".cache", "puppeteer", "chrome");
|
|
78
|
+
for (const sub of ["chrome-linux64/chrome", "chrome-win64/chrome.exe"]) {
|
|
61
79
|
try {
|
|
62
|
-
|
|
80
|
+
for (const p of new Bun.Glob(`*/${sub}`).scanSync({ cwd: pcache, absolute: true, onlyFiles: false })) out.push(p);
|
|
63
81
|
} catch {
|
|
64
|
-
|
|
82
|
+
// no cache dir / glob unsupported → skip
|
|
65
83
|
}
|
|
66
84
|
}
|
|
85
|
+
// PATH binaries (Linux/BSD).
|
|
86
|
+
for (const bin of ["google-chrome", "google-chrome-stable", "chromium", "chromium-browser", "microsoft-edge"]) {
|
|
87
|
+
const p = Bun.which(bin);
|
|
88
|
+
if (p) out.push(p);
|
|
89
|
+
}
|
|
90
|
+
// macOS app bundles + common Windows install paths.
|
|
91
|
+
out.push(
|
|
92
|
+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
93
|
+
"/Applications/Chromium.app/Contents/MacOS/Chromium",
|
|
94
|
+
);
|
|
95
|
+
for (const base of [env.PROGRAMFILES, env["PROGRAMFILES(X86)"], env.LOCALAPPDATA]) {
|
|
96
|
+
if (base) out.push(join(base, "Google", "Chrome", "Application", "chrome.exe"));
|
|
97
|
+
}
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** First system Chrome/Chromium that exists on disk, or undefined. */
|
|
102
|
+
function detectSystemChromium(): string | undefined {
|
|
103
|
+
for (const c of systemChromiumCandidates()) if (c && existsSync(c)) return c;
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Resolve a Chromium binary: explicit → $LIEBSTOECKEL_CHROMIUM → a system
|
|
108
|
+
* Chrome/Chromium → Playwright's. The first one that exists on disk wins. */
|
|
109
|
+
export function resolveChromium(opts: CaptureOptions = {}): string {
|
|
110
|
+
const explicit = opts.executablePath ?? process.env.LIEBSTOECKEL_CHROMIUM;
|
|
111
|
+
if (explicit && existsSync(explicit)) return explicit;
|
|
112
|
+
|
|
113
|
+
const system = detectSystemChromium();
|
|
114
|
+
if (system) return system;
|
|
115
|
+
|
|
67
116
|
// executablePath() returns a computed path even when the browser isn't
|
|
68
117
|
// installed, verify the binary actually exists so hasChromium() stays honest
|
|
69
118
|
// (otherwise capture is attempted where no browser exists, e.g. CI).
|
|
70
|
-
|
|
119
|
+
let playwright: string | undefined;
|
|
120
|
+
try {
|
|
121
|
+
playwright = chromium.executablePath();
|
|
122
|
+
} catch {
|
|
123
|
+
playwright = undefined;
|
|
124
|
+
}
|
|
125
|
+
if (playwright && existsSync(playwright)) return playwright;
|
|
126
|
+
|
|
71
127
|
throw new Error(
|
|
72
|
-
"No Chromium found for
|
|
73
|
-
"
|
|
128
|
+
"No Chromium found for slide capture. Run `liebstoeckel doctor --install-chromium`, " +
|
|
129
|
+
"set LIEBSTOECKEL_CHROMIUM to a Chrome/Chromium binary, or `bunx playwright install chromium`.",
|
|
74
130
|
);
|
|
75
131
|
}
|
|
76
132
|
|
|
@@ -93,7 +149,7 @@ export function thumbnailsEnabled(
|
|
|
93
149
|
): { enabled: boolean; reason?: string } {
|
|
94
150
|
if (env.LIEBSTOECKEL_NO_THUMBS) return { enabled: false, reason: "LIEBSTOECKEL_NO_THUMBS is set" };
|
|
95
151
|
if (!chromium) {
|
|
96
|
-
return { enabled: false, reason: "no Chromium (run `
|
|
152
|
+
return { enabled: false, reason: "no Chromium (run `liebstoeckel doctor --install-chromium` or set LIEBSTOECKEL_CHROMIUM)" };
|
|
97
153
|
}
|
|
98
154
|
return { enabled: true };
|
|
99
155
|
}
|