SonarQube 默认不检查 img 缺失 alt 属性,因其 HTML 插件仅做基础结构校验,可访问性规则被视为上下文强相关的自定义业务规则,需手动启用 XPath 规则 //img[not(@alt) or @alt = '']。

为什么 SonarQube 默认不检查 img 标签缺失 alt 属性
SonarQube 的 HTML 插件(sonar-html-plugin)默认只做基础结构校验,比如标签闭合、嵌套合法性,而语义可访问性规则(如 alt 必填)不在开箱即用范围内——它被归类为“自定义业务规则”,需手动启用或编写。
根本原因在于:SonarQube 将可访问性(a11y)视为上下文强相关的质量维度。例如内部管理后台可能允许图标用 alt="",而对外官网必须非空;默认规则无法安全假设你的业务意图。
- 检查
img是否有alt属性,属于 XPath 规则范畴,不是 JS/TS 那类 AST 分析 - HTML 插件底层依赖
jsoup解析,规则需以 XPath 1.0 表达式定义,不支持 CSS 选择器或正则 - 若直接在 UI 中添加 XPath 规则但未勾选“Apply to HTML files”,规则会静默失效
如何用 XPath 编写一条强制 img 含非空 alt 的规则
登录 SonarQube 管理后台 → Quality Profiles → 选中目标 HTML 配置集 → Activate more rules → 搜索 “XPath” → 选择 “XPath rule” 并激活。
关键不是写对 XPath,而是写对“能被 jsoup 正确评估”的 XPath——它不支持 normalize-space() 或 string-length() 函数,只能靠属性存在性 + 字符串字面匹配。
立即学习“前端免费学习笔记(深入)”;
- ✅ 正确表达式:
//img[not(@alt) or @alt = ''](捕获无alt或值为空字符串的img) - ❌ 错误写法:
//img[not(@alt) or normalize-space(@alt) = ''](normalize-space在 jsoup 中不可用) - ⚠️ 注意:该规则会命中
<img alt="">,但不会命中<img alt=" ">(含空格),后者需额外规则或前端 lint 工具补位 - 规则参数中,“XPath expression” 填上述表达式,“Message” 建议写明修复方式,例如:“Add non-empty
altattribute for accessibility”
自定义规则上线后为什么没扫描出已知问题
常见原因不是规则写错,而是文件未被纳入 HTML 语言分析范围——SonarQube 默认只把 .html 和 .htm 当作 HTML 文件,而你项目里可能是 .vue、.erb、.njk 或内联 <template> 片段。
- 检查
sonar.language或sonar.sources配置,确认 HTML 插件实际生效的文件后缀列表 - 若要扫描
.vue中的 HTML 片段,必须启用sonar.html.file.suffixes并追加.vue(SonarQube ≥ 9.9 支持) - 运行扫描时加
-X参数看 debug 日志,搜索HtmlVisitor或jsoup parsed关键字,确认目标文件是否被解析 - 规则仅作用于静态 HTML 文本,对 JS 动态插入的
img(如document.createElement('img'))完全无感知
要不要把自定义 XPath 规则写进 sonar-project.properties
不要。SonarQube 的 XPath 规则必须在 Web UI 或通过 Web API 注册到 Quality Profile 中,sonar-project.properties 不支持声明式定义 HTML XPath 规则。
你能在配置文件里控制的,只有“是否启用某条已存在的规则”(用 sonar.rules.custom?不存在这个参数),或调整文件识别范围(如 sonar.html.file.suffixes)。
- 自动化部署规则的唯一可靠方式是调用 SonarQube REST API:
api/rules/create+api/qualityprofiles/activate_rule - 若团队多人维护,建议将 XPath 表达式和 Message 写入内部 Wiki,并截图保存 Quality Profile 的导出 JSON(
api/qualityprofiles/export),避免 UI 误操作丢失 - 注意:不同 SonarQube 版本对 XPath 函数支持有差异,7.9 和 9.9 的 jsoup 版本不同,同一表达式在旧版可能报
XPath evaluation error
真正难的从来不是写出那行 XPath,而是确认它跑在正确的文件上、被正确的插件加载、且团队知道它为什么对某些 case 失效。



















