reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
82
vendor-new/rev-skills/tests/frontmatter.test.mjs
Normal file
82
vendor-new/rev-skills/tests/frontmatter.test.mjs
Normal file
@@ -0,0 +1,82 @@
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readdirSync, readFileSync } from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { join, dirname } from 'node:path';
|
||||
import { parseFrontmatterFields, splitFrontmatter } from '../lib/frontmatter.mjs';
|
||||
import { parseFrontmatter } from '../validate.mjs';
|
||||
import { readSkill } from '../bin/convert.mjs';
|
||||
|
||||
const SKILLS = join(dirname(fileURLToPath(import.meta.url)), '..', '.claude', 'skills');
|
||||
|
||||
test('折叠块标量 > 合并为单行', () => {
|
||||
const md = '---\nname: re-x\ndescription: >\n 第一行\n 第二行\n---\n\n# 体';
|
||||
assert.equal(parseFrontmatter(md).description, '第一行 第二行');
|
||||
});
|
||||
|
||||
test('字面块标量 | 保留换行', () => {
|
||||
const md = '---\nname: re-x\ndescription: |\n 第一行\n 第二行\n---\n\n# 体';
|
||||
assert.equal(parseFrontmatter(md).description, '第一行\n第二行');
|
||||
});
|
||||
|
||||
test('空块标量按缺描述报错(校验不再是空转)', () => {
|
||||
assert.throws(() => parseFrontmatter('---\nname: re-x\ndescription: >\n---\n\n# 体'), /description/);
|
||||
});
|
||||
|
||||
test('块标量吸收缩进行,不吞并下一个同级键', () => {
|
||||
const fm = parseFrontmatterFields('description: >\n 正文\n body\ncapabilities: [a, b]');
|
||||
assert.equal(fm.description, '正文 body');
|
||||
assert.equal(fm.capabilities, '[a, b]');
|
||||
});
|
||||
|
||||
test('顶格游离行报错,不静默丢弃(块标量误写列表项回归)', () => {
|
||||
// 行号以 frontmatter 块内 1-based 计(对应 SKILL.md 文件行号 +1,块首为文件第 2 行)
|
||||
const md = '---\nname: re-x\ndescription: >\n 正文\n- 游离行\n 触发词:x\n---\n\n# 体';
|
||||
assert.throws(() => parseFrontmatter(md), /unparsable frontmatter line 4.*游离行/);
|
||||
});
|
||||
|
||||
test('re-mobile description 覆盖块标量全部续行(截断回归)', () => {
|
||||
const md = readFileSync(join(SKILLS, 're-mobile', 'SKILL.md'), 'utf8');
|
||||
assert.match(parseFrontmatter(md).description, /加密体系审计/);
|
||||
});
|
||||
|
||||
test('splitFrontmatter 缺 frontmatter 报错并保留正文', () => {
|
||||
assert.throws(() => splitFrontmatter('# 无 frontmatter'), /frontmatter/);
|
||||
assert.equal(splitFrontmatter('---\na: b\n---\n\n正文').body, '正文');
|
||||
});
|
||||
|
||||
test('validate 与 convert 对全部技能解析一致(防解析器漂移回归)', () => {
|
||||
const dirs = readdirSync(SKILLS).filter(d => d.startsWith('re-'));
|
||||
assert.ok(dirs.length >= 46, '技能目录数异常');
|
||||
for (const name of dirs) {
|
||||
const dir = join(SKILLS, name);
|
||||
const md = readFileSync(join(dir, 'SKILL.md'), 'utf8');
|
||||
const v = parseFrontmatter(md);
|
||||
const c = readSkill(dir);
|
||||
assert.equal(v.name, c.name, `${name}: name 不一致`);
|
||||
assert.equal(v.description, c.description, `${name}: description 不一致`);
|
||||
assert.equal(v.body, c.body, `${name}: body 不一致`);
|
||||
assert.ok(v.description.trim().length > 0, `${name}: description 解析为空`);
|
||||
}
|
||||
});
|
||||
|
||||
test('frontmatter 键接受连字符(DSH 的 disable-model-invocation / user-invocable)', () => {
|
||||
// 键文法若只认 \w+,这两个 DSH 合法键会被当成顶格游离行而整份技能报错。
|
||||
const fm = parseFrontmatterFields('name: re-x\ndescription: d\ndisable-model-invocation: false\nuser-invocable: true');
|
||||
assert.equal(fm.name, 're-x');
|
||||
assert.equal(fm['disable-model-invocation'], 'false');
|
||||
assert.equal(fm['user-invocable'], 'true');
|
||||
});
|
||||
|
||||
test('CRLF 检出解析结果与 LF 一致(Windows 行尾回归)', () => {
|
||||
// Windows 上 core.autocrlf=true 的检出会把提交时的 LF 变成 CRLF;
|
||||
// 若不归一,分界正则不匹配 → 整库报 missing frontmatter,能力注册表也解析失败。
|
||||
const lf = '---\nname: re-x\ndescription: >\n 第一行\n 第二行\ncapabilities: [a, b]\n---\n\n# 体';
|
||||
const crlf = lf.replace(/\n/g, '\r\n');
|
||||
assert.equal(parseFrontmatter(crlf).description, parseFrontmatter(lf).description);
|
||||
assert.equal(parseFrontmatter(crlf).body, parseFrontmatter(lf).body);
|
||||
assert.deepEqual(parseFrontmatterFields(splitFrontmatter(crlf).raw), parseFrontmatterFields(splitFrontmatter(lf).raw));
|
||||
assert.equal(splitFrontmatter(crlf).body, '# 体');
|
||||
// 单个 CR 行尾(旧 Mac 风格)同样归一
|
||||
assert.equal(parseFrontmatter(lf.replace(/\n/g, '\r')).name, 're-x');
|
||||
});
|
||||
Reference in New Issue
Block a user