silvery 0.21.0 → 0.23.0
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 +1 -1
- package/dist/{Text-Lq0dmj8-.mjs → Text-Ci6UCSTL.mjs} +46 -48
- package/dist/Text-Ci6UCSTL.mjs.map +1 -0
- package/dist/{render-string-DkQacASz.mjs → ag-q9lRlKlt.mjs} +5322 -4259
- package/dist/ag-q9lRlKlt.mjs.map +1 -0
- package/dist/{animation-ZMN2_XKv.mjs → animation-CZ4x2R7C.mjs} +1 -1
- package/dist/{animation-ZMN2_XKv.mjs.map → animation-CZ4x2R7C.mjs.map} +1 -1
- package/dist/{ansi-D1KQMAbf.mjs → ansi-CLmIMnop.mjs} +1 -1
- package/dist/{ansi-D1KQMAbf.mjs.map → ansi-CLmIMnop.mjs.map} +1 -1
- package/dist/{ansi-2Xn0yatP.d.mts → ansi-zmNzgkPB.d.mts} +1 -1
- package/dist/{ansi-2Xn0yatP.d.mts.map → ansi-zmNzgkPB.d.mts.map} +1 -1
- package/dist/{backend-B-WYLUib.mjs → backend-DSiSIc-h.mjs} +2 -2
- package/dist/{backend-B-WYLUib.mjs.map → backend-DSiSIc-h.mjs.map} +1 -1
- package/dist/chain-bridge-CkYcMxlq.mjs +4149 -0
- package/dist/chain-bridge-CkYcMxlq.mjs.map +1 -0
- package/dist/{chunk-BSw8zbkd.mjs → chunk-BEJ448es.mjs} +1 -3
- package/dist/cli-VNqUKlXw.mjs +4 -0
- package/dist/{context-BU5LkkIy.mjs → context-CEhuD1R_.mjs} +1 -1
- package/dist/{context-BU5LkkIy.mjs.map → context-CEhuD1R_.mjs.map} +1 -1
- package/dist/devtools-BF4IMumr.mjs +2 -0
- package/dist/{devtools-DcQjgyjL.mjs → devtools-td2AjFwc.mjs} +5 -5
- package/dist/{devtools-DcQjgyjL.mjs.map → devtools-td2AjFwc.mjs.map} +1 -1
- package/dist/{easing-BI-ASGMO.d.mts → easing-C5MrdO7V.d.mts} +1 -1
- package/dist/{easing-BI-ASGMO.d.mts.map → easing-C5MrdO7V.d.mts.map} +1 -1
- package/dist/{eta-CJlGH06n.mjs → eta-BwYWEjfS.mjs} +1 -1
- package/dist/{eta-CJlGH06n.mjs.map → eta-BwYWEjfS.mjs.map} +1 -1
- package/dist/{flexily-zero-adapter-C4lW_Ov5.mjs → flexily-zero-adapter-DktX3HsX.mjs} +1 -1
- package/dist/{flexily-zero-adapter-C3Vj0fPt.mjs → flexily-zero-adapter-VoBGHG14.mjs} +1 -1
- package/dist/{flexily-zero-adapter-C3Vj0fPt.mjs.map → flexily-zero-adapter-VoBGHG14.mjs.map} +1 -1
- package/dist/hit-registry-D_nxOivS.d.mts +71 -0
- package/dist/hit-registry-D_nxOivS.d.mts.map +1 -0
- package/dist/{UPNG-DosRPdF4.mjs → image-CIF75xMr.mjs} +891 -6
- package/dist/image-CIF75xMr.mjs.map +1 -0
- package/dist/{index-CSQf13CI.d.mts → index-377zdPLP.d.mts} +35 -12
- package/dist/index-377zdPLP.d.mts.map +1 -0
- package/dist/{index-Cl9KKjQ_.d.mts → index-BcSr0RAQ.d.mts} +8670 -10659
- package/dist/index-BcSr0RAQ.d.mts.map +1 -0
- package/dist/{index-XbNrPhWl.d.mts → index-DLnpxDAm.d.mts} +2 -2
- package/dist/{index-XbNrPhWl.d.mts.map → index-DLnpxDAm.d.mts.map} +1 -1
- package/dist/{index-BUMxS65f.d.mts → index-DlNmckTq.d.mts} +2 -2
- package/dist/{index-BUMxS65f.d.mts.map → index-DlNmckTq.d.mts.map} +1 -1
- package/dist/index.d.mts +12 -8
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +18 -15
- package/dist/index.mjs.map +1 -1
- package/dist/{layout-engine-C2px0RJE.mjs → layout-engine-BgR58vL0.mjs} +3 -3
- package/dist/{layout-engine-C2px0RJE.mjs.map → layout-engine-BgR58vL0.mjs.map} +1 -1
- package/dist/{layout-engine-C07LEXWT.mjs → layout-engine-DNjTha8f.mjs} +1 -1
- package/dist/{layout-signals-Cnw6xk8Q.mjs → layout-signals-CGYbHmxy.mjs} +146 -23
- package/dist/layout-signals-CGYbHmxy.mjs.map +1 -0
- package/dist/{bound-term-0sPrrzH1.d.mts → mouse-events-B2z5tbsL.d.mts} +780 -379
- package/dist/mouse-events-B2z5tbsL.d.mts.map +1 -0
- package/dist/{mouse-events-Dki3ISIp.mjs → mouse-events-WQ2h-uqG.mjs} +45 -10
- package/dist/mouse-events-WQ2h-uqG.mjs.map +1 -0
- package/dist/{multi-progress-DHZ2xUT2.d.mts → multi-progress-BaEFfHKP.d.mts} +2 -2
- package/dist/{multi-progress-DHZ2xUT2.d.mts.map → multi-progress-BaEFfHKP.d.mts.map} +1 -1
- package/dist/{multi-progress-CIRjrzma.mjs → multi-progress-zCWHEm9P.mjs} +3 -3
- package/dist/{multi-progress-CIRjrzma.mjs.map → multi-progress-zCWHEm9P.mjs.map} +1 -1
- package/dist/{node-CjM5Rt-M.mjs → node-CJ3J_rW-.mjs} +1 -1
- package/dist/{node-CjM5Rt-M.mjs.map → node-CJ3J_rW-.mjs.map} +1 -1
- package/dist/{progress-DB_Xo071.mjs → progress-6vJ7nxUg.mjs} +4 -4
- package/dist/{progress-DB_Xo071.mjs.map → progress-6vJ7nxUg.mjs.map} +1 -1
- package/dist/{progress-bar-oJwq22CR.mjs → progress-bar-BlFNsZL8.mjs} +4 -4
- package/dist/{progress-bar-oJwq22CR.mjs.map → progress-bar-BlFNsZL8.mjs.map} +1 -1
- package/dist/{reconciler-DldIJB93.mjs → reconciler--_-biN23.mjs} +190 -134
- package/dist/reconciler--_-biN23.mjs.map +1 -0
- package/dist/{render-string-BcoCpjCB.mjs → render-string-DaghHpLN.mjs} +1 -1
- package/dist/render-string-DtHZP0cU.mjs +215 -0
- package/dist/render-string-DtHZP0cU.mjs.map +1 -0
- package/dist/runtime.d.mts +4 -3
- package/dist/runtime.mjs +4 -3
- package/dist/schemes-DWQPxXAi.mjs +2516 -0
- package/dist/{schemes-JjNp4aSl.mjs.map → schemes-DWQPxXAi.mjs.map} +1 -1
- package/dist/{spinner-D9lrHr8s.mjs → spinner-B50hILqx.mjs} +19 -4
- package/dist/{spinner-D9lrHr8s.mjs.map → spinner-B50hILqx.mjs.map} +1 -1
- package/dist/{spinner-CZINHpkV.d.mts → spinner-DN10UfF0.d.mts} +2 -2
- package/dist/{spinner-CZINHpkV.d.mts.map → spinner-DN10UfF0.d.mts.map} +1 -1
- package/dist/{src-BNTToU7l.mjs → src-B8lf1kiR.mjs} +1507 -1166
- package/dist/src-B8lf1kiR.mjs.map +1 -0
- package/dist/{src-5w9QR6_8.mjs → src-BOLdi3WG.mjs} +105 -237
- package/dist/src-BOLdi3WG.mjs.map +1 -0
- package/dist/{src-BR4xNwdG.mjs → src-BXeTHHlL.mjs} +20240 -25437
- package/dist/src-BXeTHHlL.mjs.map +1 -0
- package/dist/{src-DKp-_OFG.mjs → src-BqeBFB3X.mjs} +90 -47
- package/dist/src-BqeBFB3X.mjs.map +1 -0
- package/dist/src-DbqcSrhy.mjs +3901 -0
- package/dist/src-DbqcSrhy.mjs.map +1 -0
- package/dist/{steps-Bp2uNqnn.d.mts → steps-B2kBmFpb.d.mts} +1 -1
- package/dist/{steps-Bp2uNqnn.d.mts.map → steps-B2kBmFpb.d.mts.map} +1 -1
- package/dist/{svg-Cz0UXcDj.mjs → svg-NmV9dgB9.mjs} +1 -1
- package/dist/{svg-Cz0UXcDj.mjs.map → svg-NmV9dgB9.mjs.map} +1 -1
- package/dist/{svg-g1D6ErwR.d.mts → svg-VUr78l5d.d.mts} +1 -1
- package/dist/{svg-g1D6ErwR.d.mts.map → svg-VUr78l5d.d.mts.map} +1 -1
- package/dist/term.d.mts +2 -2
- package/dist/term.mjs +3 -8
- package/dist/test.d.mts +673 -0
- package/dist/test.d.mts.map +1 -0
- package/dist/test.mjs +2829 -0
- package/dist/test.mjs.map +1 -0
- package/dist/theme.d.mts +2 -2
- package/dist/theme.d.mts.map +1 -1
- package/dist/theme.mjs +3 -8
- package/dist/{types-kt_fKR37.d.mts → types-D_E0FbqA.d.mts} +1 -1
- package/dist/{types-kt_fKR37.d.mts.map → types-D_E0FbqA.d.mts.map} +1 -1
- package/dist/ui/animation.d.mts +2 -2
- package/dist/ui/animation.mjs +1 -1
- package/dist/ui/ansi.d.mts +1 -1
- package/dist/ui/ansi.mjs +1 -1
- package/dist/ui/cli.d.mts +3 -3
- package/dist/ui/cli.mjs +5 -5
- package/dist/ui/image.d.mts +1 -1
- package/dist/ui/image.mjs +1 -1
- package/dist/ui/progress.d.mts +4 -4
- package/dist/ui/progress.mjs +4 -4
- package/dist/ui/react.d.mts +1 -1
- package/dist/ui/react.mjs +2 -2
- package/dist/ui/recording-chrome-react.d.mts +1 -1
- package/dist/ui/recording-chrome-react.mjs +2 -2
- package/dist/ui/recording-chrome.d.mts +1 -1
- package/dist/ui/recording-chrome.mjs +1 -1
- package/dist/ui/utils.mjs +1 -1
- package/dist/ui/wrappers.d.mts +2 -2
- package/dist/ui/wrappers.mjs +1 -1
- package/dist/ui.d.mts +6 -6
- package/dist/ui.mjs +7 -7
- package/dist/unicode-CxyxVGmB.mjs +11077 -0
- package/dist/unicode-CxyxVGmB.mjs.map +1 -0
- package/dist/{useLatest-DRDDVwjh.d.mts → useLatest-UOvWy0ZW.d.mts} +2 -2
- package/dist/{useLatest-DRDDVwjh.d.mts.map → useLatest-UOvWy0ZW.d.mts.map} +1 -1
- package/dist/useLayout-D5cE8OCI.mjs +424 -0
- package/dist/useLayout-D5cE8OCI.mjs.map +1 -0
- package/dist/{with-text-input-YeohVLeo.d.mts → with-text-input-DLoSCBrm.d.mts} +3 -3
- package/dist/{with-text-input-YeohVLeo.d.mts.map → with-text-input-DLoSCBrm.d.mts.map} +1 -1
- package/dist/wrap-measurer-registration-IV2HtcCd.d.mts +3106 -0
- package/dist/wrap-measurer-registration-IV2HtcCd.d.mts.map +1 -0
- package/dist/{wrapper-C70ATkVv.mjs → wrapper-CD29afOs.mjs} +59 -17
- package/dist/wrapper-CD29afOs.mjs.map +1 -0
- package/dist/{wrappers-BCUYITrY.mjs → wrappers-CInBJm44.mjs} +18 -8
- package/dist/wrappers-CInBJm44.mjs.map +1 -0
- package/dist/{yoga-adapter-BnZX1PAY.mjs → yoga-adapter-9uab5Qn-.mjs} +2 -2
- package/dist/{yoga-adapter-BnZX1PAY.mjs.map → yoga-adapter-9uab5Qn-.mjs.map} +1 -1
- package/dist/yoga-adapter-yqTl1aXK.mjs +2 -0
- package/package.json +59 -14
- package/dist/Text-Lq0dmj8-.mjs.map +0 -1
- package/dist/UPNG-Bo33r8rA.mjs +0 -3
- package/dist/UPNG-DosRPdF4.mjs.map +0 -1
- package/dist/__vite-browser-external-2447137e-D_JM6skp.mjs +0 -6
- package/dist/__vite-browser-external-2447137e-D_JM6skp.mjs.map +0 -1
- package/dist/ansi-yC4RyBNY.mjs +0 -22441
- package/dist/ansi-yC4RyBNY.mjs.map +0 -1
- package/dist/apng-CR08rIaH.mjs +0 -58
- package/dist/apng-CR08rIaH.mjs.map +0 -1
- package/dist/apng-DaHfVaVI.mjs +0 -3
- package/dist/assets/resvgjs.darwin-arm64-BtufyGW1.node +0 -0
- package/dist/assets/skia.darwin-arm64-DQs5sT6N.node +0 -0
- package/dist/backends-CUtan80W.mjs +0 -3
- package/dist/backends-DIVYzKqd.mjs +0 -1083
- package/dist/backends-DIVYzKqd.mjs.map +0 -1
- package/dist/bound-term-0sPrrzH1.d.mts.map +0 -1
- package/dist/canvas-1v7dPT-_.mjs +0 -3
- package/dist/canvas-CSuPOMNt.mjs +0 -1442
- package/dist/canvas-CSuPOMNt.mjs.map +0 -1
- package/dist/cli-dvo0r2fs.mjs +0 -4
- package/dist/compare-CQodSH4G.mjs +0 -376
- package/dist/compare-CQodSH4G.mjs.map +0 -1
- package/dist/compare-DHlcxEYA.mjs +0 -3
- package/dist/devtools-CJdt5H0X.mjs +0 -2
- package/dist/fonts-BFmhXDv7.mjs +0 -88
- package/dist/fonts-BFmhXDv7.mjs.map +0 -1
- package/dist/gif-C_AjaT9d.mjs +0 -188
- package/dist/gif-C_AjaT9d.mjs.map +0 -1
- package/dist/gif-DaC4XrxA.mjs +0 -3
- package/dist/gifenc-BOUT-KFB.mjs +0 -730
- package/dist/gifenc-BOUT-KFB.mjs.map +0 -1
- package/dist/image-C2Birh2x.mjs +0 -1252
- package/dist/image-C2Birh2x.mjs.map +0 -1
- package/dist/index-CSQf13CI.d.mts.map +0 -1
- package/dist/index-Cl9KKjQ_.d.mts.map +0 -1
- package/dist/key-mapping-CS-YD_cD.mjs +0 -132
- package/dist/key-mapping-CS-YD_cD.mjs.map +0 -1
- package/dist/key-mapping-Yn-Jgrij.mjs +0 -3
- package/dist/layout-signals-Cnw6xk8Q.mjs.map +0 -1
- package/dist/mouse-events-Dki3ISIp.mjs.map +0 -1
- package/dist/playwright-D5YiZcNS.mjs +0 -76397
- package/dist/playwright-D5YiZcNS.mjs.map +0 -1
- package/dist/png-codec-Dp84742B.mjs +0 -36
- package/dist/png-codec-Dp84742B.mjs.map +0 -1
- package/dist/png-codec-QwOtJ8Zs.mjs +0 -3
- package/dist/rasterizer-BRXrDdWx.mjs +0 -3
- package/dist/rasterizer-CpEhJvdR.mjs +0 -296
- package/dist/rasterizer-CpEhJvdR.mjs.map +0 -1
- package/dist/reconciler-DldIJB93.mjs.map +0 -1
- package/dist/render-string-DkQacASz.mjs.map +0 -1
- package/dist/resvg-js-DkOndZI3.mjs +0 -203
- package/dist/resvg-js-DkOndZI3.mjs.map +0 -1
- package/dist/schemes-JjNp4aSl.mjs +0 -2611
- package/dist/src-5w9QR6_8.mjs.map +0 -1
- package/dist/src-BNTToU7l.mjs.map +0 -1
- package/dist/src-BR4xNwdG.mjs.map +0 -1
- package/dist/src-DKp-_OFG.mjs.map +0 -1
- package/dist/src-bt8wSrfJ.mjs +0 -258
- package/dist/src-bt8wSrfJ.mjs.map +0 -1
- package/dist/src-e33Y6kNJ.mjs +0 -3
- package/dist/src-iDwu25UD.mjs +0 -1814
- package/dist/src-iDwu25UD.mjs.map +0 -1
- package/dist/svg-15lZZzxq.mjs +0 -486
- package/dist/svg-15lZZzxq.mjs.map +0 -1
- package/dist/svg-DY72a4HK.mjs +0 -3
- package/dist/term.mjs.map +0 -1
- package/dist/theme.mjs.map +0 -1
- package/dist/ui/display.d.mts +0 -35
- package/dist/ui/display.d.mts.map +0 -1
- package/dist/ui/display.mjs +0 -123
- package/dist/ui/display.mjs.map +0 -1
- package/dist/ui/input.d.mts +0 -184
- package/dist/ui/input.d.mts.map +0 -1
- package/dist/ui/input.mjs +0 -285
- package/dist/ui/input.mjs.map +0 -1
- package/dist/wrapper-C70ATkVv.mjs.map +0 -1
- package/dist/wrappers-BCUYITrY.mjs.map +0 -1
- package/dist/yoga-adapter-DxgsQ_gg.mjs +0 -2
- package/dist/zipBundle-3nqeDRtm.mjs +0 -3
- package/dist/zipBundle-VNAYFmqJ.mjs +0 -2003
- package/dist/zipBundle-VNAYFmqJ.mjs.map +0 -1
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { n as __esmMin } from "./chunk-BSw8zbkd.mjs";
|
|
2
|
-
import { t as require_UPNG } from "./UPNG-DosRPdF4.mjs";
|
|
3
|
-
//#region ../termless/src/recording/tape/png-codec.ts
|
|
4
|
-
/** Synchronous upng access — the module is pure JS and resolves eagerly. */
|
|
5
|
-
function loadUpng() {
|
|
6
|
-
if (!upngModule) upngModule = require_UPNG();
|
|
7
|
-
return upngModule;
|
|
8
|
-
}
|
|
9
|
-
/** Decode PNG bytes to an RGBA raster. */
|
|
10
|
-
function decodePngRgba(png) {
|
|
11
|
-
const UPNG = loadUpng();
|
|
12
|
-
const buffer = png.buffer.slice(png.byteOffset, png.byteOffset + png.byteLength);
|
|
13
|
-
const decoded = UPNG.decode(buffer);
|
|
14
|
-
const frame = UPNG.toRGBA8(decoded)[0];
|
|
15
|
-
if (!frame) throw new Error("decodePngRgba: PNG decode produced no RGBA frame");
|
|
16
|
-
return {
|
|
17
|
-
width: decoded.width,
|
|
18
|
-
height: decoded.height,
|
|
19
|
-
data: new Uint8Array(frame)
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
/** Encode an RGBA raster to lossless PNG bytes (0 = no quantization). */
|
|
23
|
-
function encodePng(img) {
|
|
24
|
-
const UPNG = loadUpng();
|
|
25
|
-
const ab = img.data.buffer.slice(img.data.byteOffset, img.data.byteOffset + img.data.byteLength);
|
|
26
|
-
const encoded = UPNG.encode([ab], img.width, img.height, 0);
|
|
27
|
-
return new Uint8Array(encoded);
|
|
28
|
-
}
|
|
29
|
-
var upngModule;
|
|
30
|
-
var init_png_codec = __esmMin((() => {
|
|
31
|
-
upngModule = null;
|
|
32
|
-
}));
|
|
33
|
-
//#endregion
|
|
34
|
-
export { encodePng as n, init_png_codec as r, decodePngRgba as t };
|
|
35
|
-
|
|
36
|
-
//# sourceMappingURL=png-codec-Dp84742B.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"png-codec-Dp84742B.mjs","names":[],"sources":["../../termless/src/recording/tape/png-codec.ts"],"sourcesContent":["/**\n * Tiny PNG codec wrapper for the cross-backend compositor.\n *\n * Decode + encode via `upng-js` (already a `@termless/core` dependency, used\n * for PNG measurement in `./compare.ts`). No native `@napi-rs/canvas` needed\n * here — `@termless/core` stays dependency-light; the canvas/Skia stack lives\n * in `@termless/ghostty`.\n *\n * The compositor (`./compare-canvas.ts`) works in raw RGBA, so this module is\n * just the byte ⇄ pixel bridge.\n */\n\nlet upngModule: typeof import(\"upng-js\") | null = null\n\nasync function loadUpngAsync() {\n if (upngModule) return upngModule\n upngModule = await import(\"upng-js\")\n return upngModule\n}\n\n/** Synchronous upng access — the module is pure JS and resolves eagerly. */\nfunction loadUpng(): typeof import(\"upng-js\") {\n if (!upngModule) {\n // upng-js is CJS; require keeps decode/encode synchronous for the\n // pixel-pushing hot path in the compositor.\n upngModule = require(\"upng-js\") as typeof import(\"upng-js\")\n }\n return upngModule\n}\n\n/** A decoded raster — RGBA8, row-major, top-left origin. */\nexport interface RgbaImage {\n width: number\n height: number\n /** `width * height * 4` bytes, RGBA order. */\n data: Uint8Array\n}\n\n/** Decode PNG bytes to an RGBA raster. */\nexport function decodePngRgba(png: Uint8Array): RgbaImage {\n const UPNG = loadUpng()\n const buffer = png.buffer.slice(png.byteOffset, png.byteOffset + png.byteLength) as ArrayBuffer\n const decoded = UPNG.decode(buffer)\n const frame = UPNG.toRGBA8(decoded)[0]\n if (!frame) throw new Error(\"decodePngRgba: PNG decode produced no RGBA frame\")\n return { width: decoded.width, height: decoded.height, data: new Uint8Array(frame) }\n}\n\n/** Encode an RGBA raster to lossless PNG bytes (0 = no quantization). */\nexport function encodePng(img: RgbaImage): Uint8Array {\n const UPNG = loadUpng()\n const ab = img.data.buffer.slice(img.data.byteOffset, img.data.byteOffset + img.data.byteLength) as ArrayBuffer\n const encoded = UPNG.encode([ab], img.width, img.height, 0)\n return new Uint8Array(encoded)\n}\n\n/** Async warm-up — pre-loads the upng module so the first sync call is hot. */\nexport async function warmUpngCodec(): Promise<void> {\n await loadUpngAsync()\n}\n"],"mappings":";;;;AAqBA,SAAS,WAAqC;AAC5C,KAAI,CAAC,WAGH,cAAA,cAAA;AAEF,QAAO;;;AAYT,SAAgB,cAAc,KAA4B;CACxD,MAAM,OAAO,UAAU;CACvB,MAAM,SAAS,IAAI,OAAO,MAAM,IAAI,YAAY,IAAI,aAAa,IAAI,WAAW;CAChF,MAAM,UAAU,KAAK,OAAO,OAAO;CACnC,MAAM,QAAQ,KAAK,QAAQ,QAAQ,CAAC;AACpC,KAAI,CAAC,MAAO,OAAM,IAAI,MAAM,mDAAmD;AAC/E,QAAO;EAAE,OAAO,QAAQ;EAAO,QAAQ,QAAQ;EAAQ,MAAM,IAAI,WAAW,MAAM;EAAE;;;AAItF,SAAgB,UAAU,KAA4B;CACpD,MAAM,OAAO,UAAU;CACvB,MAAM,KAAK,IAAI,KAAK,OAAO,MAAM,IAAI,KAAK,YAAY,IAAI,KAAK,aAAa,IAAI,KAAK,WAAW;CAChG,MAAM,UAAU,KAAK,OAAO,CAAC,GAAG,EAAE,IAAI,OAAO,IAAI,QAAQ,EAAE;AAC3D,QAAO,IAAI,WAAW,QAAQ;;;;AAzC5B,cAA8C"}
|
|
@@ -1,296 +0,0 @@
|
|
|
1
|
-
import { n as __esmMin, o as __toESM } from "./chunk-BSw8zbkd.mjs";
|
|
2
|
-
import { c as init_fonts, n as BUNDLED_FONTS, o as bundledFontFiles, s as bundledFontsDir } from "./fonts-BFmhXDv7.mjs";
|
|
3
|
-
import { existsSync } from "node:fs";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
//#region ../termless/src/view/rasterizer.ts
|
|
6
|
-
async function loadResvg() {
|
|
7
|
-
if (resvgModule) return resvgModule;
|
|
8
|
-
resvgModule = await import("./resvg-js-DkOndZI3.mjs").then((m) => /* @__PURE__ */ __toESM(m.default, 1));
|
|
9
|
-
return resvgModule;
|
|
10
|
-
}
|
|
11
|
-
function createResvgRasterizer(Resvg) {
|
|
12
|
-
const fontFiles = bundledFontFiles();
|
|
13
|
-
const build = (svg, scale) => new Resvg.Resvg(svg, {
|
|
14
|
-
fitTo: {
|
|
15
|
-
mode: "zoom",
|
|
16
|
-
value: scale
|
|
17
|
-
},
|
|
18
|
-
font: {
|
|
19
|
-
loadSystemFonts: true,
|
|
20
|
-
defaultFontFamily: "Menlo",
|
|
21
|
-
fontFiles
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
return {
|
|
25
|
-
kind: "resvg",
|
|
26
|
-
async rasterize(svg, scale) {
|
|
27
|
-
const rendered = build(svg, scale).render();
|
|
28
|
-
return {
|
|
29
|
-
pixels: new Uint8Array(rendered.pixels),
|
|
30
|
-
width: rendered.width,
|
|
31
|
-
height: rendered.height
|
|
32
|
-
};
|
|
33
|
-
},
|
|
34
|
-
async toPng(svg, scale) {
|
|
35
|
-
return build(svg, scale).render().asPng();
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
async function loadCanvas() {
|
|
40
|
-
if (canvasModule) return canvasModule;
|
|
41
|
-
const mod = await import("./canvas-1v7dPT-_.mjs").then((m) => /* @__PURE__ */ __toESM(m.default, 1));
|
|
42
|
-
const dir = bundledFontsDir();
|
|
43
|
-
for (const { file, family } of BUNDLED_FONTS) {
|
|
44
|
-
const path = join(dir, file);
|
|
45
|
-
if (existsSync(path)) mod.GlobalFonts.registerFromPath(path, family);
|
|
46
|
-
}
|
|
47
|
-
canvasModule = mod;
|
|
48
|
-
return canvasModule;
|
|
49
|
-
}
|
|
50
|
-
/** Read the intrinsic `width`/`height` from an SVG's root attributes. */
|
|
51
|
-
function svgIntrinsicSize(svg) {
|
|
52
|
-
const w = svg.match(/<svg[^>]*\bwidth="([\d.]+)"/)?.[1];
|
|
53
|
-
const h = svg.match(/<svg[^>]*\bheight="([\d.]+)"/)?.[1];
|
|
54
|
-
return {
|
|
55
|
-
width: w ? Math.round(Number(w)) : 0,
|
|
56
|
-
height: h ? Math.round(Number(h)) : 0
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
function createCanvasRasterizer(mod) {
|
|
60
|
-
const draw = (svg, scale) => {
|
|
61
|
-
const img = new mod.Image();
|
|
62
|
-
img.src = Buffer.from(svg);
|
|
63
|
-
const intrinsic = svgIntrinsicSize(svg);
|
|
64
|
-
const width = Math.max(1, Math.round((img.width || intrinsic.width) * scale));
|
|
65
|
-
const height = Math.max(1, Math.round((img.height || intrinsic.height) * scale));
|
|
66
|
-
const canvas = mod.createCanvas(width, height);
|
|
67
|
-
canvas.getContext("2d").drawImage(img, 0, 0, width, height);
|
|
68
|
-
return {
|
|
69
|
-
canvas,
|
|
70
|
-
width,
|
|
71
|
-
height
|
|
72
|
-
};
|
|
73
|
-
};
|
|
74
|
-
return {
|
|
75
|
-
kind: "canvas",
|
|
76
|
-
async rasterize(svg, scale) {
|
|
77
|
-
const { canvas, width, height } = draw(svg, scale);
|
|
78
|
-
const data = canvas.getContext("2d").getImageData(0, 0, width, height).data;
|
|
79
|
-
return {
|
|
80
|
-
pixels: new Uint8Array(data),
|
|
81
|
-
width,
|
|
82
|
-
height
|
|
83
|
-
};
|
|
84
|
-
},
|
|
85
|
-
async toPng(svg, scale) {
|
|
86
|
-
const { canvas } = draw(svg, scale);
|
|
87
|
-
return new Uint8Array(canvas.toBuffer("image/png"));
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
async function loadSwash() {
|
|
92
|
-
if (swashModule) return swashModule;
|
|
93
|
-
const mod = await import("./src-bt8wSrfJ.mjs");
|
|
94
|
-
if (!mod.swashRenderAvailable()) throw new Error("@termless/swash-render native binding is not built");
|
|
95
|
-
swashModule = mod;
|
|
96
|
-
return mod;
|
|
97
|
-
}
|
|
98
|
-
async function createSwashRasterizer(mod) {
|
|
99
|
-
const svgFallback = createResvgRasterizer(await loadResvg());
|
|
100
|
-
const toBitmap = (terminal, scale) => {
|
|
101
|
-
const s = Math.max(1, scale);
|
|
102
|
-
const bmp = mod.renderCells(terminal, {
|
|
103
|
-
cellWidth: 9.6 * s,
|
|
104
|
-
cellHeight: 20 * s,
|
|
105
|
-
padding: Math.round(SWASH_EDGE_PADDING * s)
|
|
106
|
-
});
|
|
107
|
-
return {
|
|
108
|
-
pixels: new Uint8Array(bmp.pixels),
|
|
109
|
-
width: bmp.width,
|
|
110
|
-
height: bmp.height
|
|
111
|
-
};
|
|
112
|
-
};
|
|
113
|
-
return {
|
|
114
|
-
kind: "swash",
|
|
115
|
-
rasterize: svgFallback.rasterize,
|
|
116
|
-
toPng: svgFallback.toPng,
|
|
117
|
-
async rasterizeCells(terminal, scale) {
|
|
118
|
-
return toBitmap(terminal, scale);
|
|
119
|
-
},
|
|
120
|
-
async cellsToPng(terminal, scale) {
|
|
121
|
-
const { pixels, width, height } = toBitmap(terminal, scale);
|
|
122
|
-
const UPNG = await import("./UPNG-Bo33r8rA.mjs").then((m) => /* @__PURE__ */ __toESM(m.default, 1));
|
|
123
|
-
const ab = pixels.buffer.slice(pixels.byteOffset, pixels.byteOffset + pixels.byteLength);
|
|
124
|
-
return new Uint8Array(UPNG.encode([ab], width, height, 0));
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Lazily import `playwright`. Playwright is an **optional** dependency — a
|
|
130
|
-
* default `bun install` omits it. Throws a clear, actionable error if absent,
|
|
131
|
-
* naming both the package install and the browser-download step.
|
|
132
|
-
*/
|
|
133
|
-
async function loadPlaywright() {
|
|
134
|
-
if (playwrightModule) return playwrightModule;
|
|
135
|
-
playwrightModule = await import("./playwright-D5YiZcNS.mjs");
|
|
136
|
-
return playwrightModule;
|
|
137
|
-
}
|
|
138
|
-
/** Read intrinsic width/height from an SVG root — reused for the viewport. */
|
|
139
|
-
function browserSvgSize(svg) {
|
|
140
|
-
const { width, height } = svgIntrinsicSize(svg);
|
|
141
|
-
return {
|
|
142
|
-
width: Math.max(1, width),
|
|
143
|
-
height: Math.max(1, height)
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Inline the bundled `@font-face` faces into an SVG if it does not already
|
|
148
|
-
* carry them. The `record` GIF/APNG pipeline produces frame SVGs without
|
|
149
|
-
* `embedFonts`, so Chromium would otherwise fall back to host fonts (or tofu
|
|
150
|
-
* for symbol / emoji code points). Embedding makes the page deterministic.
|
|
151
|
-
*/
|
|
152
|
-
async function ensureEmbeddedFonts(svg) {
|
|
153
|
-
if (svg.includes("@font-face")) return svg;
|
|
154
|
-
const { embeddedFontFaceDefs } = await import("./svg-DY72a4HK.mjs");
|
|
155
|
-
const defs = embeddedFontFaceDefs();
|
|
156
|
-
if (!defs) return svg;
|
|
157
|
-
return svg.replace(/(<svg[^>]*>)/, `$1${defs}`);
|
|
158
|
-
}
|
|
159
|
-
/** Wrap an SVG in a minimal full-bleed HTML document for Chromium. */
|
|
160
|
-
function browserHtml(svg, width, height) {
|
|
161
|
-
return `<!doctype html><html><head><meta charset="utf-8"><style>html,body{margin:0;padding:0;width:${width}px;height:${height}px;overflow:hidden;background:transparent}svg{display:block}</style></head><body>${svg}</body></html>`;
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* The `browser` rasterizer — rasterizes SVG frames via headless Chromium.
|
|
165
|
-
*
|
|
166
|
-
* The browser instance is launched once and reused across every `rasterize` /
|
|
167
|
-
* `toPng` call; `dispose()` closes it. This is the absolute-max-fidelity path
|
|
168
|
-
* (Chrome-grade shaping, fallback, ligatures, color emoji) — opt-in only.
|
|
169
|
-
*/
|
|
170
|
-
function createBrowserRasterizer(playwright) {
|
|
171
|
-
let browserPromise = null;
|
|
172
|
-
const getBrowser = () => {
|
|
173
|
-
if (!browserPromise) browserPromise = playwright.chromium.launch({
|
|
174
|
-
headless: true,
|
|
175
|
-
args: ["--force-color-profile=srgb"]
|
|
176
|
-
}).catch((cause) => {
|
|
177
|
-
browserPromise = null;
|
|
178
|
-
throw new Error("--renderer browser could not launch Chromium. Install the browser binary:\n npx playwright install chromium", { cause });
|
|
179
|
-
});
|
|
180
|
-
return browserPromise;
|
|
181
|
-
};
|
|
182
|
-
const shot = async (svg, scale) => {
|
|
183
|
-
const { width, height } = browserSvgSize(svg);
|
|
184
|
-
const embedded = await ensureEmbeddedFonts(svg);
|
|
185
|
-
const page = await (await getBrowser()).newPage({
|
|
186
|
-
viewport: {
|
|
187
|
-
width,
|
|
188
|
-
height
|
|
189
|
-
},
|
|
190
|
-
deviceScaleFactor: Math.max(1, scale)
|
|
191
|
-
});
|
|
192
|
-
try {
|
|
193
|
-
await page.setContent(browserHtml(embedded, width, height), { waitUntil: "load" });
|
|
194
|
-
await page.evaluate(() => document.fonts.ready);
|
|
195
|
-
const buf = await page.screenshot({
|
|
196
|
-
type: "png",
|
|
197
|
-
omitBackground: false
|
|
198
|
-
});
|
|
199
|
-
return {
|
|
200
|
-
png: new Uint8Array(buf),
|
|
201
|
-
width: Math.round(width * Math.max(1, scale)),
|
|
202
|
-
height: Math.round(height * Math.max(1, scale))
|
|
203
|
-
};
|
|
204
|
-
} finally {
|
|
205
|
-
await page.close();
|
|
206
|
-
}
|
|
207
|
-
};
|
|
208
|
-
return {
|
|
209
|
-
kind: "browser",
|
|
210
|
-
async rasterize(svg, scale) {
|
|
211
|
-
const { png, width, height } = await shot(svg, scale);
|
|
212
|
-
const UPNG = await import("./UPNG-Bo33r8rA.mjs").then((m) => /* @__PURE__ */ __toESM(m.default, 1));
|
|
213
|
-
const ab = png.buffer.slice(png.byteOffset, png.byteOffset + png.byteLength);
|
|
214
|
-
const decoded = UPNG.decode(ab);
|
|
215
|
-
const rgbaFrames = UPNG.toRGBA8(decoded);
|
|
216
|
-
return {
|
|
217
|
-
pixels: new Uint8Array(rgbaFrames[0] ?? /* @__PURE__ */ new ArrayBuffer(0)),
|
|
218
|
-
width: decoded.width,
|
|
219
|
-
height: decoded.height
|
|
220
|
-
};
|
|
221
|
-
},
|
|
222
|
-
async toPng(svg, scale) {
|
|
223
|
-
return (await shot(svg, scale)).png;
|
|
224
|
-
},
|
|
225
|
-
async dispose() {
|
|
226
|
-
if (!browserPromise) return;
|
|
227
|
-
const pending = browserPromise;
|
|
228
|
-
browserPromise = null;
|
|
229
|
-
try {
|
|
230
|
-
await (await pending).close();
|
|
231
|
-
} catch {}
|
|
232
|
-
}
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* Resolve a {@link RendererKind} to a concrete {@link Rasterizer}.
|
|
237
|
-
*
|
|
238
|
-
* - `canvas` — `@napi-rs/canvas`; throws a clear error if the binding is absent.
|
|
239
|
-
* - `resvg` — `@resvg/resvg-js`; throws a clear error if it is absent.
|
|
240
|
-
* - `browser` — headless Chromium via the optional `playwright` package;
|
|
241
|
-
* throws a clear install hint if absent. Never reached from `auto`.
|
|
242
|
-
* - `auto` — `canvas` when its binding loads, else `resvg`.
|
|
243
|
-
*/
|
|
244
|
-
async function selectRasterizer(kind = "auto") {
|
|
245
|
-
if (kind === "canvas") try {
|
|
246
|
-
return createCanvasRasterizer(await loadCanvas());
|
|
247
|
-
} catch {
|
|
248
|
-
throw new Error("--renderer canvas requires @napi-rs/canvas. Install it:\n bun add @napi-rs/canvas");
|
|
249
|
-
}
|
|
250
|
-
if (kind === "resvg") try {
|
|
251
|
-
return createResvgRasterizer(await loadResvg());
|
|
252
|
-
} catch {
|
|
253
|
-
throw new Error("--renderer resvg requires @resvg/resvg-js. Install it:\n bun add @resvg/resvg-js");
|
|
254
|
-
}
|
|
255
|
-
if (kind === "swash") try {
|
|
256
|
-
return await createSwashRasterizer(await loadSwash());
|
|
257
|
-
} catch (e) {
|
|
258
|
-
throw new Error(`--renderer swash requires the @termless/swash-render native binding. Build it:
|
|
259
|
-
cd packages/swash-render && bun run build:prebuild
|
|
260
|
-
\nOriginal error: ${e instanceof Error ? e.message : String(e)}`);
|
|
261
|
-
}
|
|
262
|
-
if (kind === "browser") try {
|
|
263
|
-
return createBrowserRasterizer(await loadPlaywright());
|
|
264
|
-
} catch (e) {
|
|
265
|
-
throw new Error(`--renderer browser requires the optional playwright package. Install it:
|
|
266
|
-
bun add -d playwright
|
|
267
|
-
npx playwright install chromium
|
|
268
|
-
\nOriginal error: ${e instanceof Error ? e.message : String(e)}`);
|
|
269
|
-
}
|
|
270
|
-
try {
|
|
271
|
-
return await createSwashRasterizer(await loadSwash());
|
|
272
|
-
} catch {
|
|
273
|
-
try {
|
|
274
|
-
return createResvgRasterizer(await loadResvg());
|
|
275
|
-
} catch {
|
|
276
|
-
try {
|
|
277
|
-
return createCanvasRasterizer(await loadCanvas());
|
|
278
|
-
} catch {
|
|
279
|
-
throw new Error("createGif/screenshot requires a renderer. Install one:\n @termless/swash-render (swash — cell-native, highest fidelity)\n bun add @resvg/resvg-js (resvg — cross-platform fallback)\n bun add @napi-rs/canvas (canvas — last-resort fallback)");
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
var resvgModule, canvasModule, swashModule, SWASH_EDGE_PADDING, playwrightModule;
|
|
285
|
-
var init_rasterizer = __esmMin((() => {
|
|
286
|
-
init_fonts();
|
|
287
|
-
resvgModule = null;
|
|
288
|
-
canvasModule = null;
|
|
289
|
-
swashModule = null;
|
|
290
|
-
SWASH_EDGE_PADDING = 4;
|
|
291
|
-
playwrightModule = null;
|
|
292
|
-
}));
|
|
293
|
-
//#endregion
|
|
294
|
-
export { selectRasterizer as n, init_rasterizer as t };
|
|
295
|
-
|
|
296
|
-
//# sourceMappingURL=rasterizer-CpEhJvdR.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rasterizer-CpEhJvdR.mjs","names":[],"sources":["../../termless/src/view/rasterizer.ts"],"sourcesContent":["/**\n * The **renderer** — how termless turns an SVG terminal frame into pixels.\n *\n * A *renderer* rasterizes the vector SVG produced by `screenshotSvg` into an\n * RGBA bitmap. termless ships two:\n *\n * - **`canvas`** — `@napi-rs/canvas` (Skia). High fidelity — truecolor, real\n * glyph shaping. Needs the native `@napi-rs/canvas` binding.\n * - **`resvg`** — `@resvg/resvg-js`. Cross-platform, no native binding,\n * lower fidelity.\n * - **`swash`** — `@termless/swash-render` (pure-Rust swash via napi-rs).\n * Browser-grade text + **color emoji** (sbix / CBDT / COLR), ~1.3 MB native\n * binding. swash rasterizes the *cell grid* directly (no SVG round-trip), so\n * its `Rasterizer` exposes {@link Rasterizer.rasterizeCells}; the SVG-input\n * methods delegate to `resvg` (swash does not parse SVG). The cells path is\n * the fidelity win — `Terminal.screenshot({ renderer: \"swash\" })` uses it.\n * - **`browser`** — headless Chromium via Playwright. The **highest-fidelity**\n * path: a real browser text engine gives Chrome-identical shaping, font\n * fallback, ligatures, and color emoji with zero per-glyph work. Playwright\n * is an **optional** dependency — `browser` throws a clear install hint when\n * it is absent, and is **never** the `auto` default (Chromium is a heavy,\n * hundreds-of-MB dependency). Opt-in only, for marketing assets and as a\n * fidelity oracle against `canvas`.\n *\n * `auto` (the default) uses `canvas` when its native binding loads, and falls\n * back to `resvg` otherwise. `--renderer` is a *force* override — the common\n * case never touches it. `browser` is opt-in only and never reached by `auto`.\n *\n * Raster outputs (`.png` / `.gif` / `.apng`) consult the renderer. `.svg` is\n * vector and `.html` defers to the browser canvas — neither rasterizes\n * server-side, so neither involves a renderer.\n */\n\nimport { bundledFontFiles, bundledFontsDir, BUNDLED_FONTS } from \"../render/fonts.ts\"\nimport { existsSync } from \"node:fs\"\nimport { join } from \"node:path\"\n\n/** How a raster frame is rasterized from SVG. */\nexport type RendererKind = \"canvas\" | \"resvg\" | \"swash\" | \"browser\" | \"auto\"\n\n/** A terminal whose cell grid a {@link Rasterizer} can read directly. */\nexport type CellGridSource = import(\"../terminal/types.ts\").TerminalReadable\n\n/** A rasterized RGBA bitmap. */\nexport interface RasterBitmap {\n /** RGBA pixel bytes, row-major, 4 bytes per pixel. */\n pixels: Uint8Array\n /** Bitmap width in pixels. */\n width: number\n /** Bitmap height in pixels. */\n height: number\n}\n\n/** A renderer: rasterizes one SVG frame into an RGBA bitmap. */\nexport interface Rasterizer {\n /** The concrete renderer this resolved to (`auto` collapses to one of these). */\n readonly kind: \"canvas\" | \"resvg\" | \"swash\" | \"browser\"\n /** Rasterize `svg` at `scale`× into an RGBA bitmap. */\n rasterize(svg: string, scale: number): Promise<RasterBitmap>\n /** Rasterize `svg` at `scale`× directly into PNG bytes. */\n toPng(svg: string, scale: number): Promise<Uint8Array>\n /**\n * Rasterize a terminal's cell grid directly into an RGBA bitmap — no SVG\n * round-trip. Present only on the `swash` renderer, whose fidelity edge\n * (color emoji) depends on consuming cells, not a flattened SVG.\n */\n rasterizeCells?(terminal: CellGridSource, scale: number): Promise<RasterBitmap>\n /** Rasterize a terminal's cell grid directly into PNG bytes. */\n cellsToPng?(terminal: CellGridSource, scale: number): Promise<Uint8Array>\n /**\n * Release any long-lived resources the renderer holds. Present only on the\n * `browser` renderer, which keeps a headless-Chromium instance alive across\n * frames — callers that finish a batch (`createGif`, `createApng`) should\n * `await rasterizer.dispose?.()` so Chromium is closed. The pure-native\n * renderers hold nothing and omit it.\n */\n dispose?(): Promise<void>\n}\n\n// =============================================================================\n// resvg renderer\n// =============================================================================\n\nlet resvgModule: { Resvg: any } | null = null\n\nasync function loadResvg(): Promise<{ Resvg: any }> {\n if (resvgModule) return resvgModule\n resvgModule = (await import(\"@resvg/resvg-js\")) as { Resvg: any }\n return resvgModule\n}\n\nfunction createResvgRasterizer(Resvg: { Resvg: any }): Rasterizer {\n const fontFiles = bundledFontFiles()\n const build = (svg: string, scale: number) =>\n new Resvg.Resvg(svg, {\n fitTo: { mode: \"zoom\" as const, value: scale },\n // Bundled emoji + symbol fallback faces — without these, resvg renders\n // emoji / rarer symbol code points as `.notdef` tofu.\n font: { loadSystemFonts: true, defaultFontFamily: \"Menlo\", fontFiles },\n })\n return {\n kind: \"resvg\",\n async rasterize(svg, scale) {\n const rendered = build(svg, scale).render()\n return { pixels: new Uint8Array(rendered.pixels), width: rendered.width, height: rendered.height }\n },\n async toPng(svg, scale) {\n return build(svg, scale).render().asPng()\n },\n }\n}\n\n// =============================================================================\n// canvas renderer (@napi-rs/canvas — Skia)\n// =============================================================================\n\nlet canvasModule: { createCanvas: any; Image: any } | null = null\n\nasync function loadCanvas(): Promise<{ createCanvas: any; Image: any }> {\n if (canvasModule) return canvasModule\n const mod = (await import(\"@napi-rs/canvas\")) as {\n createCanvas: any\n Image: any\n GlobalFonts: { registerFromPath(path: string, family: string): void }\n }\n // Register the bundled fallback faces process-wide BEFORE any SVG with text\n // is rasterized — without these, `@napi-rs/canvas` falls back to system\n // fonts and every symbol / emoji / box-drawing glyph renders as tofu. The\n // `resvg` rasterizer wires the same faces via `font.fontFiles`; this is the\n // canvas-side equivalent. Idempotent (registerFromPath is keyed by family).\n const dir = bundledFontsDir()\n for (const { file, family } of BUNDLED_FONTS) {\n const path = join(dir, file)\n if (existsSync(path)) mod.GlobalFonts.registerFromPath(path, family)\n }\n canvasModule = mod\n return canvasModule\n}\n\n/** Read the intrinsic `width`/`height` from an SVG's root attributes. */\nfunction svgIntrinsicSize(svg: string): { width: number; height: number } {\n const w = svg.match(/<svg[^>]*\\bwidth=\"([\\d.]+)\"/)?.[1]\n const h = svg.match(/<svg[^>]*\\bheight=\"([\\d.]+)\"/)?.[1]\n return { width: w ? Math.round(Number(w)) : 0, height: h ? Math.round(Number(h)) : 0 }\n}\n\nfunction createCanvasRasterizer(mod: { createCanvas: any; Image: any }): Rasterizer {\n const draw = (svg: string, scale: number) => {\n const img = new mod.Image()\n img.src = Buffer.from(svg)\n const intrinsic = svgIntrinsicSize(svg)\n const width = Math.max(1, Math.round((img.width || intrinsic.width) * scale))\n const height = Math.max(1, Math.round((img.height || intrinsic.height) * scale))\n const canvas = mod.createCanvas(width, height)\n const ctx = canvas.getContext(\"2d\")\n ctx.drawImage(img, 0, 0, width, height)\n return { canvas, width, height }\n }\n return {\n kind: \"canvas\",\n async rasterize(svg, scale) {\n const { canvas, width, height } = draw(svg, scale)\n const data = canvas.getContext(\"2d\").getImageData(0, 0, width, height).data\n return { pixels: new Uint8Array(data), width, height }\n },\n async toPng(svg, scale) {\n const { canvas } = draw(svg, scale)\n return new Uint8Array(canvas.toBuffer(\"image/png\"))\n },\n }\n}\n\n// =============================================================================\n// swash renderer (@termless/swash-render — pure-Rust swash via napi-rs)\n// =============================================================================\n\ntype SwashModule = typeof import(\"../../packages/swash-render/src/index.ts\")\n\nlet swashModule: SwashModule | null = null\n\nasync function loadSwash(): Promise<SwashModule> {\n if (swashModule) return swashModule\n const mod = (await import(\"../../packages/swash-render/src/index.ts\")) as SwashModule\n // Probe the native binding now so `selectRasterizer` can fail fast.\n if (!mod.swashRenderAvailable()) {\n throw new Error(\"@termless/swash-render native binding is not built\")\n }\n swashModule = mod\n return mod\n}\n\n/**\n * The swash rasterizer. Its fidelity edge — color emoji — lives in the\n * **cells path** ({@link Rasterizer.rasterizeCells}); swash does not parse\n * SVG, so the SVG-input methods delegate to `resvg` as a faithful fallback\n * for the SVG-based gif / apng pipelines.\n */\nconst SWASH_EDGE_PADDING = 4\n\nasync function createSwashRasterizer(mod: SwashModule): Promise<Rasterizer> {\n // resvg is the SVG-input fallback — swash only consumes the cell grid.\n const svgFallback = createResvgRasterizer(await loadResvg())\n const toBitmap = (terminal: CellGridSource, scale: number): RasterBitmap => {\n const s = Math.max(1, scale)\n const bmp = mod.renderCells(terminal, {\n cellWidth: 9.6 * s,\n cellHeight: 20 * s,\n padding: Math.round(SWASH_EDGE_PADDING * s),\n })\n return { pixels: new Uint8Array(bmp.pixels), width: bmp.width, height: bmp.height }\n }\n return {\n kind: \"swash\",\n rasterize: svgFallback.rasterize,\n toPng: svgFallback.toPng,\n async rasterizeCells(terminal, scale) {\n return toBitmap(terminal, scale)\n },\n async cellsToPng(terminal, scale) {\n const { pixels, width, height } = toBitmap(terminal, scale)\n const UPNG = (await import(\"upng-js\")) as typeof import(\"upng-js\")\n const ab = pixels.buffer.slice(pixels.byteOffset, pixels.byteOffset + pixels.byteLength) as ArrayBuffer\n return new Uint8Array(UPNG.encode([ab], width, height, 0))\n },\n }\n}\n\n// =============================================================================\n// browser renderer (headless Chromium via Playwright)\n// =============================================================================\n\n/**\n * The shape of the `playwright` module's `chromium` namespace we depend on —\n * a structural subset, so the import does not require Playwright's types to\n * be installed (Playwright is an optional dependency).\n */\ninterface PlaywrightChromium {\n launch(opts?: { headless?: boolean; args?: string[] }): Promise<PlaywrightBrowser>\n}\ninterface PlaywrightBrowser {\n newPage(opts?: { viewport?: { width: number; height: number }; deviceScaleFactor?: number }): Promise<PlaywrightPage>\n close(): Promise<void>\n}\ninterface PlaywrightPage {\n setContent(html: string, opts?: { waitUntil?: string }): Promise<void>\n evaluate(fn: () => unknown): Promise<unknown>\n screenshot(opts?: { type?: \"png\"; omitBackground?: boolean }): Promise<Buffer>\n close(): Promise<void>\n}\n\nlet playwrightModule: { chromium: PlaywrightChromium } | null = null\n\n/**\n * Lazily import `playwright`. Playwright is an **optional** dependency — a\n * default `bun install` omits it. Throws a clear, actionable error if absent,\n * naming both the package install and the browser-download step.\n */\nasync function loadPlaywright(): Promise<{ chromium: PlaywrightChromium }> {\n if (playwrightModule) return playwrightModule\n // Indirect specifier so bundlers / static analysers do not treat `playwright`\n // as a hard dependency to resolve at build time.\n const specifier = \"playwright\"\n playwrightModule = (await import(specifier)) as { chromium: PlaywrightChromium }\n return playwrightModule\n}\n\n/** Read intrinsic width/height from an SVG root — reused for the viewport. */\nfunction browserSvgSize(svg: string): { width: number; height: number } {\n const { width, height } = svgIntrinsicSize(svg)\n return { width: Math.max(1, width), height: Math.max(1, height) }\n}\n\n/**\n * Inline the bundled `@font-face` faces into an SVG if it does not already\n * carry them. The `record` GIF/APNG pipeline produces frame SVGs without\n * `embedFonts`, so Chromium would otherwise fall back to host fonts (or tofu\n * for symbol / emoji code points). Embedding makes the page deterministic.\n */\nasync function ensureEmbeddedFonts(svg: string): Promise<string> {\n if (svg.includes(\"@font-face\")) return svg\n const { embeddedFontFaceDefs } = await import(\"../render/svg.ts\")\n const defs = embeddedFontFaceDefs()\n if (!defs) return svg\n // Insert the <defs> block immediately after the opening <svg ...> tag.\n return svg.replace(/(<svg[^>]*>)/, `$1${defs}`)\n}\n\n/** Wrap an SVG in a minimal full-bleed HTML document for Chromium. */\nfunction browserHtml(svg: string, width: number, height: number): string {\n return (\n `<!doctype html><html><head><meta charset=\"utf-8\"><style>` +\n `html,body{margin:0;padding:0;width:${width}px;height:${height}px;overflow:hidden;background:transparent}` +\n `svg{display:block}` +\n `</style></head><body>${svg}</body></html>`\n )\n}\n\n/**\n * The `browser` rasterizer — rasterizes SVG frames via headless Chromium.\n *\n * The browser instance is launched once and reused across every `rasterize` /\n * `toPng` call; `dispose()` closes it. This is the absolute-max-fidelity path\n * (Chrome-grade shaping, fallback, ligatures, color emoji) — opt-in only.\n */\nfunction createBrowserRasterizer(playwright: { chromium: PlaywrightChromium }): Rasterizer {\n let browserPromise: Promise<PlaywrightBrowser> | null = null\n\n const getBrowser = (): Promise<PlaywrightBrowser> => {\n if (!browserPromise) {\n browserPromise = playwright.chromium\n .launch({ headless: true, args: [\"--force-color-profile=srgb\"] })\n .catch((cause: unknown) => {\n browserPromise = null\n throw new Error(\n \"--renderer browser could not launch Chromium. Install the browser binary:\\n\" +\n \" npx playwright install chromium\",\n { cause },\n )\n })\n }\n return browserPromise\n }\n\n const shot = async (svg: string, scale: number): Promise<{ png: Uint8Array; width: number; height: number }> => {\n const { width, height } = browserSvgSize(svg)\n const embedded = await ensureEmbeddedFonts(svg)\n const browser = await getBrowser()\n const page = await browser.newPage({\n viewport: { width, height },\n deviceScaleFactor: Math.max(1, scale),\n })\n try {\n await page.setContent(browserHtml(embedded, width, height), { waitUntil: \"load\" })\n // Block until embedded @font-face faces have finished loading — without\n // this, the first frames screenshot mid-font-swap (FOUT) and glyphs\n // render in a fallback face.\n await page.evaluate(() => (document as { fonts: { ready: Promise<unknown> } }).fonts.ready)\n const buf = await page.screenshot({ type: \"png\", omitBackground: false })\n return {\n png: new Uint8Array(buf),\n width: Math.round(width * Math.max(1, scale)),\n height: Math.round(height * Math.max(1, scale)),\n }\n } finally {\n await page.close()\n }\n }\n\n return {\n kind: \"browser\",\n async rasterize(svg, scale) {\n // Decode the PNG back to RGBA via upng — the GIF/APNG encoders consume\n // raw pixels, not PNG bytes.\n const { png, width, height } = await shot(svg, scale)\n const UPNG = (await import(\"upng-js\")) as typeof import(\"upng-js\")\n const ab = png.buffer.slice(png.byteOffset, png.byteOffset + png.byteLength) as ArrayBuffer\n const decoded = UPNG.decode(ab)\n const rgbaFrames = UPNG.toRGBA8(decoded)\n return {\n pixels: new Uint8Array(rgbaFrames[0] ?? new ArrayBuffer(0)),\n width: decoded.width,\n height: decoded.height,\n }\n },\n async toPng(svg, scale) {\n return (await shot(svg, scale)).png\n },\n async dispose() {\n if (!browserPromise) return\n const pending = browserPromise\n browserPromise = null\n try {\n await (await pending).close()\n } catch {\n // Browser may have already exited — nothing to release.\n }\n },\n }\n}\n\n// =============================================================================\n// Selection\n// =============================================================================\n\n/**\n * Resolve a {@link RendererKind} to a concrete {@link Rasterizer}.\n *\n * - `canvas` — `@napi-rs/canvas`; throws a clear error if the binding is absent.\n * - `resvg` — `@resvg/resvg-js`; throws a clear error if it is absent.\n * - `browser` — headless Chromium via the optional `playwright` package;\n * throws a clear install hint if absent. Never reached from `auto`.\n * - `auto` — `canvas` when its binding loads, else `resvg`.\n */\nexport async function selectRasterizer(kind: RendererKind = \"auto\"): Promise<Rasterizer> {\n if (kind === \"canvas\") {\n try {\n return createCanvasRasterizer(await loadCanvas())\n } catch {\n throw new Error(\"--renderer canvas requires @napi-rs/canvas. Install it:\\n bun add @napi-rs/canvas\")\n }\n }\n if (kind === \"resvg\") {\n try {\n return createResvgRasterizer(await loadResvg())\n } catch {\n throw new Error(\"--renderer resvg requires @resvg/resvg-js. Install it:\\n bun add @resvg/resvg-js\")\n }\n }\n if (kind === \"swash\") {\n try {\n return await createSwashRasterizer(await loadSwash())\n } catch (e) {\n throw new Error(\n \"--renderer swash requires the @termless/swash-render native binding. Build it:\\n\" +\n \" cd packages/swash-render && bun run build:prebuild\\n\" +\n `\\nOriginal error: ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n }\n if (kind === \"browser\") {\n try {\n return createBrowserRasterizer(await loadPlaywright())\n } catch (e) {\n throw new Error(\n \"--renderer browser requires the optional playwright package. Install it:\\n\" +\n \" bun add -d playwright\\n\" +\n \" npx playwright install chromium\\n\" +\n `\\nOriginal error: ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n }\n // auto — prefer swash, fall back to resvg, then canvas.\n // `browser` is opt-in only: never reached from `auto` (Chromium is heavy).\n //\n // swash is the highest-fidelity renderer: it consumes the cell grid\n // directly (no SVG round-trip) and composites full-colour emoji from their\n // native colour tables. Its bundled font chain — JetBrains Mono, Noto Sans\n // Symbols 2, Symbols Nerd Font, Noto Emoji — covers box-drawing, sigil\n // icons, Nerd Font glyphs and emoji, so a km board renders cleanly\n // (verified). For SVG-only inputs swash's `rasterize` delegates to resvg,\n // so `auto`→swash is never worse than resvg and strictly better whenever a\n // frame carries a cell snapshot (the `record` GIF path).\n //\n // resvg is the cross-platform fallback (no native build): handed the same\n // bundled fonts via `font.fontFiles`, it renders the SVG path correctly.\n // The `canvas` rasterizer is last — its `drawImage` SVG path ignores\n // registered fonts, so glyphs the system font lacks render as tofu.\n try {\n return await createSwashRasterizer(await loadSwash())\n } catch {\n try {\n return createResvgRasterizer(await loadResvg())\n } catch {\n try {\n return createCanvasRasterizer(await loadCanvas())\n } catch {\n throw new Error(\n \"createGif/screenshot requires a renderer. Install one:\\n\" +\n \" @termless/swash-render (swash — cell-native, highest fidelity)\\n\" +\n \" bun add @resvg/resvg-js (resvg — cross-platform fallback)\\n\" +\n \" bun add @napi-rs/canvas (canvas — last-resort fallback)\",\n )\n }\n }\n }\n}\n"],"mappings":"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"}
|