Skip to content

Commit adac537

Browse files
committed
feat: 本地校验脚本
1 parent 607d7c6 commit adac537

3 files changed

Lines changed: 197 additions & 1 deletion

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
---
2+
name: nutui-build-local-verify
3+
description: NutUI 比例缩放本地验证——默认就地覆盖:每个组件 SCSS 写回 src/packages 下同一路径(如 actionsheet/actionsheet.scss→同文件);--mirror 才写到 scale-verify/ 对照。不写 build。
4+
disable-model-invocation: true
5+
---
6+
7+
# NutUI Build Local Verify
8+
9+
## 在做什么
10+
11+
**只做一步**:用 `scripts/px-to-scale-px-in-component-scss.cjs` 把组件 SCSS 里裸 `px` 转成 `scale-px` 等,并把结果写回磁盘。
12+
13+
- **默认(就地覆盖)**:对每个匹配的 `.scss`**读、写都是同一路径**——相对 `src/packages` 的路径不变。例如 `src/packages/actionsheet/actionsheet.scss` 转换后仍写回该文件,不会改到别的目录或改名。
14+
- **`--mirror`**:不写源码;结果写到 **`scale-verify/<与 src/packages 相同的相对路径>`**(例如 `scale-verify/actionsheet/actionsheet.scss`),便于 diff。
15+
16+
之后是否再跑 `pnpm run build`、是否用别的工具核对,由你自行决定;本 skill **不要求** build。
17+
18+
## 覆盖原 SCSS(推荐)
19+
20+
**nutui-react 仓库根目录** 执行。**务必先 commit / stash**,用完 `git restore src/packages``git checkout -- src/packages` 恢复。
21+
22+
```bash
23+
pnpm run verify-scale
24+
```
25+
26+
等价:
27+
28+
```bash
29+
node .cursor/skills/nutui-build-local-verify/scripts/verify-scale-generation.mjs
30+
```
31+
32+
`--in-place` / `-i` 与默认等价。)
33+
34+
## 报告
35+
36+
路径:**`scale-verify/report.json`**。覆盖模式下看 `overwriteSource === true``changedFileCount``changedFiles`
37+
38+
## 其它命令
39+
40+
```bash
41+
# 删除仓库根下 scale-verify/ 整目录(含 report;不还原已覆盖的 src/packages)
42+
node .cursor/skills/nutui-build-local-verify/scripts/verify-scale-generation.mjs --clean
43+
```
44+
45+
**可选**(只镜像、不覆盖源码):
46+
47+
```bash
48+
pnpm run verify-scale:mirror
49+
```
50+
51+
`--mirror``--in-place` 不能同时使用。
52+
53+
## 核对清单
54+
55+
- [ ] 覆盖前已 git 可回滚
56+
- [ ] `changedFiles` 抽样无 `scale-px(0px)`、无重复嵌套 `scale-px`
57+
- [ ] `font-size` / `font` 未被误改(转换器会跳过)
58+
59+
## 给用户的一句话结论
60+
61+
- 脚本跑完 + `changedFileCount` + 列 2~3 个 `changedFiles`
62+
- **覆盖的是真实源码**时,验证完用 **git 恢复**
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
#!/usr/bin/env node
2+
/**
3+
* 默认:每个文件读自且写回 src/packages 下同一路径(如 …/actionsheet/actionsheet.scss)。
4+
* 不包含 build;自行 git diff / 恢复即可。
5+
*/
6+
import fs from 'node:fs/promises'
7+
import path from 'path'
8+
import { createRequire } from 'node:module'
9+
10+
const require = createRequire(import.meta.url)
11+
const transform = require(path.resolve(process.cwd(), 'scripts/px-to-scale-px-in-component-scss.cjs'))
12+
13+
const repoRoot = process.cwd()
14+
const packagesRoot = path.resolve(repoRoot, 'src/packages')
15+
const outRoot = path.resolve(repoRoot, 'scale-verify')
16+
const reportPath = path.resolve(outRoot, 'report.json')
17+
18+
const argv = new Set(process.argv.slice(2))
19+
const shouldClean = argv.has('--clean')
20+
const mirrorMode = argv.has('--mirror')
21+
/** 默认覆盖 src/packages 原 .scss;传 --mirror 则只写 scale-verify/ */
22+
const inPlace = !mirrorMode
23+
24+
if (mirrorMode && (argv.has('--in-place') || argv.has('-i'))) {
25+
console.error('[scale-verify] 不能同时使用 --mirror 与 --in-place / -i')
26+
process.exit(1)
27+
}
28+
29+
function isScssFile(name) {
30+
return name.endsWith('.scss')
31+
}
32+
33+
function shouldSkip(relPath) {
34+
const p = relPath.replaceAll('\\', '/')
35+
if (p.includes('/demos/')) return true
36+
if (p.includes('/__test__/')) return true
37+
if (p.includes('/__tests__/')) return true
38+
if (p.includes('/__snapshots__/')) return true
39+
if (p.startsWith('.scale-verify/')) return true
40+
return false
41+
}
42+
43+
async function walkScssFiles(dir, base = dir, list = []) {
44+
const entries = await fs.readdir(dir, { withFileTypes: true })
45+
for (const entry of entries) {
46+
const abs = path.resolve(dir, entry.name)
47+
const rel = path.relative(base, abs)
48+
if (entry.isDirectory()) {
49+
await walkScssFiles(abs, base, list)
50+
continue
51+
}
52+
if (!entry.isFile() || !isScssFile(entry.name)) continue
53+
if (shouldSkip(rel)) continue
54+
list.push(abs)
55+
}
56+
return list
57+
}
58+
59+
async function ensureReportDir() {
60+
await fs.mkdir(outRoot, { recursive: true })
61+
}
62+
63+
async function prepareOutputLayout() {
64+
if (shouldClean) {
65+
await fs.rm(outRoot, { recursive: true, force: true })
66+
console.log('[scale-verify] cleaned:', path.relative(repoRoot, outRoot))
67+
return
68+
}
69+
70+
await fs.rm(outRoot, { recursive: true, force: true })
71+
await fs.mkdir(outRoot, { recursive: true })
72+
}
73+
74+
async function main() {
75+
await prepareOutputLayout()
76+
if (shouldClean) {
77+
return
78+
}
79+
80+
const files = await walkScssFiles(packagesRoot)
81+
files.sort()
82+
83+
const changed = []
84+
for (const absFile of files) {
85+
const rel = path.relative(packagesRoot, absFile)
86+
const source = await fs.readFile(absFile, 'utf8')
87+
const transformed = transform(source)
88+
if (source === transformed) continue
89+
90+
const targetFile = inPlace ? absFile : path.resolve(outRoot, rel)
91+
if (!inPlace) {
92+
await fs.mkdir(path.dirname(targetFile), { recursive: true })
93+
}
94+
await fs.writeFile(targetFile, transformed, 'utf8')
95+
changed.push(rel.replaceAll('\\', '/'))
96+
}
97+
98+
await ensureReportDir()
99+
const scssWriteRoot = inPlace
100+
? path.relative(repoRoot, packagesRoot).replaceAll('\\', '/')
101+
: path.relative(repoRoot, outRoot).replaceAll('\\', '/')
102+
103+
const report = {
104+
generatedAt: new Date().toISOString(),
105+
mode: inPlace ? 'in-place' : 'mirror',
106+
overwriteSource: inPlace,
107+
/** 本次写入的 SCSS 根路径:原地为 src/packages,镜像为仓库根下 scale-verify */
108+
scssWriteRoot,
109+
/** 镜像模式下的实验目录;原地模式为 null */
110+
outDir: inPlace ? null : path.relative(repoRoot, outRoot).replaceAll('\\', '/'),
111+
reportPath: path.relative(repoRoot, reportPath).replaceAll('\\', '/'),
112+
totalScssFiles: files.length,
113+
changedFileCount: changed.length,
114+
changedFiles: changed,
115+
}
116+
await fs.writeFile(reportPath, `${JSON.stringify(report, null, 2)}\n`, 'utf8')
117+
118+
console.log('[scale-verify] mode:', report.mode)
119+
if (!inPlace) {
120+
console.log('[scale-verify] outDir:', report.outDir)
121+
} else {
122+
console.log('[scale-verify] wrote into:', path.relative(repoRoot, packagesRoot))
123+
}
124+
console.log('[scale-verify] totalScssFiles:', report.totalScssFiles)
125+
console.log('[scale-verify] changedFileCount:', report.changedFileCount)
126+
console.log('[scale-verify] report:', path.relative(repoRoot, reportPath))
127+
}
128+
129+
main().catch((err) => {
130+
console.error('[scale-verify] failed:', err)
131+
process.exitCode = 1
132+
})

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,9 @@
101101
"e2e:run:taro": "start-server-and-test dev:taro:h5 http://localhost:10086 cypress:run:taro",
102102
"e2e:open:taro": "start-server-and-test dev:taro:h5 http://localhost:10086 cypress:open:taro",
103103
"update:taro:entry": "node ./scripts/harmony/update-taro-entry",
104-
"upgradeTaro": "pnpm --dir ./packages/nutui-taro-demo upgradeTaro"
104+
"upgradeTaro": "pnpm --dir ./packages/nutui-taro-demo upgradeTaro",
105+
"verify-scale": "node .cursor/skills/nutui-build-local-verify/scripts/verify-scale-generation.mjs",
106+
"verify-scale:mirror": "node .cursor/skills/nutui-build-local-verify/scripts/verify-scale-generation.mjs --mirror"
105107
},
106108
"lint-staged": {
107109
"*.{scss,md}": "prettier --write",

0 commit comments

Comments
 (0)