mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-23 18:50:06 +08:00
scripts(visual-regression): show target filename (#48444)
* scripts(visual-regression): show target filename * feat: update * feat: show filename * feat: update
This commit is contained in:
parent
daba39b88a
commit
b42ffe64f4
@ -181,6 +181,7 @@
|
||||
"@emotion/server": "^11.11.0",
|
||||
"@ianvs/prettier-plugin-sort-imports": "^4.2.1",
|
||||
"@madccc/duplicate-package-checker-webpack-plugin": "^1.0.0",
|
||||
"@microflash/rehype-figure": "^2.1.0",
|
||||
"@npmcli/run-script": "^7.0.4",
|
||||
"@octokit/rest": "^20.1.0",
|
||||
"@qixian.cs/github-contributors-list": "^2.0.1",
|
||||
@ -314,13 +315,14 @@
|
||||
"react-router-dom": "^6.22.3",
|
||||
"react-sticky-box": "^2.0.5",
|
||||
"regenerator-runtime": "^0.14.1",
|
||||
"rehype-stringify": "^10.0.0",
|
||||
"remark": "^15.0.1",
|
||||
"remark-cli": "^12.0.0",
|
||||
"remark-gfm": "^4.0.0",
|
||||
"remark-html": "^16.0.1",
|
||||
"remark-lint": "^9.1.2",
|
||||
"remark-lint-no-undefined-references": "^4.2.1",
|
||||
"remark-preset-lint-recommended": "^6.1.3",
|
||||
"remark-rehype": "^11.1.0",
|
||||
"runes2": "^1.1.4",
|
||||
"semver": "^7.6.0",
|
||||
"sharp": "^0.33.3",
|
||||
|
@ -6,17 +6,17 @@ import os from 'os';
|
||||
import path from 'path';
|
||||
import { Readable } from 'stream';
|
||||
import { finished } from 'stream/promises';
|
||||
import simpleGit from 'simple-git';
|
||||
import chalk from 'chalk';
|
||||
import fse from 'fs-extra';
|
||||
import difference from 'lodash/difference';
|
||||
import minimist from 'minimist';
|
||||
import pixelmatch from 'pixelmatch';
|
||||
import { PNG } from 'pngjs';
|
||||
import { remark } from 'remark';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import remarkHtml from 'remark-html';
|
||||
import sharp from 'sharp';
|
||||
|
||||
import markdown2Html from './convert';
|
||||
|
||||
const ROOT_DIR = process.cwd();
|
||||
const ALI_OSS_BUCKET = 'antd-visual-diff';
|
||||
|
||||
@ -119,36 +119,100 @@ async function downloadBaseSnapshots(ref: string, targetDir: string) {
|
||||
});
|
||||
}
|
||||
|
||||
interface IImageDesc {
|
||||
src: string;
|
||||
alt: string;
|
||||
}
|
||||
|
||||
function getMdImageTag(desc: IImageDesc, extraCaption?: boolean) {
|
||||
const { src, alt } = desc;
|
||||
if (!extraCaption || !alt) {
|
||||
// in md2html report, we use `@microflash/rehype-figure` to generate a figure
|
||||
return `![${alt}](${src})`;
|
||||
}
|
||||
// show caption with image in github markdown comment
|
||||
return `![${alt}](${src}) ${alt}`;
|
||||
}
|
||||
|
||||
interface IBadCase {
|
||||
type: 'removed' | 'changed';
|
||||
filename: string;
|
||||
/**
|
||||
* compare target file
|
||||
*/
|
||||
targetFilename?: string;
|
||||
/**
|
||||
* 0 - 1
|
||||
*/
|
||||
weight: number;
|
||||
}
|
||||
|
||||
function md2Html(md: string) {
|
||||
return remark().use(remarkGfm).use(remarkHtml).processSync(md).toString();
|
||||
}
|
||||
const git = simpleGit();
|
||||
|
||||
function parseArgs() {
|
||||
async function parseArgs() {
|
||||
// parse args from -- --pr-id=123 --base_ref=feature
|
||||
const argv = minimist(process.argv.slice(2));
|
||||
const prId = argv['pr-id'];
|
||||
assert(prId, 'Missing --pr-id');
|
||||
const baseRef = argv['base-ref'];
|
||||
assert(baseRef, 'Missing --base-ref');
|
||||
|
||||
const { latest } = await git.log();
|
||||
|
||||
return {
|
||||
prId,
|
||||
baseRef,
|
||||
currentRef: latest?.hash.slice(0, 8) || '',
|
||||
};
|
||||
}
|
||||
|
||||
function generateLineReport(
|
||||
badCase: IBadCase,
|
||||
publicPath: string,
|
||||
currentRef: string,
|
||||
extraCaption?: boolean,
|
||||
) {
|
||||
const { filename, type, targetFilename } = badCase;
|
||||
|
||||
let lineHTMLReport = '';
|
||||
if (type === 'changed') {
|
||||
lineHTMLReport += '| ';
|
||||
lineHTMLReport += [
|
||||
// add ref as query to avoid github cache image object
|
||||
getMdImageTag({
|
||||
src: `${publicPath}/images/base/${filename}?ref=${currentRef}`,
|
||||
alt: targetFilename || '',
|
||||
}, extraCaption),
|
||||
getMdImageTag({
|
||||
src: `${publicPath}/images/current/${filename}?ref=${currentRef}`,
|
||||
alt: filename,
|
||||
}, extraCaption),
|
||||
getMdImageTag({
|
||||
src: `${publicPath}/images/diff/${filename}?ref=${currentRef}`,
|
||||
alt: '',
|
||||
}, extraCaption),
|
||||
].join(' | ');
|
||||
lineHTMLReport += ' |\n';
|
||||
} else if (type === 'removed') {
|
||||
lineHTMLReport += '| ';
|
||||
lineHTMLReport += [
|
||||
getMdImageTag({
|
||||
src: `${publicPath}/images/base/${filename}?ref=${currentRef}`,
|
||||
alt: targetFilename || '',
|
||||
}, extraCaption),
|
||||
`⛔️⛔️⛔️ Missing ⛔️⛔️⛔️`,
|
||||
`🚨🚨🚨 Removed 🚨🚨🚨`,
|
||||
].join(' | ');
|
||||
lineHTMLReport += ' |\n';
|
||||
}
|
||||
return lineHTMLReport;
|
||||
}
|
||||
|
||||
function generateReport(
|
||||
badCases: IBadCase[],
|
||||
targetBranch: string,
|
||||
targetRef: string,
|
||||
currentRef: string,
|
||||
prId: string,
|
||||
): [string, string] {
|
||||
const reportDirname = path.basename(REPORT_DIR);
|
||||
@ -174,15 +238,15 @@ function generateReport(
|
||||
'<img src="https://github.com/ant-design/ant-design/assets/507615/2d1a77dc-dbc6-4b0f-9cbc-19a43d3c29cd" width="300" />',
|
||||
].join('\n');
|
||||
|
||||
return [mdStr, md2Html(mdStr)];
|
||||
return [mdStr, markdown2Html(mdStr)];
|
||||
}
|
||||
|
||||
let reportMdStr = `
|
||||
${commonHeader}
|
||||
${fullReport}
|
||||
|
||||
| Image name | Expected | Actual | Diff |
|
||||
| --- | --- | --- | --- |
|
||||
| Expected (Branch ${targetBranch}) | Actual (Current PR) | Diff |
|
||||
| --- | --- | --- |
|
||||
`.trim();
|
||||
|
||||
reportMdStr += '\n';
|
||||
@ -192,44 +256,33 @@ ${fullReport}
|
||||
let diffCount = 0;
|
||||
|
||||
for (const badCase of badCases) {
|
||||
const { filename, type } = badCase;
|
||||
let lineReportMdStr = '';
|
||||
if (type === 'changed') {
|
||||
lineReportMdStr += '| ';
|
||||
lineReportMdStr += [
|
||||
`\`${badCase.filename}\``,
|
||||
`![${targetBranch}: ${targetRef}](${publicPath}/images/base/${filename})`,
|
||||
`![current: pr-${prId}](${publicPath}/images/current/${filename})`,
|
||||
`![diff](${publicPath}/images/diff/${filename})`,
|
||||
].join(' | ');
|
||||
lineReportMdStr += ' |\n';
|
||||
} else if (type === 'removed') {
|
||||
lineReportMdStr += '| ';
|
||||
lineReportMdStr += [
|
||||
`\`${badCase.filename}\``,
|
||||
`![${targetBranch}: ${targetRef}](${publicPath}/images/base/${filename})`,
|
||||
`⛔️⛔️⛔️ Missing ⛔️⛔️⛔️`,
|
||||
`🚨🚨🚨 Removed 🚨🚨🚨`,
|
||||
].join(' | ');
|
||||
lineReportMdStr += ' |\n';
|
||||
}
|
||||
|
||||
diffCount += 1;
|
||||
if (diffCount <= 10) {
|
||||
reportMdStr += lineReportMdStr;
|
||||
// 将图片下方增加文件名
|
||||
reportMdStr += generateLineReport(
|
||||
badCase,
|
||||
publicPath,
|
||||
currentRef,
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
fullVersionMd += lineReportMdStr;
|
||||
fullVersionMd += generateLineReport(
|
||||
badCase,
|
||||
publicPath,
|
||||
currentRef,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
reportMdStr += addonFullReportDesc;
|
||||
|
||||
// convert fullVersionMd to html
|
||||
return [reportMdStr, md2Html(fullVersionMd)];
|
||||
return [reportMdStr, markdown2Html(fullVersionMd)];
|
||||
}
|
||||
|
||||
async function boot() {
|
||||
const { prId, baseRef: targetBranch = 'master' } = parseArgs();
|
||||
const { prId, baseRef: targetBranch = 'master', currentRef } = await parseArgs();
|
||||
|
||||
const baseImgSourceDir = path.resolve(ROOT_DIR, `./imageSnapshots-${targetBranch}`);
|
||||
|
||||
@ -324,6 +377,7 @@ async function boot() {
|
||||
badCases.push({
|
||||
type: 'changed',
|
||||
filename: compareImgName,
|
||||
targetFilename: baseImgName,
|
||||
weight: mismatchedPxPercent,
|
||||
});
|
||||
} else {
|
||||
@ -340,6 +394,7 @@ async function boot() {
|
||||
badCases,
|
||||
targetBranch,
|
||||
targetCommitSha,
|
||||
currentRef,
|
||||
prId,
|
||||
);
|
||||
await fse.writeFile(path.join(REPORT_DIR, './report.md'), reportMdStr);
|
||||
|
17
scripts/visual-regression/convert.ts
Normal file
17
scripts/visual-regression/convert.ts
Normal file
@ -0,0 +1,17 @@
|
||||
/* eslint-disable compat/compat */
|
||||
/* eslint-disable no-console, no-await-in-loop, import/no-extraneous-dependencies, no-restricted-syntax */
|
||||
import { remark } from 'remark';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import remarkRehype from 'remark-rehype';
|
||||
import rehypeStringify from 'rehype-stringify';
|
||||
import rehypeFigure from '@microflash/rehype-figure';
|
||||
|
||||
export default function markdown2Html(content: string) {
|
||||
return remark()
|
||||
.use(remarkGfm)
|
||||
.use(remarkRehype)
|
||||
.use(rehypeFigure)
|
||||
.use(rehypeStringify)
|
||||
.processSync(content)
|
||||
.toString();
|
||||
}
|
@ -12,6 +12,16 @@
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
/* figcaption */
|
||||
figcaption {
|
||||
color: #a3a3a3;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
figure {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Table Styles */
|
||||
table {
|
||||
width: 100%;
|
||||
@ -33,12 +43,7 @@
|
||||
|
||||
th,
|
||||
td {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
th+th,
|
||||
td+td {
|
||||
width: 30%;
|
||||
width: 33%;
|
||||
}
|
||||
|
||||
th {
|
||||
@ -89,6 +94,22 @@
|
||||
|
||||
<body>
|
||||
{{reportContent}}
|
||||
|
||||
<script>
|
||||
window.addEventListener('click', function (e) {
|
||||
if (e.target.tagName === 'FIGCAPTION') {
|
||||
// get previous sibling
|
||||
const img = e.target.previousElementSibling;
|
||||
if (img.tagName === 'IMG' && img.src) {
|
||||
window.open(img.src, '_blank');
|
||||
}
|
||||
}
|
||||
|
||||
if (e.target.tagName === 'IMG' && e.target.src) {
|
||||
window.open(e.target.src, '_blank');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
2
typings/custom-typings.d.ts
vendored
2
typings/custom-typings.d.ts
vendored
@ -25,3 +25,5 @@ declare module '@npmcli/run-script' {
|
||||
[key: string]: string | string[] | boolean | NodeJS.ProcessEnv;
|
||||
}): Promise<void>;
|
||||
}
|
||||
|
||||
declare module '@microflash/rehype-figure';
|
||||
|
Loading…
Reference in New Issue
Block a user