@crvy/rprtr 0.3.2 → 0.3.3

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.
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/rendering.ts
21
+ var rendering_exports = {};
22
+ __export(rendering_exports, {
23
+ DETERMINISTIC_CHROMIUM_ARGS: () => DETERMINISTIC_CHROMIUM_ARGS,
24
+ DISABLE_LCD_TEXT_ARG: () => DISABLE_LCD_TEXT_ARG,
25
+ deterministicChromiumLaunchOptions: () => deterministicChromiumLaunchOptions,
26
+ deterministicLaunchOptions: () => deterministicLaunchOptions
27
+ });
28
+ module.exports = __toCommonJS(rendering_exports);
29
+
30
+ // src/fontconfig.ts
31
+ var import_fs = require("fs");
32
+ var import_os = require("os");
33
+ var import_path = require("path");
34
+ var GRAYSCALE_MATCH = ` <match target="font">
35
+ <edit name="rgba" mode="assign"><const>none</const></edit>
36
+ </match>`;
37
+ var HEADER = `<?xml version="1.0"?>
38
+ <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
39
+ <!-- Written by crvy-rprtr: pins grayscale text antialiasing for screenshot determinism. -->`;
40
+ var GRAYSCALE_FONTCONFIG_XML = `${HEADER}
41
+ <fontconfig>
42
+ ${GRAYSCALE_MATCH}
43
+ </fontconfig>
44
+ `;
45
+ function grayscaleRootFontconfigXml(systemConfigPath) {
46
+ return `${HEADER}
47
+ <fontconfig>
48
+ <include ignore_missing="no">${escapeXml(systemConfigPath)}</include>
49
+ ${GRAYSCALE_MATCH}
50
+ </fontconfig>
51
+ `;
52
+ }
53
+ function escapeXml(value) {
54
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
55
+ }
56
+ var SYSTEM_FONTCONFIG_PATHS = ["/etc/fonts/fonts.conf", "/usr/local/etc/fonts/fonts.conf"];
57
+ function rootFontconfigPath() {
58
+ return (0, import_path.join)((0, import_os.tmpdir)(), "crvy-rprtr", "fonts.conf");
59
+ }
60
+ function resolveSystemFontconfig(env = process.env, exists = import_fs.existsSync) {
61
+ const ours = rootFontconfigPath();
62
+ const candidates = [
63
+ env.FONTCONFIG_FILE,
64
+ env.FONTCONFIG_PATH === void 0 ? void 0 : (0, import_path.join)(env.FONTCONFIG_PATH, "fonts.conf"),
65
+ ...SYSTEM_FONTCONFIG_PATHS
66
+ ];
67
+ for (const candidate of candidates) {
68
+ if (candidate === void 0 || candidate === ours) continue;
69
+ if (exists(candidate)) return candidate;
70
+ }
71
+ return null;
72
+ }
73
+ function ensureRootFontconfig(systemConfigPath) {
74
+ const path = rootFontconfigPath();
75
+ (0, import_fs.mkdirSync)((0, import_path.join)((0, import_os.tmpdir)(), "crvy-rprtr"), { recursive: true });
76
+ const staging = `${path}.${process.pid}.tmp`;
77
+ (0, import_fs.writeFileSync)(staging, grayscaleRootFontconfigXml(systemConfigPath), "utf8");
78
+ (0, import_fs.renameSync)(staging, path);
79
+ return path;
80
+ }
81
+ function grayscaleFontconfigEnv(baseEnv = process.env, options = {}) {
82
+ if ((options.platform ?? process.platform) !== "linux") return null;
83
+ const systemConfig = resolveSystemFontconfig(baseEnv, options.exists);
84
+ if (systemConfig === null) return null;
85
+ return { FONTCONFIG_FILE: (options.writeConfig ?? ensureRootFontconfig)(systemConfig) };
86
+ }
87
+
88
+ // src/rendering.ts
89
+ var DISABLE_LCD_TEXT_ARG = "--disable-lcd-text";
90
+ var DETERMINISTIC_CHROMIUM_ARGS = [DISABLE_LCD_TEXT_ARG];
91
+ function deterministicChromiumLaunchOptions(base = {}) {
92
+ const args = base.args ?? [];
93
+ const missing = DETERMINISTIC_CHROMIUM_ARGS.filter((arg) => !args.includes(arg));
94
+ return { ...base, args: [...args, ...missing] };
95
+ }
96
+ function deterministicLaunchOptions(base = {}, options = {}) {
97
+ const { fontRendering = "grayscale", ...envOptions } = options;
98
+ if (fontRendering === "inherit") return base;
99
+ const baseEnv = { ...process.env, ...base.env };
100
+ const fontconfig = grayscaleFontconfigEnv(baseEnv, envOptions);
101
+ if (fontconfig === null) return base;
102
+ const env = {};
103
+ for (const [key, value] of Object.entries({ ...baseEnv, ...fontconfig })) {
104
+ if (value !== void 0) env[key] = value;
105
+ }
106
+ return { ...base, env };
107
+ }
108
+ // Annotate the CommonJS export names for ESM import in node:
109
+ 0 && (module.exports = {
110
+ DETERMINISTIC_CHROMIUM_ARGS,
111
+ DISABLE_LCD_TEXT_ARG,
112
+ deterministicChromiumLaunchOptions,
113
+ deterministicLaunchOptions
114
+ });
@@ -0,0 +1,61 @@
1
+ import type { LaunchOptions } from '@playwright/test';
2
+ import { type GrayscaleFontconfigEnvOptions } from './fontconfig.ts';
3
+ /**
4
+ * Chromium switch that turns off subpixel (LCD RGB) text antialiasing and falls back to
5
+ * grayscale AA.
6
+ *
7
+ * Why it is needed even when every run shares one docker image: on Linux Chromium takes the
8
+ * text AA mode from **fontconfig**, so any second browser with a different fontconfig — a
9
+ * system Chromium via `executablePath`, a distro package, an agent-provided binary — renders
10
+ * the same page with colored fringes on every glyph. Glyph metrics stay identical, so the
11
+ * diff is invisible to the eye but fatal to the comparator: ~3% of a text-heavy screenshot
12
+ * differs, with channel deltas up to 100. Baselines then flip back and forth between the two
13
+ * environments, one "update baselines" commit at a time.
14
+ *
15
+ * The same rendering is what crvy-rprtr forces in its own run modes (there through
16
+ * fontconfig, since a reporter cannot pass browser args); the mechanisms were verified to
17
+ * produce byte-identical screenshots.
18
+ */
19
+ export declare const DISABLE_LCD_TEXT_ARG = "--disable-lcd-text";
20
+ /** Chromium args that pin text rasterization so it does not depend on the environment. */
21
+ export declare const DETERMINISTIC_CHROMIUM_ARGS: readonly string[];
22
+ /** `'inherit'` gives the browser back whatever the environment renders by default. */
23
+ export type FontRendering = 'grayscale' | 'inherit';
24
+ export interface DeterministicLaunchOptions extends GrayscaleFontconfigEnvOptions {
25
+ /** Default `'grayscale'`. `'inherit'` makes the helper a no-op. */
26
+ fontRendering?: FontRendering;
27
+ }
28
+ /**
29
+ * Merges {@link DETERMINISTIC_CHROMIUM_ARGS} into existing launch options, keeping the
30
+ * caller's own args:
31
+ *
32
+ * ```ts
33
+ * use: { launchOptions: deterministicChromiumLaunchOptions() }
34
+ * ```
35
+ *
36
+ * Chromium-only by construction — Firefox exits on unknown command-line flags. Prefer
37
+ * {@link deterministicLaunchOptions}, which pins the same rendering for every browser;
38
+ * this one stays for configs that cannot set browser env vars.
39
+ *
40
+ * Switching an existing suite to it invalidates baselines that were captured with subpixel
41
+ * AA — regenerate them once, in the same image, right after adding the option.
42
+ */
43
+ export declare function deterministicChromiumLaunchOptions(base?: LaunchOptions): LaunchOptions;
44
+ /**
45
+ * Launch options that pin grayscale text antialiasing for **any** browser, by pointing the
46
+ * browser process at a generated fontconfig root config:
47
+ *
48
+ * ```ts
49
+ * use: { launchOptions: deterministicLaunchOptions() }
50
+ * ```
51
+ *
52
+ * Equivalent to `--disable-lcd-text` for Chromium (verified byte-identical) and a no-op for
53
+ * the Playwright builds of Firefox and WebKit, which never rasterize with subpixel AA — so a
54
+ * multi-browser suite can apply it uniformly. Outside Linux it returns `base` unchanged.
55
+ *
56
+ * Baselines captured with subpixel AA have to be regenerated once after adding it. Opt out
57
+ * with `{ fontRendering: 'inherit' }` when faithful desktop text matters more than
58
+ * determinism.
59
+ */
60
+ export declare function deterministicLaunchOptions(base?: LaunchOptions, options?: DeterministicLaunchOptions): LaunchOptions;
61
+ //# sourceMappingURL=rendering.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rendering.d.ts","sourceRoot":"","sources":["../src/rendering.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAErD,OAAO,EAA0B,KAAK,6BAA6B,EAAE,MAAM,iBAAiB,CAAA;AAE5F;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,oBAAoB,uBAAuB,CAAA;AAExD,0FAA0F;AAC1F,eAAO,MAAM,2BAA2B,EAAE,SAAS,MAAM,EAA2B,CAAA;AAEpF,sFAAsF;AACtF,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,SAAS,CAAA;AAEnD,MAAM,WAAW,0BAA2B,SAAQ,6BAA6B;IAC/E,mEAAmE;IACnE,aAAa,CAAC,EAAE,aAAa,CAAA;CAC9B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kCAAkC,CAAC,IAAI,GAAE,aAAkB,GAAG,aAAa,CAI1F;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,GAAE,aAAkB,EACxB,OAAO,GAAE,0BAA+B,GACvC,aAAa,CAaf"}
@@ -0,0 +1,30 @@
1
+ import {
2
+ grayscaleFontconfigEnv
3
+ } from "./chunk-7JUICMVX.js";
4
+
5
+ // src/rendering.ts
6
+ var DISABLE_LCD_TEXT_ARG = "--disable-lcd-text";
7
+ var DETERMINISTIC_CHROMIUM_ARGS = [DISABLE_LCD_TEXT_ARG];
8
+ function deterministicChromiumLaunchOptions(base = {}) {
9
+ const args = base.args ?? [];
10
+ const missing = DETERMINISTIC_CHROMIUM_ARGS.filter((arg) => !args.includes(arg));
11
+ return { ...base, args: [...args, ...missing] };
12
+ }
13
+ function deterministicLaunchOptions(base = {}, options = {}) {
14
+ const { fontRendering = "grayscale", ...envOptions } = options;
15
+ if (fontRendering === "inherit") return base;
16
+ const baseEnv = { ...process.env, ...base.env };
17
+ const fontconfig = grayscaleFontconfigEnv(baseEnv, envOptions);
18
+ if (fontconfig === null) return base;
19
+ const env = {};
20
+ for (const [key, value] of Object.entries({ ...baseEnv, ...fontconfig })) {
21
+ if (value !== void 0) env[key] = value;
22
+ }
23
+ return { ...base, env };
24
+ }
25
+ export {
26
+ DETERMINISTIC_CHROMIUM_ARGS,
27
+ DISABLE_LCD_TEXT_ARG,
28
+ deterministicChromiumLaunchOptions,
29
+ deterministicLaunchOptions
30
+ };
@@ -1,3 +1,4 @@
1
+ import type { FontRendering } from '../rendering.ts';
1
2
  import { type DockerOptions } from './docker-launcher.ts';
2
3
  import { type RunMode } from './run-mode.ts';
3
4
  import type { RuntimeWebSocket } from './ws.ts';
@@ -28,6 +29,14 @@ export interface ServerOptions {
28
29
  runMode?: RunMode;
29
30
  /** Docker backend settings; only used when the resolved mode is 'docker'. */
30
31
  docker?: DockerOptions;
32
+ /**
33
+ * Text antialiasing for UI-triggered runs in either mode. `'grayscale'` (default) pins
34
+ * grayscale AA — a fontconfig drop-in in docker mode, a `FONTCONFIG_FILE` override in local
35
+ * mode — so screenshots do not depend on the machine's subpixel settings. `'inherit'`
36
+ * restores Playwright's default, i.e. whatever the environment renders, when faithful
37
+ * desktop text matters more than determinism.
38
+ */
39
+ fontRendering?: FontRendering;
31
40
  }
32
41
  export interface ServerApp {
33
42
  port: number;
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/server/app.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAiBzD,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAA;AAE5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAE/C,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,8BAA8B,CAAC,EAAE,MAAM,CAAA;IACvC,sCAAsC,CAAC,EAAE,MAAM,CAAA;IAC/C,+DAA+D;IAC/D,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,aAAa,CAAA;CACvB;AAUD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAA;IAChC,qEAAqE;IACrE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,aAAa,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IAClD,sBAAsB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3D;AAoKD,wBAAsB,eAAe,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,SAAS,CAAC,CAsCrF"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/server/app.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAYpD,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAiBzD,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAA;AAE5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAE/C,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,8BAA8B,CAAC,EAAE,MAAM,CAAA;IACvC,sCAAsC,CAAC,EAAE,MAAM,CAAA;IAC/C,+DAA+D;IAC/D,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,aAAa,CAAA;CAC9B;AAUD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAA;IAChC,qEAAqE;IACrE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,aAAa,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IAClD,sBAAsB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3D;AAqKD,wBAAsB,eAAe,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,SAAS,CAAC,CAsCrF"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Names of `env` entries to forward into the container as name-only `-e NAME` flags.
3
+ * Filters the denylist, Windows noise vars, undefined values, and — on win32 hosts —
4
+ * any var whose value is a Windows absolute path.
5
+ */
6
+ export declare function collectForwardedEnvNames(env: Record<string, string | undefined>, platform: NodeJS.Platform): string[];
7
+ //# sourceMappingURL=docker-env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker-env.d.ts","sourceRoot":"","sources":["../../src/server/docker-env.ts"],"names":[],"mappings":"AA4CA;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,GAAG,MAAM,EAAE,CASrH"}
@@ -6,6 +6,17 @@ export interface DockerOptions {
6
6
  platform?: 'linux/amd64' | 'linux/arm64';
7
7
  command?: string[];
8
8
  extraArgs?: string[];
9
+ /**
10
+ * Text antialiasing inside the container. `'grayscale'` (default) mounts a fontconfig
11
+ * drop-in that switches Chromium to grayscale AA, so screenshots do not depend on the
12
+ * image's subpixel settings; `'inherit'` leaves the image as it is.
13
+ *
14
+ * Local run mode pins the same rendering through `FONTCONFIG_FILE`, and a consumer's own
15
+ * CI, which runs Playwright directly, matches both with `deterministicLaunchOptions()` from
16
+ * `@crvy/rprtr/rendering`. Baselines captured with subpixel AA have to be regenerated once
17
+ * after the switch.
18
+ */
19
+ fontRendering?: 'grayscale' | 'inherit';
9
20
  }
10
21
  export interface DockerLauncherOptions {
11
22
  port: number;
@@ -1 +1 @@
1
- {"version":3,"file":"docker-launcher.d.ts","sourceRoot":"","sources":["../../src/server/docker-launcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAWL,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,IAAI,EACV,MAAM,qBAAqB,CAAA;AAG5B,OAAO,KAAK,EAA4B,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE9E,eAAO,MAAM,eAAe,UAAU,CAAA;AAKtC,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,aAAa,GAAG,aAAa,CAAA;IACxC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAA;IACrD,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACxC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;CAC3B;AAyBD,qBAAa,sBAAuB,SAAQ,KAAK;;CAKhD;AAgMD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,WAAW,CAahF"}
1
+ {"version":3,"file":"docker-launcher.d.ts","sourceRoot":"","sources":["../../src/server/docker-launcher.ts"],"names":[],"mappings":"AACA,OAAO,EAWL,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,IAAI,EACV,MAAM,qBAAqB,CAAA;AAI5B,OAAO,KAAK,EAA4B,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE9E,eAAO,MAAM,eAAe,UAAU,CAAA;AAKtC,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,aAAa,GAAG,aAAa,CAAA;IACxC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;CACxC;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAA;IACrD,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACxC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;CAC3B;AAED,qBAAa,sBAAuB,SAAQ,KAAK;;CAKhD;AAmMD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,WAAW,CAahF"}
@@ -0,0 +1,22 @@
1
+ import { GRAYSCALE_FONTCONFIG_XML } from '../fontconfig.ts';
2
+ export { GRAYSCALE_FONTCONFIG_XML };
3
+ /**
4
+ * Mount point inside the container. `99-` keeps it last in `conf.d`, after the distro's own
5
+ * subpixel and hinting drop-ins.
6
+ *
7
+ * Docker run mode pins AA one level below the browser because a reporter cannot pass browser
8
+ * args — the same reason local mode goes through `FONTCONFIG_FILE` (`src/fontconfig.ts`).
9
+ * Inside a container the drop-in is the simpler half: the image's own `conf.d` is right there
10
+ * to write into, so nothing has to be re-included.
11
+ */
12
+ export declare const CONTAINER_FONTCONFIG_PATH = "/etc/fonts/conf.d/99-crvy-rprtr-grayscale.conf";
13
+ /** Stable host path, so repeated runs reuse one file instead of littering the temp dir. */
14
+ export declare function hostFontconfigPath(): string;
15
+ /**
16
+ * Writes the drop-in and returns its host path. Synchronous and called while the `docker run`
17
+ * arg vector is built: docker silently creates a **directory** in place of a missing bind
18
+ * source, which would mount garbage into `conf.d`, so the file must exist by the time the
19
+ * mount is added — not merely by the time `prepare()` finishes.
20
+ */
21
+ export declare function ensureGrayscaleFontconfig(): string;
22
+ //# sourceMappingURL=fontconfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fontconfig.d.ts","sourceRoot":"","sources":["../../src/server/fontconfig.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAA;AAE3D,OAAO,EAAE,wBAAwB,EAAE,CAAA;AAEnC;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,mDAAmD,CAAA;AAEzF,2FAA2F;AAC3F,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAKlD"}
@@ -1,3 +1,4 @@
1
+ import type { FontRendering } from '../rendering.ts';
1
2
  import { type DockerOptions } from './docker-launcher.ts';
2
3
  import type { RoutesContextOptions } from './routes-context.ts';
3
4
  import { type RunLauncher } from './run-launcher.ts';
@@ -10,6 +11,11 @@ interface ResolveRunBackendOptions {
10
11
  runMode?: RunMode;
11
12
  docker?: DockerOptions;
12
13
  port: number;
14
+ /**
15
+ * Text antialiasing for UI-triggered runs, in either mode. Default `'grayscale'`;
16
+ * `docker.fontRendering` still wins for the docker backend when both are set.
17
+ */
18
+ fontRendering?: FontRendering;
13
19
  }
14
20
  /**
15
21
  * Resolves the run mode (auto-probes the docker daemon once) and selects the
@@ -1 +1 @@
1
- {"version":3,"file":"launcher-resolver.d.ts","sourceRoot":"","sources":["../../src/server/launcher-resolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAyC,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEhG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC/D,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACzE,OAAO,EAAkB,KAAK,OAAO,EAAE,MAAM,eAAe,CAAA;AAE5D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,WAAW,CAAA;IACrB,oBAAoB,EAAE,oBAAoB,CAAA;CAC3C;AAED,UAAU,wBAAwB;IAChC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAqBtG"}
1
+ {"version":3,"file":"launcher-resolver.d.ts","sourceRoot":"","sources":["../../src/server/launcher-resolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACpD,OAAO,EAAyC,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEhG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC/D,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACzE,OAAO,EAAkB,KAAK,OAAO,EAAE,MAAM,eAAe,CAAA;AAE5D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,WAAW,CAAA;IACrB,oBAAoB,EAAE,oBAAoB,CAAA;CAC3C;AAED,UAAU,wBAAwB;IAChC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,aAAa,CAAC,EAAE,aAAa,CAAA;CAC9B;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAyBtG"}
@@ -1,3 +1,5 @@
1
+ import { type GrayscaleFontconfigEnvOptions } from '../fontconfig.ts';
2
+ import type { FontRendering } from '../rendering.ts';
1
3
  import type { RunContext } from './run-controller.ts';
2
4
  export interface LaunchSpec {
3
5
  cmd: string;
@@ -32,8 +34,17 @@ export declare function resolvePlaywrightLaunch(cwd: string, playwrightArgs: str
32
34
  cmd: string;
33
35
  args: string[];
34
36
  };
35
- export declare function buildSpawnEnv(port: number, baseEnv?: Record<string, string | undefined>): Record<string, string | undefined>;
36
- export interface LocalLauncherOptions {
37
+ export interface SpawnEnvOptions extends GrayscaleFontconfigEnvOptions {
38
+ /**
39
+ * Text antialiasing for the browsers this run launches. `'grayscale'` (default) exports a
40
+ * `FONTCONFIG_FILE` override, which Playwright's browsers inherit through the test process,
41
+ * so a local run matches docker run mode without the project touching `launchOptions`;
42
+ * `'inherit'` leaves the environment's own rendering in place.
43
+ */
44
+ fontRendering?: FontRendering;
45
+ }
46
+ export declare function buildSpawnEnv(port: number, baseEnv?: Record<string, string | undefined>, options?: SpawnEnvOptions): Record<string, string | undefined>;
47
+ export interface LocalLauncherOptions extends SpawnEnvOptions {
37
48
  port: number;
38
49
  resolveLaunch?: (cwd: string, playwrightArgs: string[]) => {
39
50
  cmd: string;
@@ -1 +1 @@
1
- {"version":3,"file":"run-launcher.d.ts","sourceRoot":"","sources":["../../src/server/run-launcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAErD,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CACxC;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,UAAU,CAAA;IACf,cAAc,EAAE,MAAM,EAAE,CAAA;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAA;IACjC,kFAAkF;IAClF,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;IAC5B,sFAAsF;IACtF,OAAO,CAAC,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,UAAU,CAAC;QAAC,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACzF,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,UAAU,CAAA;IACxC,8EAA8E;IAC9E,WAAW,CAAC,IAAI,IAAI,CAAA;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAK9G;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GACxD,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CASpC;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;IAC1F,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CACzC;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,WAAW,CAS9E"}
1
+ {"version":3,"file":"run-launcher.d.ts","sourceRoot":"","sources":["../../src/server/run-launcher.ts"],"names":[],"mappings":"AAGA,OAAO,EAA0B,KAAK,6BAA6B,EAAE,MAAM,kBAAkB,CAAA;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAErD,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CACxC;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,UAAU,CAAA;IACf,cAAc,EAAE,MAAM,EAAE,CAAA;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAA;IACjC,kFAAkF;IAClF,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;IAC5B,sFAAsF;IACtF,OAAO,CAAC,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,UAAU,CAAC;QAAC,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACzF,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,UAAU,CAAA;IACxC,8EAA8E;IAC9E,WAAW,CAAC,IAAI,IAAI,CAAA;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAK9G;AAED,MAAM,WAAW,eAAgB,SAAQ,6BAA6B;IACpE;;;;;OAKG;IACH,aAAa,CAAC,EAAE,aAAa,CAAA;CAC9B;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,EACzD,OAAO,GAAE,eAAoB,GAC5B,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAapC;AAED,MAAM,WAAW,oBAAqB,SAAQ,eAAe;IAC3D,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;IAC1F,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CACzC;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,WAAW,CAU9E"}