code-frontmatter 0.2.3 → 0.2.5

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.
@@ -1,99 +0,0 @@
1
- /*---
2
- intent: "实现 cfm_search 工具:在已扫描的 CFM 索引中按关键字、角色、领域等条件搜索匹配文件"
3
- role: service
4
- exports:
5
- - "searchFrontmatter: 搜索匹配条件的 CFM 条目"
6
- depends_on: ["./read.ts", "../schema.ts"]
7
- when_to_load: "修改搜索逻辑或过滤条件时加载"
8
- ---*/
9
- import { scanDirectory } from "./read.js";
10
- /**
11
- * 在项目目录中搜索匹配条件的 CFM 表头
12
- *
13
- * 支持三种搜索维度:
14
- * - keyword: 在 intent、exports、ai_notes 等文本字段中全文搜索
15
- * - role: 精确匹配文件角色(如 "service", "component")
16
- * - domain: 精确匹配业务领域标签
17
- *
18
- * @param directory - 扫描的根目录
19
- * @param query - 搜索条件
20
- * @returns 搜索结果
21
- */
22
- export async function searchFrontmatter(directory, query) {
23
- // 获取全量扫描结果(包括解析失败的文件)
24
- const scanResult = await scanDirectory(directory, { cfmOnly: false });
25
- // 拼接查询描述
26
- const queryParts = [];
27
- if (query.keyword)
28
- queryParts.push(`keyword="${query.keyword}"`);
29
- if (query.role)
30
- queryParts.push(`role="${query.role}"`);
31
- if (query.domain)
32
- queryParts.push(`domain="${query.domain}"`);
33
- const queryDescription = queryParts.join(", ");
34
- const matchedEntries = [];
35
- const parseErrors = [];
36
- for (const entry of scanResult.entries) {
37
- // 收集解析错误(无 frontmatter 但有警告)
38
- if (!entry.frontmatter && entry.warnings && entry.warnings.length > 0) {
39
- parseErrors.push({
40
- file: entry.file,
41
- message: entry.warnings.join("; "),
42
- });
43
- continue;
44
- }
45
- // 匹配查询条件
46
- if (matchesQuery(entry, query)) {
47
- matchedEntries.push(entry);
48
- }
49
- }
50
- return {
51
- query: queryDescription,
52
- matches: matchedEntries.length,
53
- entries: matchedEntries,
54
- errors: parseErrors.length > 0 ? parseErrors : undefined,
55
- };
56
- }
57
- /**
58
- * 判断某个 CFM 条目是否匹配查询条件
59
- * 所有提供的条件都必须满足(AND 逻辑)
60
- */
61
- function matchesQuery(entry, query) {
62
- const fm = entry.frontmatter;
63
- if (!fm)
64
- return false;
65
- // 角色精确匹配
66
- if (query.role) {
67
- if (String(fm.role ?? "").toLowerCase() !== query.role.toLowerCase()) {
68
- return false;
69
- }
70
- }
71
- // 领域精确匹配
72
- if (query.domain) {
73
- if (String(fm.domain ?? "").toLowerCase() !== query.domain.toLowerCase()) {
74
- return false;
75
- }
76
- }
77
- // 关键字全文搜索
78
- if (query.keyword) {
79
- const kw = query.keyword.toLowerCase();
80
- const searchFields = [
81
- String(fm.intent ?? ""),
82
- String(fm.ai_notes ?? ""),
83
- String(fm.when_to_load ?? ""),
84
- String(fm.domain ?? ""),
85
- // 展开数组字段
86
- ...(Array.isArray(fm.exports) ? fm.exports.map(String) : []),
87
- ...(Array.isArray(fm.depends_on) ? fm.depends_on.map(String) : []),
88
- ...(Array.isArray(fm.side_effects) ? fm.side_effects.map(String) : []),
89
- // 文件路径也纳入搜索
90
- entry.file,
91
- ];
92
- const haystack = searchFields.join(" ").toLowerCase();
93
- if (!haystack.includes(kw)) {
94
- return false;
95
- }
96
- }
97
- return true;
98
- }
99
- //# sourceMappingURL=search.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"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"}
@@ -1,32 +0,0 @@
1
- /**
2
- * CFM 表头数据(写入时的输入)
3
- */
4
- export interface CfmWriteInput {
5
- intent: string;
6
- role: string;
7
- exports: string[];
8
- depends_on?: string[];
9
- when_to_load?: string;
10
- mutates_state?: boolean;
11
- side_effects?: string[];
12
- domain?: string;
13
- ai_notes?: string;
14
- }
15
- /**
16
- * 将 CFM 表头写入指定文件
17
- *
18
- * 流程:
19
- * 1. 根据扩展名查找语言注释规则
20
- * 2. 构建标准 YAML 内容
21
- * 3. 用正确的注释语法包裹
22
- * 4. 替换旧表头或插入到文件顶部
23
- *
24
- * @param filePath - 文件绝对路径
25
- * @param data - CFM 表头数据
26
- * @returns 操作结果
27
- */
28
- export declare function writeFrontmatter(filePath: string, data: CfmWriteInput): Promise<{
29
- success: boolean;
30
- message: string;
31
- }>;
32
- //# sourceMappingURL=write.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAeA;;GAEG;AACH,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,gBAAgB,CAClC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,aAAa,GACpB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAuEhD"}
@@ -1,130 +0,0 @@
1
- /*---
2
- intent: "实现 cfm_write 工具:将标准 CFM 表头写入指定代码文件,确保字段名和注释格式严格合规"
3
- role: service
4
- exports:
5
- - "writeFrontmatter: 将 CFM 表头写入指定文件"
6
- depends_on: ["../registry.ts", "../schema.ts"]
7
- when_to_load: "修改表头写入逻辑、格式生成或替换策略时加载"
8
- ai_notes: "此工具是 CFM 规范的唯一写入入口,从根源杜绝字段名不统一的问题"
9
- ---*/
10
- import { readFile, writeFile } from "node:fs/promises";
11
- import { extname } from "node:path";
12
- import { stringify as stringifyYaml } from "yaml";
13
- import { getLanguageByExtension } from "../registry.js";
14
- /**
15
- * 将 CFM 表头写入指定文件
16
- *
17
- * 流程:
18
- * 1. 根据扩展名查找语言注释规则
19
- * 2. 构建标准 YAML 内容
20
- * 3. 用正确的注释语法包裹
21
- * 4. 替换旧表头或插入到文件顶部
22
- *
23
- * @param filePath - 文件绝对路径
24
- * @param data - CFM 表头数据
25
- * @returns 操作结果
26
- */
27
- export async function writeFrontmatter(filePath, data) {
28
- const ext = extname(filePath);
29
- const lang = getLanguageByExtension(ext);
30
- if (!lang) {
31
- return {
32
- success: false,
33
- message: `不支持的文件类型 "${ext}",请先用 cfm_register_language 注册该语言。`,
34
- };
35
- }
36
- const { comment_start, comment_end, line_prefix } = lang.rule;
37
- // ── 构建 YAML 内容 ──
38
- // 按照标准字段顺序构建对象,只包含有值的字段
39
- const orderedData = {};
40
- orderedData.intent = data.intent;
41
- orderedData.role = data.role;
42
- orderedData.exports = data.exports;
43
- if (data.depends_on && data.depends_on.length > 0)
44
- orderedData.depends_on = data.depends_on;
45
- if (data.when_to_load)
46
- orderedData.when_to_load = data.when_to_load;
47
- if (data.mutates_state !== undefined)
48
- orderedData.mutates_state = data.mutates_state;
49
- if (data.side_effects && data.side_effects.length > 0)
50
- orderedData.side_effects = data.side_effects;
51
- if (data.domain)
52
- orderedData.domain = data.domain;
53
- if (data.ai_notes)
54
- orderedData.ai_notes = data.ai_notes;
55
- const yamlStr = stringifyYaml(orderedData, { lineWidth: 0 }).trim();
56
- // ── 生成注释块 ──
57
- let header;
58
- if (line_prefix) {
59
- // 脚本语言(Python, Ruby 等):每行加前缀
60
- const yamlLines = yamlStr.split("\n");
61
- const prefixedLines = yamlLines.map((line) => line ? `${line_prefix}${line}` : line_prefix.trim());
62
- header = `${comment_start}\n${prefixedLines.join("\n")}\n${comment_end}`;
63
- }
64
- else {
65
- // C 家族语言(JS, TS, Java 等):块注释
66
- header = `${comment_start}\n${yamlStr}\n${comment_end}`;
67
- }
68
- // ── 读取原文件 ──
69
- let content;
70
- try {
71
- content = await readFile(filePath, "utf-8");
72
- }
73
- catch {
74
- return {
75
- success: false,
76
- message: `无法读取文件: ${filePath}`,
77
- };
78
- }
79
- // 统一换行符
80
- const normalized = content.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
81
- // ── 检测是否已有表头,如果有则替换 ──
82
- const newContent = replaceOrInsertHeader(normalized, comment_start, comment_end, header);
83
- // ── 写入文件 ──
84
- try {
85
- await writeFile(filePath, newContent, "utf-8");
86
- }
87
- catch {
88
- return {
89
- success: false,
90
- message: `无法写入文件: ${filePath}`,
91
- };
92
- }
93
- return {
94
- success: true,
95
- message: `CFM 表头已写入 ${filePath}`,
96
- };
97
- }
98
- /**
99
- * 替换已有表头或在文件顶部插入新表头
100
- */
101
- function replaceOrInsertHeader(content, commentStart, commentEnd, newHeader) {
102
- const trimmed = content.trimStart();
103
- const leadingWhitespace = content.slice(0, content.length - trimmed.length);
104
- // 检查是否以 shebang (#!) 开头
105
- let shebangLine = "";
106
- let restContent = trimmed;
107
- if (trimmed.startsWith("#!")) {
108
- const newlineIdx = trimmed.indexOf("\n");
109
- if (newlineIdx !== -1) {
110
- shebangLine = trimmed.slice(0, newlineIdx + 1);
111
- restContent = trimmed.slice(newlineIdx + 1);
112
- }
113
- }
114
- const restTrimmed = restContent.trimStart();
115
- // 检查是否已有 CFM 表头
116
- if (restTrimmed.startsWith(commentStart)) {
117
- const afterStart = restTrimmed.slice(commentStart.length);
118
- const endIdx = afterStart.indexOf(commentEnd);
119
- if (endIdx !== -1) {
120
- // 找到旧表头,替换
121
- const afterOldHeader = afterStart.slice(endIdx + commentEnd.length);
122
- // 保留旧表头后的空行
123
- const cleaned = afterOldHeader.replace(/^\n{0,2}/, "\n");
124
- return shebangLine + newHeader + cleaned;
125
- }
126
- }
127
- // 没有旧表头,插入到文件顶部
128
- return shebangLine + newHeader + "\n\n" + restContent;
129
- }
130
- //# sourceMappingURL=write.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAAA;;;;;;;;KAQK;AAEL,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,MAAM,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAiBxD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAClC,QAAgB,EAChB,IAAmB;IAEnB,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC;IAEzC,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,OAAO;YACH,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,aAAa,GAAG,oCAAoC;SAChE,CAAC;IACN,CAAC;IAED,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;IAE9D,mBAAmB;IACnB,wBAAwB;IACxB,MAAM,WAAW,GAA4B,EAAE,CAAC;IAChD,WAAW,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACjC,WAAW,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IAC7B,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IACnC,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QAAE,WAAW,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;IAC5F,IAAI,IAAI,CAAC,YAAY;QAAE,WAAW,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;IACpE,IAAI,IAAI,CAAC,aAAa,KAAK,SAAS;QAAE,WAAW,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;IACrF,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;QAAE,WAAW,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;IACpG,IAAI,IAAI,CAAC,MAAM;QAAE,WAAW,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAClD,IAAI,IAAI,CAAC,QAAQ;QAAE,WAAW,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAExD,MAAM,OAAO,GAAG,aAAa,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAEpE,cAAc;IACd,IAAI,MAAc,CAAC;IACnB,IAAI,WAAW,EAAE,CAAC;QACd,6BAA6B;QAC7B,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,aAAa,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,WAAW,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;QACnG,MAAM,GAAG,GAAG,aAAa,KAAK,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,WAAW,EAAE,CAAC;IAC7E,CAAC;SAAM,CAAC;QACJ,6BAA6B;QAC7B,MAAM,GAAG,GAAG,aAAa,KAAK,OAAO,KAAK,WAAW,EAAE,CAAC;IAC5D,CAAC;IAED,cAAc;IACd,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACD,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACL,OAAO;YACH,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,WAAW,QAAQ,EAAE;SACjC,CAAC;IACN,CAAC;IAED,QAAQ;IACR,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAEvE,wBAAwB;IACxB,MAAM,UAAU,GAAG,qBAAqB,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;IAEzF,aAAa;IACb,IAAI,CAAC;QACD,MAAM,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACL,OAAO;YACH,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,WAAW,QAAQ,EAAE;SACjC,CAAC;IACN,CAAC;IAED,OAAO;QACH,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,aAAa,QAAQ,EAAE;KACnC,CAAC;AACN,CAAC;AAED;;GAEG;AACH,SAAS,qBAAqB,CAC1B,OAAe,EACf,YAAoB,EACpB,UAAkB,EAClB,SAAiB;IAEjB,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IACpC,MAAM,iBAAiB,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE5E,wBAAwB;IACxB,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,WAAW,GAAG,OAAO,CAAC;IAE1B,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;YACpB,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC;YAC/C,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;QAChD,CAAC;IACL,CAAC;IAED,MAAM,WAAW,GAAG,WAAW,CAAC,SAAS,EAAE,CAAC;IAE5C,gBAAgB;IAChB,IAAI,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACvC,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAE9C,IAAI,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;YAChB,WAAW;YACX,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;YACpE,YAAY;YACZ,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;YACzD,OAAO,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;QAC7C,CAAC;IACL,CAAC;IAED,gBAAgB;IAChB,OAAO,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,WAAW,CAAC;AAC1D,CAAC"}