JS 引用类名/变量核对(ui-js-refs.py)¶
位置:
deploy/nfos/tools/ui-js-refs.py| 语言:python3 | 是否需要 root:否
工具性质:本地静态核对(只读 7 个站点的前端 JS + 候选 CSS;只写 --out 指定的文件)
运行前提:仓库检出必须在场(os.walk 遍历 apps/web/<site>/js)。可从任意位置运行(工具自动向上找到含 deploy/nfos 的祖先目录)
部署状态:随仓库检出运行,不部署到 /opt/Cy/services/system.d/nfos/
用途¶
扫描全部前端 JS 引用到的「类名 / CSS 变量」,核对候选 CSS 是否已定义。
源码 docstring 说明的动因(逐字引用):
为什么需要:候选 A 用基线头部合成,而并发 agent 从 19:19 起也在改 JS(新增 col.wrap /
col.ellipsis 等)。只要 JS 输出的类名在候选 CSS 里没有定义,那一列就会退化成浏览器默认
行为(无换行控制、或被祖先裁掉)—— 所以必须逐个核对。
实现要点:
| 环节 | 源码行为 |
|---|---|
| 扫描范围 | 源码内 SITES 的 7 个站点:index console online store hub mcp tools,各自 apps/web/<site>/js 递归遍历 .js(跳过文件名含 .bak 的) |
| 类名上下文 | 只统计类上下文里的 nf-* 词元,正则共 8 条:class="..."、class='...'、className='...'、className="..."、class: '...'、classList.add/remove/toggle('...')、(U.el\|mk\|el)('tag','nf-x')、add('...');词元还需整体匹配 ^nf-[a-z0-9-]+$ |
| 变量 | var(--nf-...) 形式记入引用;CSS 侧扫 --nf-...: 定义 |
| CSS 定义 | 先剥离 /* ... */ 注释,再按 \.(nf-[a-z0-9-]+) 与 (--nf-[a-z0-9-]+)\s*: 提取 |
| 输出 4 段 | 1) JS 引用但 CSS 未定义的类(含引用处 site/js/file:line,最多列 6 处)2) 同上的变量 3) JS 引用到的全部类(OK / **MISS**) 4) 全部变量 |
本工具不加载
lint-layout.py—— 与同批其它ui-*.py不同,它自带一套纯正则的 CSS 定义提取。
典型场景¶
- 合成/挑选候选 CSS(例如“候选 A”)后,确认所有 JS 里用过的
nf-*类与--nf-*变量都被候选 CSS 定义,避免那一列静默退化成浏览器默认行为; - 并发改 JS(新增
col.wrap/col.ellipsis之类)与改 CSS 同时进行时,用它在合并前对齐两侧; - 排查“某个类在页面上完全没样式”时,先确认它是否属于
**MISS**。
用法与参数¶
源码 docstring 给出的用法(逐字引用,.scratch/ 为升级前旧路径;本页按新位置书写,路径参数不变):
用法:
python .scratch/ui-js-refs.py --css .scratch/nf-css-candidate-A.css --out .scratch/ui-js-refs.txt
参数来自 argparse.ArgumentParser():
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
--css |
字符串(文件路径) | 无默认值(required=True) |
候选 CSS(被当作“定义方”核对) |
--out |
字符串(文件路径) | ''(空 = 写 stdout) |
输出文件;给值时打印 written: <path> (<N> bytes) |
无参数时的默认行为:没有默认行为 —— --css 是必填,缺失时 argparse 报错并以退出码 2 结束。JS 侧路径不由参数控制,固定遍历仓库内 7 个站点。
--css按当前工作目录解析;JS 扫描路径按仓库根解析(源码用ROOT拼接),因此同样要求仓库检出在场。
示例¶
从仓库根目录执行:
python deploy/nfos/tools/ui-js-refs.py --css apps/web/index/css/nf.css --out .scratch/ui-js-refs.txt
期望输出形态:
正文形如:
== 前端 JS 引用的类名 / CSS 变量 vs 候选 CSS 定义 ==
css = apps/web/index/css/nf.css
CSS 里定义的 .nf-* 类:... 个;定义的 --nf-* 变量:... 个
JS 里引用的 .nf-* 类:... 个;引用的 --nf-* 变量:... 个
-- 1. JS 引用了但候选 CSS 未定义的类(0) --
(无)
...
-- 3. JS 引用到的全部类(... 个,逐个核对结果) --
OK .nf-table 引用 12 处
**MISS** .nf-xxx 引用 2 处
| 情形 | 期望退出码 |
|---|---|
| 正常完成 | 0(sys.exit(main()) 且 main() 恒返回 0) |
缺 --css |
2(argparse 报错) |
CSS 文件不存在 / --out 不可写 |
1(Python traceback) |
**MISS**不影响退出码:即使存在未定义的类,也仍返回0;判定要看报告正文的-- 1./-- 2.两段计数。
依赖与权限¶
- 语言/版本:Python 3(
#!/usr/bin/env python3)。 - 第三方依赖:无,标准库
argparse/io/os/re/sys。 - 仓库依赖:必需 —— 递归遍历
apps/web/index|console|online|store|hub|mcp|tools/js(_nf_repo_root()向上找第一个含deploy/nfos的祖先目录)。不加载lint-layout.py。 - 权限:不需要 root;不需要网络(纯离线);写权限仅用于
--out。
风险与注意事项¶
- 只读输入,只写
--out:不修改任何 JS 或 CSS。不传--out时只写 stdout,不落盘。 - 类名抽取是启发式:只认 8 条正则;动态拼接(
'nf-' + x、模板字符串)抽不到。其中add('...')这条最宽,可能把非类名场景里的字符串误当成类名(分母偏大),因此**MISS**需要人工过一眼。 - 只覆盖 7 个固定站点目录:新增站点(
SITES未更新)不会被扫描。 - “CSS 定义”判定是纯正则:只剥
/* ... */注释后找.nf-xxx与--nf-xxx:。CSS 里以其它形式声明(如@layer里同名、或用.nf-a,逗号连写——后者仍能命中)可能带来边界误判。 - 与明文机密扫描的已知交叉:源码里
TOKEN常量(一个匹配nf-词元的正则)会被同批工具scan-secrets.py误报为“可疑机密”(实测deploy/nfos/tools3 处误报中的 1 处)。这是扫描器误报,不是泄露。
回滚¶
本工具不部署到线上、不改线上系统;不改动任何被扫描文件。
- 产出/改动位置:仅
--out指定的文件(例如.scratch/ui-js-refs.txt)。 - 清理方式:
- 不给
--out时无任何落盘物,无需清理;线上侧无需回滚。