@vscode/component-explorer-cli 0.1.1-6 → 0.1.1-8
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 +4 -5
- package/dist/commands/compareCommand.d.ts +0 -3
- package/dist/commands/compareCommand.d.ts.map +1 -1
- package/dist/commands/compareCommand.js +18 -210
- package/dist/commands/compareCommand.js.map +1 -1
- package/dist/commands/mcpCommand.d.ts +2 -0
- package/dist/commands/mcpCommand.d.ts.map +1 -1
- package/dist/commands/mcpCommand.js +35 -6
- package/dist/commands/mcpCommand.js.map +1 -1
- package/dist/commands/screenshotCommand.d.ts.map +1 -1
- package/dist/commands/screenshotCommand.js +21 -75
- package/dist/commands/screenshotCommand.js.map +1 -1
- package/dist/commands/serveCommand.d.ts +3 -0
- package/dist/commands/serveCommand.d.ts.map +1 -1
- package/dist/commands/serveCommand.js +52 -3
- package/dist/commands/serveCommand.js.map +1 -1
- package/dist/comparison.d.ts +60 -0
- package/dist/comparison.d.ts.map +1 -0
- package/dist/comparison.js +250 -0
- package/dist/comparison.js.map +1 -0
- package/dist/component-explorer-config.schema.json +183 -0
- package/dist/componentExplorer.d.ts +13 -0
- package/dist/componentExplorer.d.ts.map +1 -1
- package/dist/componentExplorer.js +65 -2
- package/dist/componentExplorer.js.map +1 -1
- package/dist/daemon/DaemonService.d.ts +55 -4
- package/dist/daemon/DaemonService.d.ts.map +1 -1
- package/dist/daemon/DaemonService.js +139 -8
- package/dist/daemon/DaemonService.js.map +1 -1
- package/dist/daemon/lifecycle.js +3 -3
- package/dist/daemon/lifecycle.js.map +1 -1
- package/dist/daemon/pipeClient.js +3 -3
- package/dist/daemon/pipeClient.js.map +1 -1
- package/dist/daemon/pipeServer.js +2 -2
- package/dist/daemon/pipeServer.js.map +1 -1
- package/dist/dependencyInstaller.js +1 -1
- package/dist/dependencyInstaller.js.map +1 -1
- package/dist/external/vscode-observables/observables/dist/disposables.js +24 -1
- package/dist/external/vscode-observables/observables/dist/disposables.js.map +1 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/commonFacade/deps.js +1 -4
- package/dist/external/vscode-observables/observables/dist/observableInternal/commonFacade/deps.js.map +1 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/index.js +2 -5
- package/dist/external/vscode-observables/observables/dist/observableInternal/index.js.map +1 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/consoleObservableLogger.js +30 -6
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/consoleObservableLogger.js.map +1 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/observables/baseObservable.js +1 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/observables/baseObservable.js.map +1 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/observables/derived.js +12 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/observables/derived.js.map +1 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/utils/utilsCancellation.js +55 -0
- package/dist/external/vscode-observables/observables/dist/observableInternal/utils/utilsCancellation.js.map +1 -0
- package/dist/git/gitUtils.js +1 -1
- package/dist/git/gitUtils.js.map +1 -1
- package/dist/mcp/McpServer.d.ts +30 -4
- package/dist/mcp/McpServer.d.ts.map +1 -1
- package/dist/mcp/McpServer.js +435 -80
- package/dist/mcp/McpServer.js.map +1 -1
- package/dist/packages/simple-api/dist/{chunk-A5PE72HI.js → chunk-Q24JOMNK.js} +7 -1
- package/dist/packages/simple-api/dist/chunk-Q24JOMNK.js.map +1 -0
- package/dist/utils.d.ts +24 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +50 -0
- package/dist/utils.js.map +1 -0
- package/dist/watchConfig.d.ts +36 -0
- package/dist/watchConfig.d.ts.map +1 -1
- package/dist/watchConfig.js +32 -22
- package/dist/watchConfig.js.map +1 -1
- package/package.json +6 -4
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/debugger/debuggerRpc.js +0 -72
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/debugger/debuggerRpc.js.map +0 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/debugger/devToolsLogger.js +0 -447
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/debugger/devToolsLogger.js.map +0 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/debugger/rpc.js +0 -64
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/debugger/rpc.js.map +0 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/debugger/utils.js +0 -52
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/debugger/utils.js.map +0 -1
- package/dist/packages/simple-api/dist/chunk-A5PE72HI.js.map +0 -1
|
@@ -2,6 +2,7 @@ import { Command, Option } from 'clipanion';
|
|
|
2
2
|
import { spawn } from 'node:child_process';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
import * as path from 'node:path';
|
|
5
|
+
import * as http from 'node:http';
|
|
5
6
|
import { ConsoleLogger, verbosityToLogLevel } from '../logger.js';
|
|
6
7
|
import { ResolvedWatchConfig } from '../watchConfig.js';
|
|
7
8
|
import { DaemonService } from '../daemon/DaemonService.js';
|
|
@@ -34,6 +35,8 @@ Without flags: starts a foreground daemon. Errors if one is already running.
|
|
|
34
35
|
background = Option.Boolean('--background', false, { description: 'Spawn as a detached background process' });
|
|
35
36
|
attach = Option.Boolean('--attach', false, { description: 'Attach to a running daemon and stream events' });
|
|
36
37
|
kill = Option.Boolean('--kill', false, { description: 'Shut down a running daemon' });
|
|
38
|
+
redirectionPort = Option.String('--redirectionPort', { description: 'Start an HTTP server that redirects /___explorer to the session URL' });
|
|
39
|
+
redirectionHost = Option.String('--redirectionHost', { description: 'Host to bind the redirection server to (default: localhost)' });
|
|
37
40
|
async execute() {
|
|
38
41
|
const resolved = await resolveProject(this.project);
|
|
39
42
|
if (resolved.kind !== 'explorerConfig') {
|
|
@@ -76,7 +79,9 @@ Without flags: starts a foreground daemon. Errors if one is already running.
|
|
|
76
79
|
// Default: start foreground daemon
|
|
77
80
|
const existing = await tryConnect(pipeName);
|
|
78
81
|
if (existing) {
|
|
79
|
-
this.context.stderr.write(`Daemon already running (pipe: ${pipeName}).\
|
|
82
|
+
this.context.stderr.write(`Daemon already running (pipe: ${pipeName}).\n`);
|
|
83
|
+
this.context.stderr.write(` Attach: component-explorer serve -c ${configPath} --attach\n`);
|
|
84
|
+
this.context.stderr.write(` Kill: component-explorer serve -c ${configPath} --kill\n`);
|
|
80
85
|
return;
|
|
81
86
|
}
|
|
82
87
|
return this._startDaemon(pipeName, configPath);
|
|
@@ -87,7 +92,14 @@ Without flags: starts a foreground daemon. Errors if one is already running.
|
|
|
87
92
|
return;
|
|
88
93
|
}
|
|
89
94
|
const cliEntryPoint = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../index.js');
|
|
90
|
-
const
|
|
95
|
+
const args = [cliEntryPoint, 'serve', '--project', configPath];
|
|
96
|
+
if (this.redirectionPort) {
|
|
97
|
+
args.push('--redirectionPort', this.redirectionPort);
|
|
98
|
+
}
|
|
99
|
+
if (this.redirectionHost) {
|
|
100
|
+
args.push('--redirectionHost', this.redirectionHost);
|
|
101
|
+
}
|
|
102
|
+
const child = spawn(process.execPath, args, { detached: true, stdio: 'ignore', windowsHide: true });
|
|
91
103
|
child.unref();
|
|
92
104
|
await waitForDaemon(pipeName, { timeoutMs: 30_000 });
|
|
93
105
|
this.context.stdout.write(`Daemon started (pipe: ${pipeName})\n`);
|
|
@@ -127,17 +139,54 @@ Without flags: starts a foreground daemon. Errors if one is already running.
|
|
|
127
139
|
this.context.stdout.write('Press Ctrl+C to stop.\n\n');
|
|
128
140
|
const sessionInfos = service.getSessionInfos();
|
|
129
141
|
for (const s of sessionInfos) {
|
|
130
|
-
|
|
142
|
+
if (s.isLoading) {
|
|
143
|
+
this.context.stdout.write(` ${s.name}: (loading) (${s.sourceKind})\n`);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
this.context.stdout.write(` ${s.name}: ${s.serverUrl} (${s.sourceKind})\n`);
|
|
147
|
+
}
|
|
131
148
|
}
|
|
132
149
|
this.context.stdout.write('\n');
|
|
150
|
+
let redirectServer;
|
|
151
|
+
const redirectPort = this.redirectionPort
|
|
152
|
+
? parseInt(this.redirectionPort, 10)
|
|
153
|
+
: resolvedConfig.redirection?.port;
|
|
154
|
+
const redirectHost = this.redirectionHost ?? resolvedConfig.redirection?.host ?? 'localhost';
|
|
155
|
+
if (redirectPort) {
|
|
156
|
+
redirectServer = this._startRedirectionServer(service, redirectPort, redirectHost);
|
|
157
|
+
}
|
|
133
158
|
process.on('SIGINT', () => {
|
|
134
159
|
service.requestShutdown();
|
|
135
160
|
});
|
|
136
161
|
await service.runEventLoop();
|
|
137
162
|
this.context.stdout.write('\nShutting down...\n');
|
|
163
|
+
redirectServer?.dispose();
|
|
138
164
|
server.close();
|
|
139
165
|
await service.dispose();
|
|
140
166
|
}
|
|
167
|
+
_startRedirectionServer(service, port, host) {
|
|
168
|
+
const server = http.createServer(async (req, res) => {
|
|
169
|
+
const url = new URL(req.url ?? '/', `http://${req.headers.host}`);
|
|
170
|
+
const sessionName = url.searchParams.get('sessionName');
|
|
171
|
+
try {
|
|
172
|
+
const session = await service.waitForSession(sessionName ?? undefined);
|
|
173
|
+
const target = new URL(session.serverUrl);
|
|
174
|
+
target.pathname = url.pathname;
|
|
175
|
+
url.searchParams.delete('sessionName');
|
|
176
|
+
target.search = url.search;
|
|
177
|
+
res.writeHead(302, { Location: target.href });
|
|
178
|
+
res.end();
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
res.writeHead(503);
|
|
182
|
+
res.end('Session not available.\\n');
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
server.listen(port, host, () => {
|
|
186
|
+
this.context.stdout.write(`Redirection server listening on http://${host}:${port}\\n`);
|
|
187
|
+
});
|
|
188
|
+
return { dispose: () => server.close() };
|
|
189
|
+
}
|
|
141
190
|
}
|
|
142
191
|
|
|
143
192
|
export { ServeCommand };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serveCommand.js","sources":["../../src/commands/serveCommand.ts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"serveCommand.js","sources":["../../src/commands/serveCommand.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Writable } from 'node:stream';
|
|
2
|
+
export interface CompareReportFixtureDetail {
|
|
3
|
+
readonly status: 'added' | 'removed' | 'changed' | 'unchanged';
|
|
4
|
+
readonly baselineHash?: string;
|
|
5
|
+
readonly currentHash?: string;
|
|
6
|
+
readonly baselineScreenshot?: string;
|
|
7
|
+
readonly currentScreenshot?: string;
|
|
8
|
+
readonly background?: 'light' | 'dark';
|
|
9
|
+
}
|
|
10
|
+
export interface CompareReport {
|
|
11
|
+
readonly timestamp: string;
|
|
12
|
+
readonly baseline: string;
|
|
13
|
+
readonly current: string;
|
|
14
|
+
readonly summary: {
|
|
15
|
+
readonly total: number;
|
|
16
|
+
readonly added: number;
|
|
17
|
+
readonly removed: number;
|
|
18
|
+
readonly changed: number;
|
|
19
|
+
readonly unchanged: number;
|
|
20
|
+
};
|
|
21
|
+
readonly fixtures: Record<string, CompareReportFixtureDetail>;
|
|
22
|
+
}
|
|
23
|
+
export interface ComparisonResult {
|
|
24
|
+
readonly added: string[];
|
|
25
|
+
readonly removed: string[];
|
|
26
|
+
readonly changed: string[];
|
|
27
|
+
readonly unchanged: string[];
|
|
28
|
+
readonly fixtures: Record<string, CompareReportFixtureDetail>;
|
|
29
|
+
}
|
|
30
|
+
export interface ScreenshotData {
|
|
31
|
+
readonly data: Uint8Array;
|
|
32
|
+
readonly background?: 'light' | 'dark';
|
|
33
|
+
}
|
|
34
|
+
export interface ComparisonStorage {
|
|
35
|
+
list(): Promise<string[]>;
|
|
36
|
+
read(id: string): Promise<Uint8Array>;
|
|
37
|
+
exists(id: string): Promise<boolean>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Compare screenshots between current and baseline.
|
|
41
|
+
* @param currentScreenshots Map of fixture IDs to screenshot data (already captured)
|
|
42
|
+
* @param baselineStorage Storage to read baseline screenshots from
|
|
43
|
+
*/
|
|
44
|
+
export declare function compareScreenshotsInMemory(currentScreenshots: Map<string, ScreenshotData>, baselineStorage: ComparisonStorage): Promise<ComparisonResult>;
|
|
45
|
+
/**
|
|
46
|
+
* Compare screenshots between two directories on disk.
|
|
47
|
+
*/
|
|
48
|
+
export declare function compareScreenshotsOnDisk(currentStorage: ComparisonStorage, baselineStorage: ComparisonStorage, currentFiles: string[], baselineFiles: string[]): Promise<ComparisonResult>;
|
|
49
|
+
export declare function printComparisonToConsole(result: ComparisonResult, stdout: Writable): void;
|
|
50
|
+
export interface WriteReportOptions {
|
|
51
|
+
readonly reportDir: string;
|
|
52
|
+
readonly result: ComparisonResult;
|
|
53
|
+
readonly baselinePath: string;
|
|
54
|
+
readonly currentPath: string;
|
|
55
|
+
readonly getBaselineData: (fixtureId: string) => Promise<Uint8Array>;
|
|
56
|
+
readonly getCurrentData: (fixtureId: string) => Promise<Uint8Array>;
|
|
57
|
+
}
|
|
58
|
+
export declare function writeComparisonReport(options: WriteReportOptions): Promise<void>;
|
|
59
|
+
export declare function generateMarkdownReport(report: CompareReport): string;
|
|
60
|
+
//# sourceMappingURL=comparison.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comparison.d.ts","sourceRoot":"","sources":["../src/comparison.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import * as fs from 'node:fs/promises';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { contentHash } from './screenshotCache.js';
|
|
4
|
+
import { writeFile } from './utils.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Compare screenshots between current and baseline.
|
|
8
|
+
* @param currentScreenshots Map of fixture IDs to screenshot data (already captured)
|
|
9
|
+
* @param baselineStorage Storage to read baseline screenshots from
|
|
10
|
+
*/
|
|
11
|
+
async function compareScreenshotsInMemory(currentScreenshots, baselineStorage) {
|
|
12
|
+
const added = [];
|
|
13
|
+
const changed = [];
|
|
14
|
+
const unchanged = [];
|
|
15
|
+
const fixtures = {};
|
|
16
|
+
for (const [fixtureId, screenshot] of currentScreenshots) {
|
|
17
|
+
const currentHash = contentHash(screenshot.data);
|
|
18
|
+
if (await baselineStorage.exists(`${fixtureId}.png`)) {
|
|
19
|
+
const baselineData = await baselineStorage.read(`${fixtureId}.png`);
|
|
20
|
+
const baselineHash = contentHash(baselineData);
|
|
21
|
+
if (currentHash === baselineHash) {
|
|
22
|
+
unchanged.push(fixtureId);
|
|
23
|
+
fixtures[fixtureId] = { status: 'unchanged', baselineHash, currentHash, background: screenshot.background };
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
changed.push(fixtureId);
|
|
27
|
+
fixtures[fixtureId] = { status: 'changed', baselineHash, currentHash, background: screenshot.background };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
added.push(fixtureId);
|
|
32
|
+
fixtures[fixtureId] = { status: 'added', currentHash, background: screenshot.background };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
added.sort();
|
|
36
|
+
changed.sort();
|
|
37
|
+
unchanged.sort();
|
|
38
|
+
return { added, removed: [], changed, unchanged, fixtures };
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Compare screenshots between two directories on disk.
|
|
42
|
+
*/
|
|
43
|
+
async function compareScreenshotsOnDisk(currentStorage, baselineStorage, currentFiles, baselineFiles) {
|
|
44
|
+
const baselineSet = new Set(baselineFiles);
|
|
45
|
+
const currentSet = new Set(currentFiles);
|
|
46
|
+
const added = [];
|
|
47
|
+
const removed = [];
|
|
48
|
+
const changed = [];
|
|
49
|
+
const unchanged = [];
|
|
50
|
+
const fixtures = {};
|
|
51
|
+
for (const file of currentSet) {
|
|
52
|
+
const fixtureId = file.replace(/\.png$/, '');
|
|
53
|
+
if (!baselineSet.has(file)) {
|
|
54
|
+
added.push(fixtureId);
|
|
55
|
+
const currentData = await currentStorage.read(file);
|
|
56
|
+
fixtures[fixtureId] = { status: 'added', currentHash: contentHash(currentData) };
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
const baselineData = await baselineStorage.read(file);
|
|
60
|
+
const currentData = await currentStorage.read(file);
|
|
61
|
+
const baselineHash = contentHash(baselineData);
|
|
62
|
+
const currentHash = contentHash(currentData);
|
|
63
|
+
if (baselineHash === currentHash) {
|
|
64
|
+
unchanged.push(fixtureId);
|
|
65
|
+
fixtures[fixtureId] = { status: 'unchanged', baselineHash, currentHash };
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
changed.push(fixtureId);
|
|
69
|
+
fixtures[fixtureId] = { status: 'changed', baselineHash, currentHash };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
for (const file of baselineSet) {
|
|
74
|
+
const fixtureId = file.replace(/\.png$/, '');
|
|
75
|
+
if (!currentSet.has(file)) {
|
|
76
|
+
removed.push(fixtureId);
|
|
77
|
+
const baselineData = await baselineStorage.read(file);
|
|
78
|
+
fixtures[fixtureId] = { status: 'removed', baselineHash: contentHash(baselineData) };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
added.sort();
|
|
82
|
+
removed.sort();
|
|
83
|
+
changed.sort();
|
|
84
|
+
unchanged.sort();
|
|
85
|
+
return { added, removed, changed, unchanged, fixtures };
|
|
86
|
+
}
|
|
87
|
+
function printComparisonToConsole(result, stdout) {
|
|
88
|
+
if (result.added.length > 0) {
|
|
89
|
+
stdout.write(`Added (${result.added.length}):\n`);
|
|
90
|
+
for (const f of result.added) {
|
|
91
|
+
stdout.write(` + ${f}\n`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (result.removed.length > 0) {
|
|
95
|
+
stdout.write(`Removed (${result.removed.length}):\n`);
|
|
96
|
+
for (const f of result.removed) {
|
|
97
|
+
stdout.write(` - ${f}\n`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (result.changed.length > 0) {
|
|
101
|
+
stdout.write(`Changed (${result.changed.length}):\n`);
|
|
102
|
+
for (const f of result.changed) {
|
|
103
|
+
stdout.write(` ~ ${f}\n`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const total = result.added.length + result.removed.length + result.changed.length + result.unchanged.length;
|
|
107
|
+
stdout.write(`\nSummary: ${total} fixtures`);
|
|
108
|
+
if (result.added.length > 0 || result.removed.length > 0 || result.changed.length > 0) {
|
|
109
|
+
const parts = [];
|
|
110
|
+
if (result.added.length > 0)
|
|
111
|
+
parts.push(`${result.added.length} added`);
|
|
112
|
+
if (result.removed.length > 0)
|
|
113
|
+
parts.push(`${result.removed.length} removed`);
|
|
114
|
+
if (result.changed.length > 0)
|
|
115
|
+
parts.push(`${result.changed.length} changed`);
|
|
116
|
+
if (result.unchanged.length > 0)
|
|
117
|
+
parts.push(`${result.unchanged.length} unchanged`);
|
|
118
|
+
stdout.write(` (${parts.join(', ')})\n`);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
stdout.write(' — no differences\n');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async function writeComparisonReport(options) {
|
|
125
|
+
const { reportDir, result, baselinePath, currentPath, getBaselineData, getCurrentData } = options;
|
|
126
|
+
await fs.mkdir(reportDir, { recursive: true });
|
|
127
|
+
const screenshotsRelDir = 'screenshots';
|
|
128
|
+
const fixturesWithPaths = { ...result.fixtures };
|
|
129
|
+
for (const id of result.changed) {
|
|
130
|
+
const relBase = `${screenshotsRelDir}/${id}/baseline.png`;
|
|
131
|
+
const relCurrent = `${screenshotsRelDir}/${id}/current.png`;
|
|
132
|
+
const baselineData = await getBaselineData(id);
|
|
133
|
+
const currentData = await getCurrentData(id);
|
|
134
|
+
await writeFile(path.join(reportDir, relBase), baselineData);
|
|
135
|
+
await writeFile(path.join(reportDir, relCurrent), currentData);
|
|
136
|
+
fixturesWithPaths[id] = { ...fixturesWithPaths[id], baselineScreenshot: relBase, currentScreenshot: relCurrent };
|
|
137
|
+
}
|
|
138
|
+
for (const id of result.added) {
|
|
139
|
+
const relCurrent = `${screenshotsRelDir}/${id}/current.png`;
|
|
140
|
+
const currentData = await getCurrentData(id);
|
|
141
|
+
await writeFile(path.join(reportDir, relCurrent), currentData);
|
|
142
|
+
fixturesWithPaths[id] = { ...fixturesWithPaths[id], currentScreenshot: relCurrent };
|
|
143
|
+
}
|
|
144
|
+
for (const id of result.removed) {
|
|
145
|
+
const relBase = `${screenshotsRelDir}/${id}/baseline.png`;
|
|
146
|
+
const baselineData = await getBaselineData(id);
|
|
147
|
+
await writeFile(path.join(reportDir, relBase), baselineData);
|
|
148
|
+
fixturesWithPaths[id] = { ...fixturesWithPaths[id], baselineScreenshot: relBase };
|
|
149
|
+
}
|
|
150
|
+
const hasDiffs = result.added.length + result.removed.length + result.changed.length > 0;
|
|
151
|
+
const report = {
|
|
152
|
+
timestamp: new Date().toISOString(),
|
|
153
|
+
baseline: baselinePath,
|
|
154
|
+
current: currentPath,
|
|
155
|
+
summary: {
|
|
156
|
+
total: result.added.length + result.removed.length + result.changed.length + result.unchanged.length,
|
|
157
|
+
added: result.added.length,
|
|
158
|
+
removed: result.removed.length,
|
|
159
|
+
changed: result.changed.length,
|
|
160
|
+
unchanged: result.unchanged.length,
|
|
161
|
+
},
|
|
162
|
+
fixtures: fixturesWithPaths,
|
|
163
|
+
};
|
|
164
|
+
await fs.writeFile(path.join(reportDir, 'report.json'), JSON.stringify(report, null, 2));
|
|
165
|
+
if (hasDiffs) {
|
|
166
|
+
const markdown = generateMarkdownReport(report);
|
|
167
|
+
await fs.writeFile(path.join(reportDir, 'report.md'), markdown);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function generateMarkdownReport(report) {
|
|
171
|
+
const lines = [];
|
|
172
|
+
const changed = Object.entries(report.fixtures).filter(([, d]) => d.status === 'changed').map(([id]) => id);
|
|
173
|
+
const added = Object.entries(report.fixtures).filter(([, d]) => d.status === 'added').map(([id]) => id);
|
|
174
|
+
const removed = Object.entries(report.fixtures).filter(([, d]) => d.status === 'removed').map(([id]) => id);
|
|
175
|
+
const unchanged = Object.entries(report.fixtures).filter(([, d]) => d.status === 'unchanged').map(([id]) => id);
|
|
176
|
+
lines.push('# Screenshot Comparison Report');
|
|
177
|
+
lines.push('');
|
|
178
|
+
lines.push(`**Generated:** ${report.timestamp}`);
|
|
179
|
+
lines.push(`**Baseline:** \`${report.baseline}\``);
|
|
180
|
+
lines.push(`**Current:** \`${report.current}\``);
|
|
181
|
+
lines.push('');
|
|
182
|
+
lines.push('## Summary');
|
|
183
|
+
lines.push('');
|
|
184
|
+
lines.push('| Status | Count |');
|
|
185
|
+
lines.push('|--------|-------|');
|
|
186
|
+
if (added.length > 0)
|
|
187
|
+
lines.push(`| Added | ${added.length} |`);
|
|
188
|
+
if (removed.length > 0)
|
|
189
|
+
lines.push(`| Removed | ${removed.length} |`);
|
|
190
|
+
if (changed.length > 0)
|
|
191
|
+
lines.push(`| Changed | ${changed.length} |`);
|
|
192
|
+
lines.push(`| Unchanged | ${unchanged.length} |`);
|
|
193
|
+
lines.push(`| **Total** | **${report.summary.total}** |`);
|
|
194
|
+
lines.push('');
|
|
195
|
+
if (changed.length > 0) {
|
|
196
|
+
lines.push('## Changed Fixtures');
|
|
197
|
+
lines.push('');
|
|
198
|
+
for (const id of changed) {
|
|
199
|
+
const detail = report.fixtures[id];
|
|
200
|
+
lines.push(`### \`${id}\``);
|
|
201
|
+
lines.push('');
|
|
202
|
+
lines.push('| Baseline | Current |');
|
|
203
|
+
lines.push('|----------|---------|');
|
|
204
|
+
const baseImg = detail.baselineScreenshot ? `` : '-';
|
|
205
|
+
const curImg = detail.currentScreenshot ? `` : '-';
|
|
206
|
+
lines.push(`| ${baseImg} | ${curImg} |`);
|
|
207
|
+
lines.push('');
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
if (added.length > 0) {
|
|
211
|
+
lines.push('## Added Fixtures');
|
|
212
|
+
lines.push('');
|
|
213
|
+
for (const id of added) {
|
|
214
|
+
const detail = report.fixtures[id];
|
|
215
|
+
lines.push(`### \`${id}\``);
|
|
216
|
+
lines.push('');
|
|
217
|
+
if (detail.currentScreenshot) {
|
|
218
|
+
lines.push(``);
|
|
219
|
+
}
|
|
220
|
+
lines.push('');
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (removed.length > 0) {
|
|
224
|
+
lines.push('## Removed Fixtures');
|
|
225
|
+
lines.push('');
|
|
226
|
+
for (const id of removed) {
|
|
227
|
+
const detail = report.fixtures[id];
|
|
228
|
+
lines.push(`### \`${id}\``);
|
|
229
|
+
lines.push('');
|
|
230
|
+
if (detail.baselineScreenshot) {
|
|
231
|
+
lines.push(``);
|
|
232
|
+
}
|
|
233
|
+
lines.push('');
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (unchanged.length > 0) {
|
|
237
|
+
lines.push('<details>');
|
|
238
|
+
lines.push(`<summary>Unchanged Fixtures (${unchanged.length})</summary>`);
|
|
239
|
+
lines.push('');
|
|
240
|
+
for (const id of unchanged) {
|
|
241
|
+
lines.push(`- \`${id}\``);
|
|
242
|
+
}
|
|
243
|
+
lines.push('');
|
|
244
|
+
lines.push('</details>');
|
|
245
|
+
}
|
|
246
|
+
return lines.join('\n');
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export { compareScreenshotsInMemory, compareScreenshotsOnDisk, generateMarkdownReport, printComparisonToConsole, writeComparisonReport };
|
|
250
|
+
//# sourceMappingURL=comparison.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comparison.js","sources":["../src/comparison.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;AAgDA;;;;AAIG;AACI,eAAe,0BAA0B,CAC/C,kBAA+C,EAC/C,eAAkC,EAAA;IAElC,MAAM,KAAK,GAAa,EAAE;IAC1B,MAAM,OAAO,GAAa,EAAE;IAC5B,MAAM,SAAS,GAAa,EAAE;IAC9B,MAAM,QAAQ,GAA+C,EAAE;IAE/D,KAAK,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,IAAI,kBAAkB,EAAE;QACzD,MAAM,WAAW,GAAG,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC;QAEhD,IAAI,MAAM,eAAe,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA,IAAA,CAAM,CAAC,EAAE;YACrD,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,CAAA,EAAG,SAAS,CAAA,IAAA,CAAM,CAAC;AACnE,YAAA,MAAM,YAAY,GAAG,WAAW,CAAC,YAAY,CAAC;AAE9C,YAAA,IAAI,WAAW,KAAK,YAAY,EAAE;AACjC,gBAAA,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC;AACzB,gBAAA,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,CAAC,UAAU,EAAE;YAC5G;iBAAO;AACN,gBAAA,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;AACvB,gBAAA,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,CAAC,UAAU,EAAE;YAC1G;QACD;aAAO;AACN,YAAA,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;AACrB,YAAA,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,CAAC,UAAU,EAAE;QAC1F;IACD;IAEA,KAAK,CAAC,IAAI,EAAE;IACZ,OAAO,CAAC,IAAI,EAAE;IACd,SAAS,CAAC,IAAI,EAAE;AAEhB,IAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE;AAC5D;AAEA;;AAEG;AACI,eAAe,wBAAwB,CAC7C,cAAiC,EACjC,eAAkC,EAClC,YAAsB,EACtB,aAAuB,EAAA;AAEvB,IAAA,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC;AAC1C,IAAA,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC;IAExC,MAAM,KAAK,GAAa,EAAE;IAC1B,MAAM,OAAO,GAAa,EAAE;IAC5B,MAAM,OAAO,GAAa,EAAE;IAC5B,MAAM,SAAS,GAAa,EAAE;IAC9B,MAAM,QAAQ,GAA+C,EAAE;AAE/D,IAAA,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE;QAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC5C,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;AAC3B,YAAA,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;YACrB,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;AACnD,YAAA,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,CAAC,WAAW,CAAC,EAAE;QACjF;aAAO;YACN,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;YACrD,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;AACnD,YAAA,MAAM,YAAY,GAAG,WAAW,CAAC,YAAY,CAAC;AAC9C,YAAA,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC;AAE5C,YAAA,IAAI,YAAY,KAAK,WAAW,EAAE;AACjC,gBAAA,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC;AACzB,gBAAA,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE;YACzE;iBAAO;AACN,gBAAA,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;AACvB,gBAAA,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE;YACvE;QACD;IACD;AAEA,IAAA,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE;QAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC5C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;AAC1B,YAAA,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;YACvB,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;AACrD,YAAA,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,CAAC,YAAY,CAAC,EAAE;QACrF;IACD;IAEA,KAAK,CAAC,IAAI,EAAE;IACZ,OAAO,CAAC,IAAI,EAAE;IACd,OAAO,CAAC,IAAI,EAAE;IACd,SAAS,CAAC,IAAI,EAAE;IAEhB,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE;AACxD;AAEM,SAAU,wBAAwB,CAAC,MAAwB,EAAE,MAAgB,EAAA;IAClF,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;QAC5B,MAAM,CAAC,KAAK,CAAC,CAAA,OAAA,EAAU,MAAM,CAAC,KAAK,CAAC,MAAM,CAAA,IAAA,CAAM,CAAC;AACjD,QAAA,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,EAAE;AAAE,YAAA,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA,EAAA,CAAI,CAAC;QAAE;IAC7D;IAEA,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;QAC9B,MAAM,CAAC,KAAK,CAAC,CAAA,SAAA,EAAY,MAAM,CAAC,OAAO,CAAC,MAAM,CAAA,IAAA,CAAM,CAAC;AACrD,QAAA,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE;AAAE,YAAA,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA,EAAA,CAAI,CAAC;QAAE;IAC/D;IAEA,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;QAC9B,MAAM,CAAC,KAAK,CAAC,CAAA,SAAA,EAAY,MAAM,CAAC,OAAO,CAAC,MAAM,CAAA,IAAA,CAAM,CAAC;AACrD,QAAA,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE;AAAE,YAAA,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA,EAAA,CAAI,CAAC;QAAE;IAC/D;IAEA,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM;AAC3G,IAAA,MAAM,CAAC,KAAK,CAAC,cAAc,KAAK,CAAA,SAAA,CAAW,CAAC;IAC5C,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;QACtF,MAAM,KAAK,GAAa,EAAE;AAC1B,QAAA,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,CAAA,EAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAA,MAAA,CAAQ,CAAC;AACvE,QAAA,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,CAAA,EAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAA,QAAA,CAAU,CAAC;AAC7E,QAAA,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,CAAA,EAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAA,QAAA,CAAU,CAAC;AAC7E,QAAA,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,CAAA,EAAG,MAAM,CAAC,SAAS,CAAC,MAAM,CAAA,UAAA,CAAY,CAAC;AACnF,QAAA,MAAM,CAAC,KAAK,CAAC,CAAA,EAAA,EAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA,GAAA,CAAK,CAAC;IACzC;SAAO;AACN,QAAA,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC;IACpC;AACD;AAWO,eAAe,qBAAqB,CAAC,OAA2B,EAAA;AACtE,IAAA,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,cAAc,EAAE,GAAG,OAAO;AAEjG,IAAA,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAE9C,MAAM,iBAAiB,GAAG,aAAa;IACvC,MAAM,iBAAiB,GAA+C,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE;AAE5F,IAAA,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,OAAO,EAAE;AAChC,QAAA,MAAM,OAAO,GAAG,CAAA,EAAG,iBAAiB,CAAA,CAAA,EAAI,EAAE,eAAe;AACzD,QAAA,MAAM,UAAU,GAAG,CAAA,EAAG,iBAAiB,CAAA,CAAA,EAAI,EAAE,cAAc;AAC3D,QAAA,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC,EAAE,CAAC;AAC9C,QAAA,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,EAAE,CAAC;AAC5C,QAAA,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC;AAC5D,QAAA,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,WAAW,CAAC;AAC9D,QAAA,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,iBAAiB,CAAC,EAAE,CAAC,EAAE,kBAAkB,EAAE,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE;IACjH;AAEA,IAAA,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,KAAK,EAAE;AAC9B,QAAA,MAAM,UAAU,GAAG,CAAA,EAAG,iBAAiB,CAAA,CAAA,EAAI,EAAE,cAAc;AAC3D,QAAA,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,EAAE,CAAC;AAC5C,QAAA,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,WAAW,CAAC;AAC9D,QAAA,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,iBAAiB,CAAC,EAAE,CAAC,EAAE,iBAAiB,EAAE,UAAU,EAAE;IACpF;AAEA,IAAA,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,OAAO,EAAE;AAChC,QAAA,MAAM,OAAO,GAAG,CAAA,EAAG,iBAAiB,CAAA,CAAA,EAAI,EAAE,eAAe;AACzD,QAAA,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC,EAAE,CAAC;AAC9C,QAAA,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC;AAC5D,QAAA,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,iBAAiB,CAAC,EAAE,CAAC,EAAE,kBAAkB,EAAE,OAAO,EAAE;IAClF;IAEA,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;AAExF,IAAA,MAAM,MAAM,GAAkB;AAC7B,QAAA,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;AACnC,QAAA,QAAQ,EAAE,YAAY;AACtB,QAAA,OAAO,EAAE,WAAW;AACpB,QAAA,OAAO,EAAE;YACR,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM;AACpG,YAAA,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM;AAC1B,YAAA,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM;AAC9B,YAAA,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM;AAC9B,YAAA,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM;AAClC,SAAA;AACD,QAAA,QAAQ,EAAE,iBAAiB;KAC3B;IACD,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAExF,IAAI,QAAQ,EAAE;AACb,QAAA,MAAM,QAAQ,GAAG,sBAAsB,CAAC,MAAM,CAAC;AAC/C,QAAA,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,QAAQ,CAAC;IAChE;AACD;AAEM,SAAU,sBAAsB,CAAC,MAAqB,EAAA;IAC3D,MAAM,KAAK,GAAa,EAAE;AAC1B,IAAA,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;AAC3G,IAAA,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;AACvG,IAAA,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;AAC3G,IAAA,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;AAE/G,IAAA,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC;AAC5C,IAAA,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;IACd,KAAK,CAAC,IAAI,CAAC,CAAA,eAAA,EAAkB,MAAM,CAAC,SAAS,CAAA,CAAE,CAAC;IAChD,KAAK,CAAC,IAAI,CAAC,CAAA,gBAAA,EAAmB,MAAM,CAAC,QAAQ,CAAA,EAAA,CAAI,CAAC;IAClD,KAAK,CAAC,IAAI,CAAC,CAAA,eAAA,EAAkB,MAAM,CAAC,OAAO,CAAA,EAAA,CAAI,CAAC;AAChD,IAAA,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AAEd,IAAA,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC;AACxB,IAAA,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AACd,IAAA,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC;AAChC,IAAA,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC;AAChC,IAAA,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,CAAA,UAAA,EAAa,KAAK,CAAC,MAAM,CAAA,EAAA,CAAI,CAAC;AAC/D,IAAA,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,CAAA,YAAA,EAAe,OAAO,CAAC,MAAM,CAAA,EAAA,CAAI,CAAC;AACrE,IAAA,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,CAAA,YAAA,EAAe,OAAO,CAAC,MAAM,CAAA,EAAA,CAAI,CAAC;IACrE,KAAK,CAAC,IAAI,CAAC,CAAA,cAAA,EAAiB,SAAS,CAAC,MAAM,CAAA,EAAA,CAAI,CAAC;IACjD,KAAK,CAAC,IAAI,CAAC,CAAA,gBAAA,EAAmB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAA,IAAA,CAAM,CAAC;AACzD,IAAA,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AAEd,IAAA,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;AACvB,QAAA,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC;AACjC,QAAA,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AACd,QAAA,KAAK,MAAM,EAAE,IAAI,OAAO,EAAE;YACzB,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;AAClC,YAAA,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAA,EAAA,CAAI,CAAC;AAC3B,YAAA,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AACd,YAAA,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC;AACpC,YAAA,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC;AACpC,YAAA,MAAM,OAAO,GAAG,MAAM,CAAC,kBAAkB,GAAG,CAAA,YAAA,EAAe,MAAM,CAAC,kBAAkB,CAAA,CAAA,CAAG,GAAG,GAAG;AAC7F,YAAA,MAAM,MAAM,GAAG,MAAM,CAAC,iBAAiB,GAAG,CAAA,WAAA,EAAc,MAAM,CAAC,iBAAiB,CAAA,CAAA,CAAG,GAAG,GAAG;YACzF,KAAK,CAAC,IAAI,CAAC,CAAA,EAAA,EAAK,OAAO,CAAA,GAAA,EAAM,MAAM,CAAA,EAAA,CAAI,CAAC;AACxC,YAAA,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACf;IACD;AAEA,IAAA,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;AACrB,QAAA,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC;AAC/B,QAAA,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AACd,QAAA,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE;YACvB,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;AAClC,YAAA,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAA,EAAA,CAAI,CAAC;AAC3B,YAAA,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AACd,YAAA,IAAI,MAAM,CAAC,iBAAiB,EAAE;gBAC7B,KAAK,CAAC,IAAI,CAAC,CAAA,WAAA,EAAc,MAAM,CAAC,iBAAiB,CAAA,CAAA,CAAG,CAAC;YACtD;AACA,YAAA,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACf;IACD;AAEA,IAAA,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;AACvB,QAAA,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC;AACjC,QAAA,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AACd,QAAA,KAAK,MAAM,EAAE,IAAI,OAAO,EAAE;YACzB,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;AAClC,YAAA,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAA,EAAA,CAAI,CAAC;AAC3B,YAAA,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AACd,YAAA,IAAI,MAAM,CAAC,kBAAkB,EAAE;gBAC9B,KAAK,CAAC,IAAI,CAAC,CAAA,YAAA,EAAe,MAAM,CAAC,kBAAkB,CAAA,CAAA,CAAG,CAAC;YACxD;AACA,YAAA,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACf;IACD;AAEA,IAAA,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;AACzB,QAAA,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,CAAA,6BAAA,EAAgC,SAAS,CAAC,MAAM,CAAA,WAAA,CAAa,CAAC;AACzE,QAAA,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AACd,QAAA,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE;AAC3B,YAAA,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAA,EAAA,CAAI,CAAC;QAC1B;AACA,QAAA,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AACd,QAAA,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC;IACzB;AAEA,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;AACxB;;;;"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"properties": {
|
|
5
|
+
"screenshotDir": {
|
|
6
|
+
"description": "Directory for storing screenshots (default: .screenshots)",
|
|
7
|
+
"type": "string"
|
|
8
|
+
},
|
|
9
|
+
"sessions": {
|
|
10
|
+
"minItems": 1,
|
|
11
|
+
"type": "array",
|
|
12
|
+
"items": {
|
|
13
|
+
"type": "object",
|
|
14
|
+
"properties": {
|
|
15
|
+
"name": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Unique session name"
|
|
18
|
+
},
|
|
19
|
+
"source": {
|
|
20
|
+
"anyOf": [
|
|
21
|
+
{
|
|
22
|
+
"type": "string",
|
|
23
|
+
"const": "current"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"type": "object",
|
|
27
|
+
"properties": {
|
|
28
|
+
"worktree": {
|
|
29
|
+
"type": "object",
|
|
30
|
+
"properties": {
|
|
31
|
+
"ref": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"description": "Git ref (branch, tag, or commit) to check out"
|
|
34
|
+
},
|
|
35
|
+
"name": {
|
|
36
|
+
"description": "Directory name for the worktree (default: component-explorer-baseline)",
|
|
37
|
+
"type": "string"
|
|
38
|
+
},
|
|
39
|
+
"install": {
|
|
40
|
+
"anyOf": [
|
|
41
|
+
{
|
|
42
|
+
"type": "string",
|
|
43
|
+
"const": "auto"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"type": "string",
|
|
47
|
+
"const": "npm"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"type": "string",
|
|
51
|
+
"const": "pnpm"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"type": "string",
|
|
55
|
+
"const": "yarn"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"type": "object",
|
|
59
|
+
"properties": {
|
|
60
|
+
"command": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"description": "Custom install command to run in the worktree"
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"required": [
|
|
66
|
+
"command"
|
|
67
|
+
],
|
|
68
|
+
"additionalProperties": false
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"type": "boolean",
|
|
72
|
+
"const": false
|
|
73
|
+
}
|
|
74
|
+
],
|
|
75
|
+
"description": "Dependency install strategy for the worktree"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"required": [
|
|
79
|
+
"ref"
|
|
80
|
+
],
|
|
81
|
+
"additionalProperties": false,
|
|
82
|
+
"description": "Git worktree configuration for a baseline session"
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"required": [
|
|
86
|
+
"worktree"
|
|
87
|
+
],
|
|
88
|
+
"additionalProperties": false
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
"description": "Session source: \"current\" for the working tree, or a worktree config for a baseline"
|
|
92
|
+
},
|
|
93
|
+
"viteConfig": {
|
|
94
|
+
"description": "Path to vite config file, relative to this config (overrides top-level viteConfig)",
|
|
95
|
+
"type": "string"
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"required": [
|
|
99
|
+
"name"
|
|
100
|
+
],
|
|
101
|
+
"additionalProperties": false,
|
|
102
|
+
"description": "A component explorer session"
|
|
103
|
+
},
|
|
104
|
+
"description": "List of explorer sessions"
|
|
105
|
+
},
|
|
106
|
+
"compare": {
|
|
107
|
+
"type": "object",
|
|
108
|
+
"properties": {
|
|
109
|
+
"baseline": {
|
|
110
|
+
"type": "string",
|
|
111
|
+
"description": "Session name to use as the baseline for comparisons"
|
|
112
|
+
},
|
|
113
|
+
"current": {
|
|
114
|
+
"type": "string",
|
|
115
|
+
"description": "Session name to use as the current version for comparisons"
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"required": [
|
|
119
|
+
"baseline",
|
|
120
|
+
"current"
|
|
121
|
+
],
|
|
122
|
+
"additionalProperties": false,
|
|
123
|
+
"description": "Screenshot comparison configuration"
|
|
124
|
+
},
|
|
125
|
+
"viteConfig": {
|
|
126
|
+
"description": "Default vite config file path, relative to this config (default: vite.config.ts)",
|
|
127
|
+
"type": "string"
|
|
128
|
+
},
|
|
129
|
+
"vite": {
|
|
130
|
+
"type": "object",
|
|
131
|
+
"properties": {
|
|
132
|
+
"hmr": {
|
|
133
|
+
"type": "object",
|
|
134
|
+
"properties": {
|
|
135
|
+
"allowedPaths": {
|
|
136
|
+
"type": "array",
|
|
137
|
+
"items": {
|
|
138
|
+
"type": "string"
|
|
139
|
+
},
|
|
140
|
+
"description": "Glob patterns for files that keep HMR; everything else triggers a full reload"
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
"required": [
|
|
144
|
+
"allowedPaths"
|
|
145
|
+
],
|
|
146
|
+
"additionalProperties": false,
|
|
147
|
+
"description": "Vite HMR configuration"
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"additionalProperties": false,
|
|
151
|
+
"description": "Vite configuration overrides"
|
|
152
|
+
},
|
|
153
|
+
"redirection": {
|
|
154
|
+
"type": "object",
|
|
155
|
+
"properties": {
|
|
156
|
+
"port": {
|
|
157
|
+
"type": "integer",
|
|
158
|
+
"minimum": 1,
|
|
159
|
+
"maximum": 65535,
|
|
160
|
+
"description": "Port for the redirection HTTP server"
|
|
161
|
+
},
|
|
162
|
+
"host": {
|
|
163
|
+
"description": "Host to bind the redirection server to (default: localhost)",
|
|
164
|
+
"type": "string"
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
"required": [
|
|
168
|
+
"port"
|
|
169
|
+
],
|
|
170
|
+
"additionalProperties": false,
|
|
171
|
+
"description": "HTTP redirection server that redirects to the session URL"
|
|
172
|
+
},
|
|
173
|
+
"$schema": {
|
|
174
|
+
"type": "string",
|
|
175
|
+
"description": "URL of the JSON Schema for this config file"
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
"required": [
|
|
179
|
+
"sessions"
|
|
180
|
+
],
|
|
181
|
+
"additionalProperties": false,
|
|
182
|
+
"description": "Component Explorer configuration"
|
|
183
|
+
}
|