Skip to content

Commit b42ffe6

Browse files
authored
scripts(visual-regression): show target filename (ant-design#48444)
* scripts(visual-regression): show target filename * feat: update * feat: show filename * feat: update
1 parent daba39b commit b42ffe6

File tree

5 files changed

+141
-44
lines changed

5 files changed

+141
-44
lines changed

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@
181181
"@emotion/server": "^11.11.0",
182182
"@ianvs/prettier-plugin-sort-imports": "^4.2.1",
183183
"@madccc/duplicate-package-checker-webpack-plugin": "^1.0.0",
184+
"@microflash/rehype-figure": "^2.1.0",
184185
"@npmcli/run-script": "^7.0.4",
185186
"@octokit/rest": "^20.1.0",
186187
"@qixian.cs/github-contributors-list": "^2.0.1",
@@ -314,13 +315,14 @@
314315
"react-router-dom": "^6.22.3",
315316
"react-sticky-box": "^2.0.5",
316317
"regenerator-runtime": "^0.14.1",
318+
"rehype-stringify": "^10.0.0",
317319
"remark": "^15.0.1",
318320
"remark-cli": "^12.0.0",
319321
"remark-gfm": "^4.0.0",
320-
"remark-html": "^16.0.1",
321322
"remark-lint": "^9.1.2",
322323
"remark-lint-no-undefined-references": "^4.2.1",
323324
"remark-preset-lint-recommended": "^6.1.3",
325+
"remark-rehype": "^11.1.0",
324326
"runes2": "^1.1.4",
325327
"semver": "^7.6.0",
326328
"sharp": "^0.33.3",

scripts/visual-regression/build.ts

+91-36
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@ import os from 'os';
66
import path from 'path';
77
import { Readable } from 'stream';
88
import { finished } from 'stream/promises';
9+
import simpleGit from 'simple-git';
910
import chalk from 'chalk';
1011
import fse from 'fs-extra';
1112
import difference from 'lodash/difference';
1213
import minimist from 'minimist';
1314
import pixelmatch from 'pixelmatch';
1415
import { PNG } from 'pngjs';
15-
import { remark } from 'remark';
16-
import remarkGfm from 'remark-gfm';
17-
import remarkHtml from 'remark-html';
1816
import sharp from 'sharp';
1917

18+
import markdown2Html from './convert';
19+
2020
const ROOT_DIR = process.cwd();
2121
const ALI_OSS_BUCKET = 'antd-visual-diff';
2222

@@ -119,36 +119,100 @@ async function downloadBaseSnapshots(ref: string, targetDir: string) {
119119
});
120120
}
121121

122+
interface IImageDesc {
123+
src: string;
124+
alt: string;
125+
}
126+
127+
function getMdImageTag(desc: IImageDesc, extraCaption?: boolean) {
128+
const { src, alt } = desc;
129+
if (!extraCaption || !alt) {
130+
// in md2html report, we use `@microflash/rehype-figure` to generate a figure
131+
return `![${alt}](${src})`;
132+
}
133+
// show caption with image in github markdown comment
134+
return `![${alt}](${src}) ${alt}`;
135+
}
136+
122137
interface IBadCase {
123138
type: 'removed' | 'changed';
124139
filename: string;
140+
/**
141+
* compare target file
142+
*/
143+
targetFilename?: string;
125144
/**
126145
* 0 - 1
127146
*/
128147
weight: number;
129148
}
130149

131-
function md2Html(md: string) {
132-
return remark().use(remarkGfm).use(remarkHtml).processSync(md).toString();
133-
}
150+
const git = simpleGit();
134151

135-
function parseArgs() {
152+
async function parseArgs() {
136153
// parse args from -- --pr-id=123 --base_ref=feature
137154
const argv = minimist(process.argv.slice(2));
138155
const prId = argv['pr-id'];
139156
assert(prId, 'Missing --pr-id');
140157
const baseRef = argv['base-ref'];
141158
assert(baseRef, 'Missing --base-ref');
159+
160+
const { latest } = await git.log();
161+
142162
return {
143163
prId,
144164
baseRef,
165+
currentRef: latest?.hash.slice(0, 8) || '',
145166
};
146167
}
147168

169+
function generateLineReport(
170+
badCase: IBadCase,
171+
publicPath: string,
172+
currentRef: string,
173+
extraCaption?: boolean,
174+
) {
175+
const { filename, type, targetFilename } = badCase;
176+
177+
let lineHTMLReport = '';
178+
if (type === 'changed') {
179+
lineHTMLReport += '| ';
180+
lineHTMLReport += [
181+
// add ref as query to avoid github cache image object
182+
getMdImageTag({
183+
src: `${publicPath}/images/base/${filename}?ref=${currentRef}`,
184+
alt: targetFilename || '',
185+
}, extraCaption),
186+
getMdImageTag({
187+
src: `${publicPath}/images/current/${filename}?ref=${currentRef}`,
188+
alt: filename,
189+
}, extraCaption),
190+
getMdImageTag({
191+
src: `${publicPath}/images/diff/${filename}?ref=${currentRef}`,
192+
alt: '',
193+
}, extraCaption),
194+
].join(' | ');
195+
lineHTMLReport += ' |\n';
196+
} else if (type === 'removed') {
197+
lineHTMLReport += '| ';
198+
lineHTMLReport += [
199+
getMdImageTag({
200+
src: `${publicPath}/images/base/${filename}?ref=${currentRef}`,
201+
alt: targetFilename || '',
202+
}, extraCaption),
203+
`⛔️⛔️⛔️ Missing ⛔️⛔️⛔️`,
204+
`🚨🚨🚨 Removed 🚨🚨🚨`,
205+
].join(' | ');
206+
lineHTMLReport += ' |\n';
207+
}
208+
return lineHTMLReport;
209+
}
210+
148211
function generateReport(
149212
badCases: IBadCase[],
150213
targetBranch: string,
151214
targetRef: string,
215+
currentRef: string,
152216
prId: string,
153217
): [string, string] {
154218
const reportDirname = path.basename(REPORT_DIR);
@@ -174,15 +238,15 @@ function generateReport(
174238
'<img src="https://github.com/ant-design/ant-design/assets/507615/2d1a77dc-dbc6-4b0f-9cbc-19a43d3c29cd" width="300" />',
175239
].join('\n');
176240

177-
return [mdStr, md2Html(mdStr)];
241+
return [mdStr, markdown2Html(mdStr)];
178242
}
179243

180244
let reportMdStr = `
181245
${commonHeader}
182246
${fullReport}
183247
184-
| Image name | Expected | Actual | Diff |
185-
| --- | --- | --- | --- |
248+
| Expected (Branch ${targetBranch}) | Actual (Current PR) | Diff |
249+
| --- | --- | --- |
186250
`.trim();
187251

188252
reportMdStr += '\n';
@@ -192,44 +256,33 @@ ${fullReport}
192256
let diffCount = 0;
193257

194258
for (const badCase of badCases) {
195-
const { filename, type } = badCase;
196-
let lineReportMdStr = '';
197-
if (type === 'changed') {
198-
lineReportMdStr += '| ';
199-
lineReportMdStr += [
200-
`\`${badCase.filename}\``,
201-
`![${targetBranch}: ${targetRef}](${publicPath}/images/base/${filename})`,
202-
`![current: pr-${prId}](${publicPath}/images/current/${filename})`,
203-
`![diff](${publicPath}/images/diff/${filename})`,
204-
].join(' | ');
205-
lineReportMdStr += ' |\n';
206-
} else if (type === 'removed') {
207-
lineReportMdStr += '| ';
208-
lineReportMdStr += [
209-
`\`${badCase.filename}\``,
210-
`![${targetBranch}: ${targetRef}](${publicPath}/images/base/${filename})`,
211-
`⛔️⛔️⛔️ Missing ⛔️⛔️⛔️`,
212-
`🚨🚨🚨 Removed 🚨🚨🚨`,
213-
].join(' | ');
214-
lineReportMdStr += ' |\n';
215-
}
216-
217259
diffCount += 1;
218260
if (diffCount <= 10) {
219-
reportMdStr += lineReportMdStr;
261+
// 将图片下方增加文件名
262+
reportMdStr += generateLineReport(
263+
badCase,
264+
publicPath,
265+
currentRef,
266+
true,
267+
);
220268
}
221269

222-
fullVersionMd += lineReportMdStr;
270+
fullVersionMd += generateLineReport(
271+
badCase,
272+
publicPath,
273+
currentRef,
274+
false,
275+
);
223276
}
224277

225278
reportMdStr += addonFullReportDesc;
226279

227280
// convert fullVersionMd to html
228-
return [reportMdStr, md2Html(fullVersionMd)];
281+
return [reportMdStr, markdown2Html(fullVersionMd)];
229282
}
230283

231284
async function boot() {
232-
const { prId, baseRef: targetBranch = 'master' } = parseArgs();
285+
const { prId, baseRef: targetBranch = 'master', currentRef } = await parseArgs();
233286

234287
const baseImgSourceDir = path.resolve(ROOT_DIR, `./imageSnapshots-${targetBranch}`);
235288

@@ -324,6 +377,7 @@ async function boot() {
324377
badCases.push({
325378
type: 'changed',
326379
filename: compareImgName,
380+
targetFilename: baseImgName,
327381
weight: mismatchedPxPercent,
328382
});
329383
} else {
@@ -340,6 +394,7 @@ async function boot() {
340394
badCases,
341395
targetBranch,
342396
targetCommitSha,
397+
currentRef,
343398
prId,
344399
);
345400
await fse.writeFile(path.join(REPORT_DIR, './report.md'), reportMdStr);

scripts/visual-regression/convert.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/* eslint-disable compat/compat */
2+
/* eslint-disable no-console, no-await-in-loop, import/no-extraneous-dependencies, no-restricted-syntax */
3+
import { remark } from 'remark';
4+
import remarkGfm from 'remark-gfm';
5+
import remarkRehype from 'remark-rehype';
6+
import rehypeStringify from 'rehype-stringify';
7+
import rehypeFigure from '@microflash/rehype-figure';
8+
9+
export default function markdown2Html(content: string) {
10+
return remark()
11+
.use(remarkGfm)
12+
.use(remarkRehype)
13+
.use(rehypeFigure)
14+
.use(rehypeStringify)
15+
.processSync(content)
16+
.toString();
17+
}

scripts/visual-regression/report-template.html

+28-7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@
1212
padding-bottom: 16px;
1313
}
1414

15+
/* figcaption */
16+
figcaption {
17+
color: #a3a3a3;
18+
text-align: center;
19+
}
20+
21+
figure {
22+
cursor: pointer;
23+
}
24+
1525
/* Table Styles */
1626
table {
1727
width: 100%;
@@ -33,12 +43,7 @@
3343

3444
th,
3545
td {
36-
width: 10%;
37-
}
38-
39-
th+th,
40-
td+td {
41-
width: 30%;
46+
width: 33%;
4247
}
4348

4449
th {
@@ -89,6 +94,22 @@
8994

9095
<body>
9196
{{reportContent}}
97+
98+
<script>
99+
window.addEventListener('click', function (e) {
100+
if (e.target.tagName === 'FIGCAPTION') {
101+
// get previous sibling
102+
const img = e.target.previousElementSibling;
103+
if (img.tagName === 'IMG' && img.src) {
104+
window.open(img.src, '_blank');
105+
}
106+
}
107+
108+
if (e.target.tagName === 'IMG' && e.target.src) {
109+
window.open(e.target.src, '_blank');
110+
}
111+
});
112+
</script>
92113
</body>
93114

94-
</html>
115+
</html>

typings/custom-typings.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,5 @@ declare module '@npmcli/run-script' {
2525
[key: string]: string | string[] | boolean | NodeJS.ProcessEnv;
2626
}): Promise<void>;
2727
}
28+
29+
declare module '@microflash/rehype-figure';

0 commit comments

Comments
 (0)