snapdiff-cli 0.1.4 → 0.1.6
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 +3 -1
- package/dist/commands/approve.js +1 -2
- package/dist/commands/capture.js +1 -2
- package/dist/commands/diff.js +90 -40
- package/dist/commands/init.js +12 -12
- package/dist/commands/status.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<p align="center">一行命令的视觉回归测试工具</p>
|
|
4
4
|
<p align="center">
|
|
5
5
|
<a href="https://www.npmjs.com/package/snapdiff-cli"><img src="https://img.shields.io/npm/v/snapdiff-cli" alt="npm"></a>
|
|
6
|
-
<a href="https://github.com/
|
|
6
|
+
<a href="https://github.com/zixuan57/snapdiff"><img src="https://img.shields.io/badge/license-MIT-blue" alt="license"></a>
|
|
7
7
|
</p>
|
|
8
8
|
</p>
|
|
9
9
|
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
- PR 提交前自动对比视觉差异
|
|
20
20
|
- CI 流水线中集成视觉回归检查
|
|
21
21
|
|
|
22
|
+
<img src="https://raw.githubusercontent.com/zixuan57/snapdiff/main/packages/cli/demo.svg" alt="snapdiff demo" width="800">
|
|
23
|
+
|
|
22
24
|
---
|
|
23
25
|
|
|
24
26
|
## 快速开始
|
package/dist/commands/approve.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import pc from "picocolors";
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import { baselineImagePath, ensureDirs, captureSnapshot, saveBaselineMeta, loadConfig } from "
|
|
4
|
+
import { baselineImagePath, ensureDirs, captureSnapshot, saveBaselineMeta, loadConfig, baselineExists } from "@snapdiff/core";
|
|
5
5
|
export async function approveCommand(name) {
|
|
6
6
|
const cwd = process.cwd();
|
|
7
|
-
const { baselineExists } = await import("@snapdiff/core");
|
|
8
7
|
if (!(await baselineExists(cwd, name))) {
|
|
9
8
|
console.log(pc.yellow(`⚠ "${name}" 没有基线截图,无法接受。`));
|
|
10
9
|
console.log(` 请先运行: ${pc.bold(`npx snapdiff capture <url> --name ${name}`)}`);
|
package/dist/commands/capture.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ensureDirs, captureSnapshotsParallel, baselineImagePath, saveBaselineMeta, loadConfig
|
|
1
|
+
import { ensureDirs, captureSnapshotsParallel, captureSnapshot, baselineImagePath, saveBaselineMeta, loadConfig } from "@snapdiff/core";
|
|
2
2
|
import pc from "picocolors";
|
|
3
3
|
export async function captureCommand(url, options) {
|
|
4
4
|
const cwd = process.cwd();
|
|
@@ -34,7 +34,6 @@ export async function captureCommand(url, options) {
|
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
36
36
|
await ensureDirs(cwd);
|
|
37
|
-
const { captureSnapshot } = await import("@snapdiff/core");
|
|
38
37
|
const snap = {
|
|
39
38
|
name: options.name,
|
|
40
39
|
url,
|
package/dist/commands/diff.js
CHANGED
|
@@ -1,15 +1,44 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { unlink, readdir } from "node:fs/promises";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
2
4
|
import pc from "picocolors";
|
|
3
|
-
import {
|
|
5
|
+
import { ensureDirs, captureSnapshot, captureSnapshotsParallel, baselineImagePath, diffImagePath, compareSnapshots, loadConfig, generateReportSummary, generateHtmlReport, baselineExists, makePercentBar, } from "@snapdiff/core";
|
|
6
|
+
const TEMP_DIR = ".snapdiff/tmp";
|
|
7
|
+
function tempImagePath(cwd, name) {
|
|
8
|
+
return join(cwd, TEMP_DIR, `current-${name}.png`);
|
|
9
|
+
}
|
|
10
|
+
async function cleanupOldFiles(cwd) {
|
|
11
|
+
const maxAge = 7 * 24 * 60 * 60 * 1000;
|
|
12
|
+
const now = Date.now();
|
|
13
|
+
for (const subDir of ["diffs", "reports"]) {
|
|
14
|
+
const dir = join(cwd, ".snapdiff", subDir);
|
|
15
|
+
if (!existsSync(dir))
|
|
16
|
+
continue;
|
|
17
|
+
try {
|
|
18
|
+
const files = await readdir(dir);
|
|
19
|
+
for (const file of files) {
|
|
20
|
+
const filePath = join(dir, file);
|
|
21
|
+
try {
|
|
22
|
+
const stat = await import("node:fs/promises").then(m => m.stat(filePath));
|
|
23
|
+
if (now - stat.mtimeMs > maxAge) {
|
|
24
|
+
await unlink(filePath);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch { }
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch { }
|
|
31
|
+
}
|
|
32
|
+
}
|
|
4
33
|
export async function diffCommand(url, options) {
|
|
5
34
|
const cwd = process.cwd();
|
|
6
35
|
await ensureDirs(cwd);
|
|
7
36
|
const threshold = parseFloat(options.threshold || "0.1");
|
|
8
|
-
// No args
|
|
37
|
+
// No args -> run all snaps from config (parallel capture)
|
|
9
38
|
if (!url && !options.name) {
|
|
10
39
|
const config = await loadConfig(cwd);
|
|
11
40
|
if (!config || config.snaps.length === 0) {
|
|
12
|
-
console.log(pc.yellow("
|
|
41
|
+
console.log(pc.yellow("\u26a0 \u672a\u627e\u5230\u914d\u7f6e\uff0c\u8bf7\u5148\u8fd0\u884c snapdiff init \u6216\u63d0\u4f9b\u53c2\u6570"));
|
|
13
42
|
console.log(` ${pc.bold("npx snapdiff diff <url> --name <name>")}`);
|
|
14
43
|
return;
|
|
15
44
|
}
|
|
@@ -20,79 +49,102 @@ export async function diffCommand(url, options) {
|
|
|
20
49
|
validSnaps.push(snap);
|
|
21
50
|
}
|
|
22
51
|
else {
|
|
23
|
-
console.log(pc.yellow(`\n
|
|
52
|
+
console.log(pc.yellow(`\n \u26a0 "${snap.name}" \u8fd8\u6ca1\u6709\u57fa\u7ebf\u622a\u56fe\u3002`));
|
|
24
53
|
console.log(` ${pc.bold("npx snapdiff capture " + snap.url + " --name " + snap.name)}`);
|
|
25
54
|
}
|
|
26
55
|
}
|
|
27
56
|
if (validSnaps.length === 0) {
|
|
28
|
-
console.log(pc.dim("\n
|
|
57
|
+
console.log(pc.dim("\n \u6ca1\u6709\u9700\u8981\u5bf9\u6bd4\u7684\u9875\u9762\u3002"));
|
|
29
58
|
return;
|
|
30
59
|
}
|
|
31
|
-
|
|
60
|
+
await cleanupOldFiles(cwd);
|
|
61
|
+
console.log(pc.cyan(`\n \u6b63\u5728\u5e76\u884c\u622a\u53d6 ${validSnaps.length} \u4e2a\u9875\u9762...`));
|
|
32
62
|
const timestamp = String(Math.floor(Date.now() / 1000));
|
|
33
|
-
// Phase 1: capture all current states in parallel
|
|
63
|
+
// Phase 1: capture all current states in parallel (to tmp dir)
|
|
34
64
|
const captureTasks = validSnaps.map((snap) => ({
|
|
35
65
|
config: {
|
|
36
66
|
...snap,
|
|
37
67
|
viewport: snap.viewport ?? { width: 1440, height: 900 },
|
|
38
68
|
threshold: snap.threshold ?? 0.1,
|
|
39
69
|
},
|
|
40
|
-
outputPath:
|
|
70
|
+
outputPath: tempImagePath(cwd, snap.name),
|
|
41
71
|
}));
|
|
42
72
|
const captureResults = await captureSnapshotsParallel(captureTasks, 3);
|
|
43
|
-
// Phase 2: compare all diffs
|
|
73
|
+
// Phase 2: compare all diffs
|
|
44
74
|
const results = [];
|
|
75
|
+
const currentPaths = {};
|
|
45
76
|
for (let i = 0; i < validSnaps.length; i++) {
|
|
46
77
|
const snap = validSnaps[i];
|
|
47
|
-
const
|
|
78
|
+
const captureResult = captureResults[i];
|
|
79
|
+
if (captureResult.error) {
|
|
80
|
+
results.push({
|
|
81
|
+
name: snap.name,
|
|
82
|
+
url: snap.url,
|
|
83
|
+
diffPixels: 0,
|
|
84
|
+
totalPixels: 0,
|
|
85
|
+
diffPercent: 0,
|
|
86
|
+
error: '\u622a\u56fe\u5931\u8d25: ' + captureResult.error,
|
|
87
|
+
passed: false,
|
|
88
|
+
});
|
|
89
|
+
console.log(' \u26a0 ' + snap.name + ': \u622a\u56fe\u5931\u8d25 - ' + captureResult.error);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const currentPath = captureResult.imagePath;
|
|
93
|
+
currentPaths[snap.name] = currentPath;
|
|
48
94
|
const diffOut = diffImagePath(cwd, snap.name, timestamp);
|
|
49
95
|
const result = await compareSnapshots({
|
|
50
96
|
baselinePath: baselineImagePath(cwd, snap.name),
|
|
51
97
|
currentPath,
|
|
52
98
|
diffOutputPath: diffOut,
|
|
53
99
|
threshold: threshold / 100,
|
|
100
|
+
maskRegions: snap.maskRegions,
|
|
54
101
|
});
|
|
55
102
|
result.name = snap.name;
|
|
56
103
|
result.url = snap.url;
|
|
57
104
|
results.push(result);
|
|
58
|
-
await unlink(currentPath).catch(() => { });
|
|
59
105
|
if (result.error) {
|
|
60
|
-
console.log("
|
|
106
|
+
console.log(" \u26a0 " + snap.name + ": " + result.error);
|
|
61
107
|
}
|
|
62
108
|
else if (result.passed) {
|
|
63
|
-
console.log(pc.green("
|
|
109
|
+
console.log(pc.green(" \u2705 " + snap.name + " \u2014\u2014 \u65e0\u53d8\u5316 (\u5dee\u5f02 " + result.diffPercent + "%)"));
|
|
64
110
|
}
|
|
65
111
|
else {
|
|
66
|
-
const bar =
|
|
67
|
-
console.log("
|
|
68
|
-
console.log(" " + bar + " " + result.diffPercent + "% (" + result.diffPixels + "
|
|
69
|
-
console.log(pc.dim("
|
|
70
|
-
console.log(pc.cyan("
|
|
112
|
+
const bar = makePercentBar(result.diffPercent, 20);
|
|
113
|
+
console.log(" \u274c " + snap.name);
|
|
114
|
+
console.log(" " + bar + " " + result.diffPercent + "% (" + result.diffPixels + " \u50cf\u7d20)");
|
|
115
|
+
console.log(pc.dim(" \ud83d\udcc4 diff \u56fe: " + result.diffImagePath));
|
|
116
|
+
console.log(pc.cyan(" \u5982\u679c\u8fd9\u662f\u9884\u671f\u7684\u53d8\u66f4: " + pc.bold("npx snapdiff approve " + snap.name)));
|
|
71
117
|
}
|
|
72
118
|
}
|
|
119
|
+
// Generate report BEFORE cleanup (so current images are available)
|
|
73
120
|
if (results.length > 0) {
|
|
74
121
|
console.log(generateReportSummary(results));
|
|
75
|
-
const htmlPath = await generateHtmlReport(results, cwd);
|
|
76
|
-
console.log(pc.cyan("\n
|
|
122
|
+
const htmlPath = await generateHtmlReport(results, cwd, { currentPaths });
|
|
123
|
+
console.log(pc.cyan("\n \ud83d\udcca HTML \u62a5\u544a: " + htmlPath));
|
|
124
|
+
}
|
|
125
|
+
// Cleanup temp current images
|
|
126
|
+
for (const path of Object.values(currentPaths)) {
|
|
127
|
+
await unlink(path).catch(() => { });
|
|
77
128
|
}
|
|
78
129
|
return;
|
|
79
130
|
}
|
|
80
131
|
// Single URL mode
|
|
81
132
|
if (!url || !options.name) {
|
|
82
|
-
console.log(pc.yellow("
|
|
133
|
+
console.log(pc.yellow("\u8bf7\u63d0\u4f9b URL \u548c\u540d\u79f0\uff1a"));
|
|
83
134
|
console.log(" " + pc.bold("npx snapdiff diff <url> --name <name>"));
|
|
84
135
|
return;
|
|
85
136
|
}
|
|
86
137
|
const name = options.name;
|
|
87
138
|
if (!(await baselineExists(cwd, name))) {
|
|
88
|
-
console.log(pc.yellow('\n
|
|
89
|
-
console.log("
|
|
139
|
+
console.log(pc.yellow('\n \u26a0 "' + name + '" \u8fd8\u6ca1\u6709\u57fa\u7ebf\u622a\u56fe\u3002'));
|
|
140
|
+
console.log(" \u8bf7\u5148\u8fd0\u884c: " + pc.bold("npx snapdiff capture " + url + " --name " + name));
|
|
90
141
|
return;
|
|
91
142
|
}
|
|
92
|
-
|
|
143
|
+
await cleanupOldFiles(cwd);
|
|
144
|
+
console.log(pc.cyan("\u6b63\u5728\u5bf9\u6bd4 " + name + "..."));
|
|
93
145
|
const viewport = { width: 1440, height: 900 };
|
|
94
146
|
const t = String(Math.floor(Date.now() / 1000));
|
|
95
|
-
const currentPath =
|
|
147
|
+
const currentPath = tempImagePath(cwd, name);
|
|
96
148
|
const { imagePath: curPath } = await captureSnapshot({
|
|
97
149
|
config: { name, url, viewport, threshold: threshold / 100 },
|
|
98
150
|
outputPath: currentPath,
|
|
@@ -103,28 +155,26 @@ export async function diffCommand(url, options) {
|
|
|
103
155
|
currentPath: curPath,
|
|
104
156
|
diffOutputPath: diffOut,
|
|
105
157
|
threshold: threshold / 100,
|
|
158
|
+
maskRegions: undefined,
|
|
106
159
|
});
|
|
107
160
|
result.name = name;
|
|
108
161
|
result.url = url;
|
|
162
|
+
// Generate report before cleanup
|
|
163
|
+
const htmlPath = await generateHtmlReport([result], cwd, { currentPaths: { [name]: curPath } });
|
|
164
|
+
// Cleanup temp
|
|
109
165
|
await unlink(curPath).catch(() => { });
|
|
110
166
|
if (result.error) {
|
|
111
|
-
console.log("
|
|
167
|
+
console.log(" \u26a0 " + result.error);
|
|
112
168
|
}
|
|
113
169
|
else if (result.passed) {
|
|
114
|
-
console.log(pc.green("
|
|
170
|
+
console.log(pc.green(" \u2705 \u65e0\u53d8\u5316 (\u5dee\u5f02 " + result.diffPercent + "%)"));
|
|
115
171
|
}
|
|
116
172
|
else {
|
|
117
|
-
const bar =
|
|
118
|
-
console.log("
|
|
119
|
-
console.log(" " + bar + " " + result.diffPercent + "% (" + result.diffPixels + "
|
|
120
|
-
console.log(pc.dim("
|
|
121
|
-
console.log(pc.cyan("
|
|
173
|
+
const bar = makePercentBar(result.diffPercent, 20);
|
|
174
|
+
console.log(" \u274c " + name);
|
|
175
|
+
console.log(" " + bar + " " + result.diffPercent + "% (" + result.diffPixels + " \u50cf\u7d20)");
|
|
176
|
+
console.log(pc.dim(" \ud83d\udcc4 diff \u56fe: " + result.diffImagePath));
|
|
177
|
+
console.log(pc.cyan(" \u5982\u679c\u8fd9\u662f\u9884\u671f\u7684\u53d8\u66f4: " + pc.bold("npx snapdiff approve " + name)));
|
|
122
178
|
}
|
|
123
|
-
|
|
124
|
-
console.log(pc.cyan("\n 📊 HTML 报告: " + htmlPath));
|
|
125
|
-
}
|
|
126
|
-
function makeBar(percent, width) {
|
|
127
|
-
const filled = Math.min(Math.round((percent / 100) * width), width);
|
|
128
|
-
const empty = width - filled;
|
|
129
|
-
return pc.red("█".repeat(filled)) + pc.dim("░".repeat(empty));
|
|
179
|
+
console.log(pc.cyan("\n \ud83d\udcca HTML \u62a5\u544a: " + htmlPath));
|
|
130
180
|
}
|
package/dist/commands/init.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ensureDirs, captureSnapshot, baselineImagePath, saveBaselineMeta } from "@snapdiff/core";
|
|
1
2
|
import path from "node:path";
|
|
2
3
|
import { writeFile, mkdir, readFile, appendFile } from "node:fs/promises";
|
|
3
4
|
import { existsSync } from "node:fs";
|
|
@@ -86,7 +87,6 @@ async function setupGitignore(cwd) {
|
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
89
|
async function takeFirstBaseline(cwd, configPath) {
|
|
89
|
-
const { ensureDirs, captureSnapshot, baselineImagePath, saveBaselineMeta } = await import("@snapdiff/core");
|
|
90
90
|
const config = JSON.parse(await readFile(configPath, "utf-8"));
|
|
91
91
|
await ensureDirs(cwd);
|
|
92
92
|
console.log(pc.cyan("\n 正在截取基线..."));
|
|
@@ -111,17 +111,17 @@ async function maybeSetupCi(cwd, ci) {
|
|
|
111
111
|
if (!existsSync(ciDir)) {
|
|
112
112
|
await mkdir(ciDir, { recursive: true });
|
|
113
113
|
}
|
|
114
|
-
const ciYaml = `name: Visual Regression Test
|
|
115
|
-
on: [pull_request]
|
|
116
|
-
jobs:
|
|
117
|
-
snapdiff:
|
|
118
|
-
runs-on: ubuntu-latest
|
|
119
|
-
steps:
|
|
120
|
-
- uses: actions/checkout@v4
|
|
121
|
-
- uses: actions/setup-node@v4
|
|
122
|
-
with:
|
|
123
|
-
node-version: 20
|
|
124
|
-
- run: npx snapdiff diff
|
|
114
|
+
const ciYaml = `name: Visual Regression Test
|
|
115
|
+
on: [pull_request]
|
|
116
|
+
jobs:
|
|
117
|
+
snapdiff:
|
|
118
|
+
runs-on: ubuntu-latest
|
|
119
|
+
steps:
|
|
120
|
+
- uses: actions/checkout@v4
|
|
121
|
+
- uses: actions/setup-node@v4
|
|
122
|
+
with:
|
|
123
|
+
node-version: 20
|
|
124
|
+
- run: npx snapdiff diff
|
|
125
125
|
`;
|
|
126
126
|
await writeFile(path.join(ciDir, "snapdiff.yml"), ciYaml, "utf-8");
|
|
127
127
|
console.log(pc.green(" ✔ 已创建 .github/workflows/snapdiff.yml"));
|
package/dist/commands/status.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import pc from "picocolors";
|
|
2
|
-
import { listBaselines, loadConfig } from "
|
|
2
|
+
import { listBaselines, loadConfig } from "@snapdiff/core";
|
|
3
3
|
export async function statusCommand() {
|
|
4
4
|
const cwd = process.cwd();
|
|
5
5
|
const baselines = await listBaselines(cwd);
|
package/dist/index.js
CHANGED
|
@@ -67,5 +67,5 @@ program
|
|
|
67
67
|
.description("\u67e5\u770b\u6240\u6709\u57fa\u7ebf\u72b6\u6001\uff08\u8868\u683c\u5c55\u793a\uff09")
|
|
68
68
|
.addHelpText("after", pc.dim("\n\u793a\u4f8b:\n $ snapdiff status \u67e5\u770b\u54ea\u4e9b\u9875\u9762\u6709\u57fa\u7ebf\uff0c\u54ea\u4e9b\u8fd8\u672a\u622a\u53d6\n"))
|
|
69
69
|
.action(statusCommand);
|
|
70
|
-
program.addHelpText("afterAll", "\n" + pc.bold("\u5feb\u901f\u5f00\u59cb") + ":\n $ snapdiff init \u9996\u6b21\u8fd0\u884c\uff0c\u8d70\u4e00\u904d\u5411\u5bfc\n $ snapdiff diff \u6539\u5b8c\u4ee3\u7801\u540e\u5bf9\u6bd4\u53d8\u5316\n\n" + pc.bold("\u5178\u578b\u5de5\u4f5c\u6d41") + ":\n 1. " + pc.dim("snapdiff init") + " \u521d\u59cb\u5316\u9879\u76ee\uff0c\u81ea\u52a8\u622a\u53d6\u9996\u5f20\u57fa\u7ebf\n 2. " + pc.dim("\u4fee\u6539\u4ee3\u7801") + " \u6539\u4f60\u7684 CSS/\u7ec4\u4ef6/\u9875\u9762\n 3. " + pc.dim("snapdiff diff") + " \u5bf9\u6bd4\u53d8\u5316\uff0c\u67e5\u770b\u5dee\u5f02\n 4. " + pc.dim("snapdiff approve <name>") + " \u786e\u8ba4\u53d8\u66f4\uff0c\u66f4\u65b0\u57fa\u7ebf\n\n" + pc.dim("\u5b8c\u6574\u6587\u6863: https://github.com/
|
|
70
|
+
program.addHelpText("afterAll", "\n" + pc.bold("\u5feb\u901f\u5f00\u59cb") + ":\n $ snapdiff init \u9996\u6b21\u8fd0\u884c\uff0c\u8d70\u4e00\u904d\u5411\u5bfc\n $ snapdiff diff \u6539\u5b8c\u4ee3\u7801\u540e\u5bf9\u6bd4\u53d8\u5316\n\n" + pc.bold("\u5178\u578b\u5de5\u4f5c\u6d41") + ":\n 1. " + pc.dim("snapdiff init") + " \u521d\u59cb\u5316\u9879\u76ee\uff0c\u81ea\u52a8\u622a\u53d6\u9996\u5f20\u57fa\u7ebf\n 2. " + pc.dim("\u4fee\u6539\u4ee3\u7801") + " \u6539\u4f60\u7684 CSS/\u7ec4\u4ef6/\u9875\u9762\n 3. " + pc.dim("snapdiff diff") + " \u5bf9\u6bd4\u53d8\u5316\uff0c\u67e5\u770b\u5dee\u5f02\n 4. " + pc.dim("snapdiff approve <name>") + " \u786e\u8ba4\u53d8\u66f4\uff0c\u66f4\u65b0\u57fa\u7ebf\n\n" + pc.dim("\u5b8c\u6574\u6587\u6863: https://github.com/zixuan57/snapdiff") + "\n");
|
|
71
71
|
program.parse(process.argv);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "snapdiff-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "????????????????????????? Playwright + pixelmatch",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"prepublishOnly": "npm run build"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
+
"@snapdiff/core": "*",
|
|
19
20
|
"playwright": "^1.52.0",
|
|
20
21
|
"pixelmatch": "^6.0.0",
|
|
21
22
|
"pngjs": "^7.0.0",
|
|
@@ -32,11 +33,11 @@
|
|
|
32
33
|
},
|
|
33
34
|
"repository": {
|
|
34
35
|
"type": "git",
|
|
35
|
-
"url": "git+https://github.com/
|
|
36
|
+
"url": "git+https://github.com/zixuan57/snapdiff.git"
|
|
36
37
|
},
|
|
37
|
-
"homepage": "https://github.com/
|
|
38
|
+
"homepage": "https://github.com/zixuan57/snapdiff",
|
|
38
39
|
"bugs": {
|
|
39
|
-
"url": "https://github.com/
|
|
40
|
+
"url": "https://github.com/zixuan57/snapdiff/issues"
|
|
40
41
|
},
|
|
41
42
|
"license": "MIT",
|
|
42
43
|
"keywords": [
|
|
@@ -47,4 +48,4 @@
|
|
|
47
48
|
"diff",
|
|
48
49
|
"cli"
|
|
49
50
|
]
|
|
50
|
-
}
|
|
51
|
+
}
|