repo-audit-tool 1.4.0 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/AGENT-INDEX.json +124 -40
- package/docs/repo-audit/AGENT-GUIDE.md +4 -0
- package/docs/repo-audit/HUMAN-GUIDE.md +9 -0
- package/package.json +1 -1
- package/repo-audit.mjs +46 -22
package/docs/AGENT-INDEX.json
CHANGED
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"title": "repo-audit 文档索引",
|
|
4
4
|
"description": "AI Agent 可读的文档索引 — 包含所有文档的元数据、结构、和调用协议",
|
|
5
|
-
"version": "1.4.
|
|
6
|
-
"updated": "2026-09-
|
|
5
|
+
"version": "1.4.1",
|
|
6
|
+
"updated": "2026-09-09",
|
|
7
7
|
"repo": "NinjaSln-labs/repo-audit",
|
|
8
8
|
"npm": "repo-audit-tool",
|
|
9
9
|
"pages": "https://ninjasln-labs.github.io/repo-audit/",
|
|
10
|
-
|
|
11
10
|
"entry_points": {
|
|
12
11
|
"json_index": "/AGENT-INDEX.json",
|
|
13
12
|
"schema": "/SCHEMA.json",
|
|
@@ -15,33 +14,72 @@
|
|
|
15
14
|
"human_guide": "/repo-audit/HUMAN-GUIDE.md",
|
|
16
15
|
"agent_guide": "/repo-audit/AGENT-GUIDE.md"
|
|
17
16
|
},
|
|
18
|
-
|
|
19
17
|
"tool": {
|
|
20
18
|
"name": "repo-audit",
|
|
21
19
|
"description": "仓库标准化审计工具 + 工程脚手架生成器(零依赖)",
|
|
22
20
|
"bin": "repo-audit",
|
|
23
|
-
"version": "1.4.
|
|
21
|
+
"version": "1.4.1",
|
|
24
22
|
"language": "JavaScript (ESM)",
|
|
25
23
|
"runtime": "Node.js >= 18",
|
|
26
24
|
"dependencies": [],
|
|
27
25
|
"license": "MIT",
|
|
28
|
-
|
|
29
26
|
"invocation": {
|
|
30
27
|
"command": "repo-audit [options]",
|
|
31
28
|
"options": {
|
|
32
|
-
"--repo": {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"--
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"--
|
|
42
|
-
|
|
29
|
+
"--repo": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"default": ".",
|
|
32
|
+
"description": "目标仓库路径"
|
|
33
|
+
},
|
|
34
|
+
"--type": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"description": "强制指定分类(跳过自动检测)"
|
|
37
|
+
},
|
|
38
|
+
"--format": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"enum": [
|
|
41
|
+
"md",
|
|
42
|
+
"json",
|
|
43
|
+
"both"
|
|
44
|
+
],
|
|
45
|
+
"default": "both",
|
|
46
|
+
"description": "输出格式"
|
|
47
|
+
},
|
|
48
|
+
"--output": {
|
|
49
|
+
"type": "string",
|
|
50
|
+
"default": "<repo>/audit-report/",
|
|
51
|
+
"description": "输出目录"
|
|
52
|
+
},
|
|
53
|
+
"--llm-provider": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"description": "LLM 协议:openai/anthropic 或厂商别名"
|
|
56
|
+
},
|
|
57
|
+
"--llm-model": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"description": "模型名称"
|
|
60
|
+
},
|
|
61
|
+
"--strict": {
|
|
62
|
+
"type": "boolean",
|
|
63
|
+
"default": false,
|
|
64
|
+
"description": "严格模式:Critical/Major 即 exit 1"
|
|
65
|
+
},
|
|
66
|
+
"--rules": {
|
|
67
|
+
"type": "string",
|
|
68
|
+
"description": "自定义规则 YAML(可多次)"
|
|
69
|
+
},
|
|
70
|
+
"--dim": {
|
|
71
|
+
"type": "string",
|
|
72
|
+
"description": "只审计指定维度(可多次)"
|
|
73
|
+
},
|
|
74
|
+
"--feedback": {
|
|
75
|
+
"type": "string",
|
|
76
|
+
"description": "提交反馈(创建 GitHub Issue)"
|
|
77
|
+
},
|
|
78
|
+
"--help": {
|
|
79
|
+
"type": "boolean",
|
|
80
|
+
"description": "显示帮助"
|
|
81
|
+
}
|
|
43
82
|
},
|
|
44
|
-
|
|
45
83
|
"exit_codes": {
|
|
46
84
|
"0": "审计通过(无 Critical/Major 或 --strict 未启用)",
|
|
47
85
|
"1": "有 Critical/Major 发现且 --strict 启用",
|
|
@@ -49,7 +87,6 @@
|
|
|
49
87
|
"3": "目标不是 git 仓库"
|
|
50
88
|
}
|
|
51
89
|
},
|
|
52
|
-
|
|
53
90
|
"environment_variables": {
|
|
54
91
|
"LLM_PROVIDER": "LLM 协议(openai/anthropic/none),也可用厂商别名如 deepseek/qwen/glm",
|
|
55
92
|
"LLM_API_KEY": "API Key(必须手动指定)",
|
|
@@ -58,35 +95,58 @@
|
|
|
58
95
|
"REPO_AUDIT_TYPES": "自定义分类列表(JSON 数组)"
|
|
59
96
|
}
|
|
60
97
|
},
|
|
61
|
-
|
|
62
98
|
"audit": {
|
|
63
99
|
"dimensions": [
|
|
64
100
|
{
|
|
65
101
|
"id": "docs",
|
|
66
102
|
"label": "文档",
|
|
67
|
-
"rules": [
|
|
103
|
+
"rules": [
|
|
104
|
+
"DOC-001",
|
|
105
|
+
"DOC-002",
|
|
106
|
+
"DOC-003",
|
|
107
|
+
"DOC-003b",
|
|
108
|
+
"DOC-004",
|
|
109
|
+
"DOC-005",
|
|
110
|
+
"DOC-006",
|
|
111
|
+
"DOC-007"
|
|
112
|
+
],
|
|
68
113
|
"description": "README/LICENSE/CONTRIBUTING/SECURITY 等文档完整性"
|
|
69
114
|
},
|
|
70
115
|
{
|
|
71
116
|
"id": "git",
|
|
72
117
|
"label": "Git",
|
|
73
|
-
"rules": [
|
|
118
|
+
"rules": [
|
|
119
|
+
"GIT-001",
|
|
120
|
+
"GIT-002",
|
|
121
|
+
"GIT-003",
|
|
122
|
+
"GIT-004"
|
|
123
|
+
],
|
|
74
124
|
"description": "commit 规范、分支策略、scaffold 管理"
|
|
75
125
|
},
|
|
76
126
|
{
|
|
77
127
|
"id": "quality",
|
|
78
128
|
"label": "质量",
|
|
79
|
-
"rules": [
|
|
129
|
+
"rules": [
|
|
130
|
+
"QUA-001",
|
|
131
|
+
"QUA-002",
|
|
132
|
+
"QUA-003",
|
|
133
|
+
"QUA-004",
|
|
134
|
+
"QUA-005"
|
|
135
|
+
],
|
|
80
136
|
"description": "构建配置、测试、lint、typecheck"
|
|
81
137
|
},
|
|
82
138
|
{
|
|
83
139
|
"id": "security",
|
|
84
140
|
"label": "安全",
|
|
85
|
-
"rules": [
|
|
141
|
+
"rules": [
|
|
142
|
+
"SEC-001",
|
|
143
|
+
"SEC-002",
|
|
144
|
+
"SEC-003",
|
|
145
|
+
"SEC-004"
|
|
146
|
+
],
|
|
86
147
|
"description": "密钥泄露、依赖漏洞、权限配置"
|
|
87
148
|
}
|
|
88
149
|
],
|
|
89
|
-
|
|
90
150
|
"scoring": {
|
|
91
151
|
"formula": "score = 100 - (critical × 25) - (major × 10) - (minor × 3)",
|
|
92
152
|
"grades": {
|
|
@@ -98,14 +158,26 @@
|
|
|
98
158
|
},
|
|
99
159
|
"note": "score 和 grade 不在 JSON 输出中,Agent 需根据 summary 字段自行计算"
|
|
100
160
|
},
|
|
101
|
-
|
|
102
161
|
"categories": [
|
|
103
|
-
"dsh-plugin",
|
|
104
|
-
"
|
|
105
|
-
"
|
|
162
|
+
"dsh-plugin",
|
|
163
|
+
"python-app",
|
|
164
|
+
"go-service",
|
|
165
|
+
"content",
|
|
166
|
+
"sandbox",
|
|
167
|
+
"archive",
|
|
168
|
+
"product-oss",
|
|
169
|
+
"javascript",
|
|
170
|
+
"typescript",
|
|
171
|
+
"java",
|
|
172
|
+
"python",
|
|
173
|
+
"rust",
|
|
174
|
+
"cpp",
|
|
175
|
+
"dotnet",
|
|
176
|
+
"php",
|
|
177
|
+
"ruby",
|
|
178
|
+
"unknown"
|
|
106
179
|
]
|
|
107
180
|
},
|
|
108
|
-
|
|
109
181
|
"documents": [
|
|
110
182
|
{
|
|
111
183
|
"id": "human-guide",
|
|
@@ -189,12 +261,10 @@
|
|
|
189
261
|
"description": "JSON Schema 定义,用于验证审计报告输出"
|
|
190
262
|
}
|
|
191
263
|
],
|
|
192
|
-
|
|
193
264
|
"feedback": {
|
|
194
265
|
"description": "反馈通道 — Agent 可通过 GitHub Issues API 检测和处理用户反馈",
|
|
195
266
|
"label": "audit-feedback",
|
|
196
267
|
"repo": "NinjaSln-labs/repo-audit",
|
|
197
|
-
|
|
198
268
|
"detect": {
|
|
199
269
|
"command": "gh issue list --repo NinjaSln-labs/repo-audit --label audit-feedback --state open --json number,title,createdAt,body",
|
|
200
270
|
"description": "列出未处理的反馈"
|
|
@@ -211,15 +281,29 @@
|
|
|
211
281
|
"command": "node repo-audit.mjs --feedback '<反馈内容>'",
|
|
212
282
|
"description": "通过 CLI 创建反馈 Issue(自动预填环境信息)"
|
|
213
283
|
},
|
|
214
|
-
|
|
215
284
|
"priorities": [
|
|
216
|
-
{
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
285
|
+
{
|
|
286
|
+
"level": "critical",
|
|
287
|
+
"sla": "24h",
|
|
288
|
+
"description": "工具崩溃/数据损坏"
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
"level": "major",
|
|
292
|
+
"sla": "72h",
|
|
293
|
+
"description": "功能严重受损"
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
"level": "minor",
|
|
297
|
+
"sla": "1周",
|
|
298
|
+
"description": "功能部分受损"
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
"level": "info",
|
|
302
|
+
"sla": "排期",
|
|
303
|
+
"description": "建议改进"
|
|
304
|
+
}
|
|
220
305
|
]
|
|
221
306
|
},
|
|
222
|
-
|
|
223
307
|
"quick_start": {
|
|
224
308
|
"install": "npm install -g repo-audit-tool",
|
|
225
309
|
"audit": "repo-audit --repo /path/to/repo",
|
|
@@ -229,7 +313,6 @@
|
|
|
229
313
|
"custom_rules": "repo-audit --repo /path/to/repo --rules my-rules.yaml",
|
|
230
314
|
"llm_enhanced": "LLM_API_KEY=sk-xxx repo-audit --repo . --llm-provider deepseek"
|
|
231
315
|
},
|
|
232
|
-
|
|
233
316
|
"changelog": {
|
|
234
317
|
"1.4.0": "json_field workspace 递归——monorepo 场景下递归检查所有 workspace 包的 license 字段;findWorkspacePackages 发现 npm/pnpm workspaces + 常见目录;checkJsonFieldContent 提取为可复用函数;DOC-003b 启用;15 用例回归",
|
|
235
318
|
"1.3.3": "Issue#5 修复:.auditrc.yaml since 字段 YAML 引号剥离——loadAuditrc 中 since: 分支补 .replace(/['\"]/g, ''),与 reason 分支对称,修复 waived_since 输出含字面引号的 bug;5 用例回归(test/auditrc-since.test.mjs)",
|
|
@@ -239,6 +322,7 @@
|
|
|
239
322
|
"1.2.3": "package.json 补充 repository 字段,修复 npm provenance E422;完成 Trusted Publisher tag 自动发布",
|
|
240
323
|
"1.2.2": "publish CI 改用 node 22 + 条件升级 npm,修复 EBADENGINE(tag 发布因 1.2.1 已存在未出包)",
|
|
241
324
|
"1.2.1": "README 链接改为绝对 URL(修复 npm 页面 404)",
|
|
242
|
-
"1.2.0": "开源就绪:AGENTS.md、CI/publish workflow、json_field monorepo、fallback_field 数组、英文 README、参数类型校验、占位符扫描"
|
|
325
|
+
"1.2.0": "开源就绪:AGENTS.md、CI/publish workflow、json_field monorepo、fallback_field 数组、英文 README、参数类型校验、占位符扫描",
|
|
326
|
+
"1.4.1": "yaml_field 解析健壮性——CRLF 行尾剥离 + 引号键名识别 + 子层缩进以首个子键为准(SEC-004 job 级 id-token 误判 fail,Issue#6);6 用例回归"
|
|
243
327
|
}
|
|
244
328
|
}
|
|
@@ -275,6 +275,10 @@ EOF
|
|
|
275
275
|
node repo-audit.mjs --repo /path/to/repo --rules /tmp/my-rules.yaml --format json
|
|
276
276
|
```
|
|
277
277
|
|
|
278
|
+
### 4.7 yaml_field fallback_field 与解析健壮性(Issue#6)
|
|
279
|
+
|
|
280
|
+
`yaml_field` 支持 `fallback_field`(数组):主字段不匹配时逐个尝试备选路径,段内 `*` 为通配展开(如 `jobs.*.permissions.id-token`——任一 job 级命中即 pass,覆盖 PyPA 最小化权限模式)。解析层(v1.4.1)统一剥离 CRLF 行尾 `\r`、识别引号键名、按首个子键实际缩进确定子层(2/4 空格风格均支持)。误判排查时优先确认 workflow 文件是否踩过这三类形态。
|
|
281
|
+
|
|
278
282
|
---
|
|
279
283
|
|
|
280
284
|
## 五、错误处理协议
|
|
@@ -688,6 +688,15 @@ params:
|
|
|
688
688
|
fallback_field: "scripts.test"
|
|
689
689
|
```
|
|
690
690
|
|
|
691
|
+
### 12.4b yaml_field fallback_field 与解析健壮性(Issue#6)
|
|
692
|
+
|
|
693
|
+
`yaml_field` 支持 `fallback_field`(数组):主字段不匹配时逐个尝试备选路径,段内 `*` 为通配(如 `jobs.*.permissions.id-token`——顶层无 `permissions.id-token` 时,任一 job 级命中即 pass,覆盖 PyPA 最小化权限模式)。
|
|
694
|
+
|
|
695
|
+
解析健壮性(v1.4.1 修复,Issue#6):
|
|
696
|
+
- **CRLF 行尾**:行解析前统一剥离 `\r`,Windows 编辑的 workflow 不再标量失配
|
|
697
|
+
- **引号键名**:`"publish":` / `'publish':` 与裸键等价识别
|
|
698
|
+
- **缩进风格**:子层缩进以首个子键实际缩进为准(2/4 空格等风格均支持,不再硬编码 +2)
|
|
699
|
+
|
|
691
700
|
### 12.5 toml_field expect_table
|
|
692
701
|
|
|
693
702
|
检查 TOML 表头存在性(而非表内键值):
|
package/package.json
CHANGED
package/repo-audit.mjs
CHANGED
|
@@ -325,30 +325,49 @@ function countNonHiddenFiles(path) {
|
|
|
325
325
|
return count
|
|
326
326
|
}
|
|
327
327
|
|
|
328
|
-
// Issue#
|
|
328
|
+
// Issue#6 fix: 规范化 YAML 行——剥离行尾 \r(CRLF 文件在 Linux 审计时 (.*)$ 不吞 \r,
|
|
329
|
+
// 标量值带尾 \r 导致与 expected 比较全部失配);行内键名引号在匹配处单独处理
|
|
330
|
+
function normalizeYamlLines(content) {
|
|
331
|
+
return String(content).split('\n').map(l => l.replace(/\r$/, ''))
|
|
332
|
+
}
|
|
333
|
+
// Issue#6 fix: YAML 键名匹配——兼容裸键与引号键("publish": / 'publish':),
|
|
334
|
+
// 返回 [key, valueRest];非键行返回 null
|
|
335
|
+
function matchYamlKey(l) {
|
|
336
|
+
const m = l.match(/^(\s*)(?:"([^"]+)"|'([^']+)'|(\w[\w\-]*))\s*:\s*(.*)$/)
|
|
337
|
+
if (!m) return null
|
|
338
|
+
return [m[2] ?? m[3] ?? m[4], m[5]]
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Issue#6 fix: 定位指定缩进层级下的具名子键(返回行号与缩进;未找到返回 null)
|
|
342
|
+
// 子层缩进以本层首个子键的实际缩进为准(兼容 2/4 空格等缩进风格),不再硬编码 +2
|
|
329
343
|
function findNestedYamlKey(lines, startIdx, baseIndent, key) {
|
|
344
|
+
let childIndent = -1
|
|
330
345
|
for (let i = startIdx + 1; i < lines.length; i++) {
|
|
331
346
|
const l = lines[i]
|
|
332
347
|
if (!l.trim() || l.trim().startsWith('#')) continue
|
|
333
348
|
const ind = l.length - l.trimStart().length
|
|
334
349
|
if (ind <= baseIndent) return null
|
|
335
|
-
if (
|
|
336
|
-
|
|
337
|
-
|
|
350
|
+
if (childIndent === -1) childIndent = ind // 本层首个子键确定子层缩进
|
|
351
|
+
if (ind !== childIndent) continue // 只看直接子层
|
|
352
|
+
const km = matchYamlKey(l)
|
|
353
|
+
if (km && km[0] === key) return { idx: i, indent: ind }
|
|
338
354
|
}
|
|
339
355
|
return null
|
|
340
356
|
}
|
|
341
357
|
// Issue#2 fix: 列出指定父键下一层的所有子键名(通配 * 展开用)
|
|
358
|
+
// 子层缩进同样以首个子键实际缩进为准(与 findNestedYamlKey 对称)
|
|
342
359
|
function listChildKeys(lines, startIdx, baseIndent) {
|
|
343
360
|
const keys = []
|
|
361
|
+
let childIndent = -1
|
|
344
362
|
for (let i = startIdx + 1; i < lines.length; i++) {
|
|
345
363
|
const l = lines[i]
|
|
346
364
|
if (!l.trim() || l.trim().startsWith('#')) continue
|
|
347
365
|
const ind = l.length - l.trimStart().length
|
|
348
366
|
if (ind <= baseIndent) break
|
|
349
|
-
if (
|
|
350
|
-
|
|
351
|
-
|
|
367
|
+
if (childIndent === -1) childIndent = ind
|
|
368
|
+
if (ind !== childIndent) continue
|
|
369
|
+
const km = matchYamlKey(l)
|
|
370
|
+
if (km) keys.push(km[0])
|
|
352
371
|
}
|
|
353
372
|
return keys
|
|
354
373
|
}
|
|
@@ -374,10 +393,10 @@ function findNestedYaml(lines, startIdx, baseIndent, segments) {
|
|
|
374
393
|
if (!l.trim() || l.trim().startsWith('#')) continue
|
|
375
394
|
const ind = l.length - l.trimStart().length
|
|
376
395
|
if (ind <= currentIndent) break // 退出当前层级
|
|
377
|
-
const
|
|
378
|
-
if (
|
|
379
|
-
const key =
|
|
380
|
-
const valStr = stripYamlComment(
|
|
396
|
+
const km = matchYamlKey(l)
|
|
397
|
+
if (km) {
|
|
398
|
+
const key = km[0]
|
|
399
|
+
const valStr = stripYamlComment(km[1])
|
|
381
400
|
const seg = segments[0]
|
|
382
401
|
if (key === seg) {
|
|
383
402
|
if (valStr && valStr !== '' && valStr !== '{}') {
|
|
@@ -902,6 +921,11 @@ function hasEquivalentDocs(repoPath) {
|
|
|
902
921
|
// 规则检查引擎
|
|
903
922
|
// ============================================================
|
|
904
923
|
|
|
924
|
+
// Issue#6 回归需要进程内直调(win32 下 spawnSync node 走 PATHEXT 解析不可靠,P-007 同族坑)
|
|
925
|
+
export function runCheckForTest(rule, repoPath, mpj = null) {
|
|
926
|
+
return runCheck(rule, repoPath, mpj)
|
|
927
|
+
}
|
|
928
|
+
|
|
905
929
|
function runCheck(rule, repoPath, mpj = null) {
|
|
906
930
|
const { check, params } = rule
|
|
907
931
|
let passed = false
|
|
@@ -1187,7 +1211,7 @@ function runCheck(rule, repoPath, mpj = null) {
|
|
|
1187
1211
|
let val = null
|
|
1188
1212
|
let found = false
|
|
1189
1213
|
try {
|
|
1190
|
-
const lines = content
|
|
1214
|
+
const lines = normalizeYamlLines(content)
|
|
1191
1215
|
let currentIndent = -1
|
|
1192
1216
|
let currentObj = null
|
|
1193
1217
|
// 第一遍:找到顶层键
|
|
@@ -1195,10 +1219,10 @@ function runCheck(rule, repoPath, mpj = null) {
|
|
|
1195
1219
|
const l = lines[i]
|
|
1196
1220
|
if (!l.trim() || l.trim().startsWith('#')) continue
|
|
1197
1221
|
const ind = l.length - l.trimStart().length
|
|
1198
|
-
const
|
|
1199
|
-
if (
|
|
1222
|
+
const km = matchYamlKey(l)
|
|
1223
|
+
if (km && km[0] === segments[0]) {
|
|
1200
1224
|
currentIndent = ind
|
|
1201
|
-
const valStr = stripYamlComment(
|
|
1225
|
+
const valStr = stripYamlComment(km[1])
|
|
1202
1226
|
if (valStr && valStr !== '' && valStr !== '{}') {
|
|
1203
1227
|
// 标量值(非嵌套)
|
|
1204
1228
|
val = valStr
|
|
@@ -1233,7 +1257,7 @@ function runCheck(rule, repoPath, mpj = null) {
|
|
|
1233
1257
|
const wIdx = segs.indexOf('*')
|
|
1234
1258
|
if (wIdx === -1) { candidates.push({ segments: segs }); return }
|
|
1235
1259
|
// 找通配段父级的所有子键:先定位父级前缀(逐段下钻收集行号)
|
|
1236
|
-
const lines = content
|
|
1260
|
+
const lines = normalizeYamlLines(content)
|
|
1237
1261
|
const prefix = segs.slice(0, wIdx)
|
|
1238
1262
|
const suffix = segs.slice(wIdx + 1)
|
|
1239
1263
|
// 顶层段
|
|
@@ -1241,8 +1265,8 @@ function runCheck(rule, repoPath, mpj = null) {
|
|
|
1241
1265
|
for (let i = 0; i < lines.length; i++) {
|
|
1242
1266
|
const l = lines[i]
|
|
1243
1267
|
if (!l.trim() || l.trim().startsWith('#')) continue
|
|
1244
|
-
const
|
|
1245
|
-
if (!
|
|
1268
|
+
const km = matchYamlKey(l)
|
|
1269
|
+
if (!km || km[0] !== prefix[0]) continue
|
|
1246
1270
|
// 沿 prefix 下钻
|
|
1247
1271
|
let curIdx = i, curIndent = l.length - l.trimStart().length
|
|
1248
1272
|
let ok = true
|
|
@@ -1263,14 +1287,14 @@ function runCheck(rule, repoPath, mpj = null) {
|
|
|
1263
1287
|
let fbVal = null
|
|
1264
1288
|
let fbFound = false
|
|
1265
1289
|
try {
|
|
1266
|
-
const lines = content
|
|
1290
|
+
const lines = normalizeYamlLines(content)
|
|
1267
1291
|
for (let i = 0; i < lines.length; i++) {
|
|
1268
1292
|
const l = lines[i]
|
|
1269
1293
|
if (!l.trim() || l.trim().startsWith('#')) continue
|
|
1270
1294
|
const ind = l.length - l.trimStart().length
|
|
1271
|
-
const
|
|
1272
|
-
if (
|
|
1273
|
-
const v = stripYamlComment(
|
|
1295
|
+
const km = matchYamlKey(l)
|
|
1296
|
+
if (km && km[0] === cand.segments[0]) {
|
|
1297
|
+
const v = stripYamlComment(km[1])
|
|
1274
1298
|
if (v && v !== '' && v !== '{}') { fbVal = v; fbFound = true }
|
|
1275
1299
|
else {
|
|
1276
1300
|
const sub = findNestedYaml(lines, i, ind, cand.segments.slice(1))
|