跳转至

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

期望输出形态:

written: .scratch/ui-js-refs.txt (34567 bytes)

正文形如:

== 前端 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/tools 3 处误报中的 1 处)。这是扫描器误报,不是泄露。

回滚

本工具不部署到线上、不改线上系统;不改动任何被扫描文件。

  • 产出/改动位置:仅 --out 指定的文件(例如 .scratch/ui-js-refs.txt)。
  • 清理方式:
Remove-Item -Force .scratch/ui-js-refs.txt
  • 不给 --out 时无任何落盘物,无需清理;线上侧无需回滚。