larkcc 0.1.7 → 0.1.8
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/CHANGELOG.md +43 -1
- package/README.md +114 -0
- package/dist/app.js +41 -3
- package/dist/app.js.map +1 -1
- package/dist/commands/default-prompts.yml +62 -0
- package/dist/commands.d.ts +21 -3
- package/dist/commands.js +124 -38
- package/dist/commands.js.map +1 -1
- package/dist/config.d.ts +9 -0
- package/dist/config.js +23 -0
- package/dist/config.js.map +1 -1
- package/dist/feishu.js +17 -203
- package/dist/feishu.js.map +1 -1
- package/dist/format/builder.d.ts +119 -0
- package/dist/format/builder.js +190 -0
- package/dist/format/builder.js.map +1 -0
- package/dist/format/card.d.ts +24 -0
- package/dist/format/card.js +104 -0
- package/dist/format/card.js.map +1 -0
- package/dist/format/constants.d.ts +44 -0
- package/dist/format/constants.js +202 -0
- package/dist/format/constants.js.map +1 -0
- package/dist/format/document.d.ts +18 -0
- package/dist/format/document.js +163 -0
- package/dist/format/document.js.map +1 -0
- package/dist/format/index.d.ts +14 -0
- package/dist/format/index.js +17 -0
- package/dist/format/index.js.map +1 -0
- package/dist/format/parser.d.ts +90 -0
- package/dist/format/parser.js +220 -0
- package/dist/format/parser.js.map +1 -0
- package/dist/format/sanitize.d.ts +18 -0
- package/dist/format/sanitize.js +47 -0
- package/dist/format/sanitize.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -7
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown 解析器
|
|
3
|
+
* 解析表格、任务列表、公式、高亮块等
|
|
4
|
+
*/
|
|
5
|
+
// ── 表格解析 ───────────────────────────────────────────────────
|
|
6
|
+
/**
|
|
7
|
+
* 解析表格对齐方式
|
|
8
|
+
* :--- 左对齐, :---: 居中, ---: 右对齐
|
|
9
|
+
*/
|
|
10
|
+
function parseAlignment(cell) {
|
|
11
|
+
const trimmed = cell.trim();
|
|
12
|
+
const left = trimmed.startsWith(":");
|
|
13
|
+
const right = trimmed.endsWith(":");
|
|
14
|
+
if (left && right)
|
|
15
|
+
return "center";
|
|
16
|
+
if (right)
|
|
17
|
+
return "right";
|
|
18
|
+
return "left";
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 解析表格行
|
|
22
|
+
*/
|
|
23
|
+
function parseTableRow(line) {
|
|
24
|
+
const trimmed = line.trim();
|
|
25
|
+
if (!trimmed.startsWith("|") || !trimmed.endsWith("|"))
|
|
26
|
+
return null;
|
|
27
|
+
return trimmed
|
|
28
|
+
.slice(1, -1)
|
|
29
|
+
.split("|")
|
|
30
|
+
.map(cell => cell.trim());
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 检查是否为表格分隔行
|
|
34
|
+
*/
|
|
35
|
+
function isTableSeparator(line) {
|
|
36
|
+
const cells = parseTableRow(line);
|
|
37
|
+
if (!cells)
|
|
38
|
+
return false;
|
|
39
|
+
return cells.every(cell => /^:?-+:?$/.test(cell.trim()));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 解析 Markdown 表格
|
|
43
|
+
* @returns 表格数据和结束行索引,如果不是表格返回 null
|
|
44
|
+
*/
|
|
45
|
+
export function parseTable(lines, startIndex) {
|
|
46
|
+
if (startIndex >= lines.length)
|
|
47
|
+
return null;
|
|
48
|
+
// 第一行必须是表头
|
|
49
|
+
const headerRow = parseTableRow(lines[startIndex]);
|
|
50
|
+
if (!headerRow || headerRow.length === 0)
|
|
51
|
+
return null;
|
|
52
|
+
// 第二行必须是分隔符
|
|
53
|
+
if (startIndex + 1 >= lines.length)
|
|
54
|
+
return null;
|
|
55
|
+
if (!isTableSeparator(lines[startIndex + 1]))
|
|
56
|
+
return null;
|
|
57
|
+
// 解析对齐方式
|
|
58
|
+
const separatorCells = parseTableRow(lines[startIndex + 1]);
|
|
59
|
+
const alignments = separatorCells.map(parseAlignment);
|
|
60
|
+
const rows = [headerRow];
|
|
61
|
+
// 解析数据行
|
|
62
|
+
let endIndex = startIndex + 2;
|
|
63
|
+
while (endIndex < lines.length) {
|
|
64
|
+
const row = parseTableRow(lines[endIndex]);
|
|
65
|
+
if (!row)
|
|
66
|
+
break;
|
|
67
|
+
// 补齐列数
|
|
68
|
+
while (row.length < headerRow.length)
|
|
69
|
+
row.push("");
|
|
70
|
+
rows.push(row.slice(0, headerRow.length));
|
|
71
|
+
endIndex++;
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
data: { rows, alignments },
|
|
75
|
+
endIndex: endIndex - 1,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* 解析任务列表
|
|
80
|
+
* - [ ] 未完成
|
|
81
|
+
* - [x] 已完成
|
|
82
|
+
*/
|
|
83
|
+
export function parseTodo(line) {
|
|
84
|
+
const match = line.match(/^\s*[-*]\s+\[([ xX])\]\s+(.+)$/);
|
|
85
|
+
if (!match)
|
|
86
|
+
return null;
|
|
87
|
+
return {
|
|
88
|
+
checked: match[1].toLowerCase() === "x",
|
|
89
|
+
content: match[2].trim(),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* 解析块级公式 $$...$$
|
|
94
|
+
*/
|
|
95
|
+
export function parseBlockEquation(lines, startIndex) {
|
|
96
|
+
const line = lines[startIndex].trim();
|
|
97
|
+
// 单行公式:$$E = mc^2$$
|
|
98
|
+
const singleLineMatch = line.match(/^\$\$([^$]+)\$\$$/);
|
|
99
|
+
if (singleLineMatch) {
|
|
100
|
+
return {
|
|
101
|
+
result: { latex: singleLineMatch[1].trim(), inline: false },
|
|
102
|
+
endIndex: startIndex,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
// 多行公式:$$ 开头
|
|
106
|
+
if (line !== "$$")
|
|
107
|
+
return null;
|
|
108
|
+
const latexLines = [];
|
|
109
|
+
let endIndex = startIndex + 1;
|
|
110
|
+
while (endIndex < lines.length) {
|
|
111
|
+
if (lines[endIndex].trim() === "$$") {
|
|
112
|
+
return {
|
|
113
|
+
result: { latex: latexLines.join("\n"), inline: false },
|
|
114
|
+
endIndex,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
latexLines.push(lines[endIndex]);
|
|
118
|
+
endIndex++;
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* 解析行内公式 $...$
|
|
124
|
+
*/
|
|
125
|
+
export function parseInlineEquation(text) {
|
|
126
|
+
const match = text.match(/^\$([^$]+)\$/);
|
|
127
|
+
if (!match)
|
|
128
|
+
return null;
|
|
129
|
+
return {
|
|
130
|
+
latex: match[1].trim(),
|
|
131
|
+
remaining: text.slice(match[0].length),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* 解析高亮块
|
|
136
|
+
* > [!NOTE]
|
|
137
|
+
* > 这是一个提示
|
|
138
|
+
*
|
|
139
|
+
* > [!WARNING]
|
|
140
|
+
* > 这是一个警告
|
|
141
|
+
*/
|
|
142
|
+
export function parseCallout(lines, startIndex) {
|
|
143
|
+
const line = lines[startIndex].trim();
|
|
144
|
+
// 匹配 > [!TYPE]
|
|
145
|
+
const headerMatch = line.match(/^>\s*\[!(\w+)\]\s*$/);
|
|
146
|
+
if (!headerMatch)
|
|
147
|
+
return null;
|
|
148
|
+
const type = headerMatch[1].toUpperCase();
|
|
149
|
+
const content = [];
|
|
150
|
+
let endIndex = startIndex + 1;
|
|
151
|
+
// 收集后续的引用行
|
|
152
|
+
while (endIndex < lines.length) {
|
|
153
|
+
const nextLine = lines[endIndex].trim();
|
|
154
|
+
if (nextLine.startsWith("> ")) {
|
|
155
|
+
content.push(nextLine.slice(2));
|
|
156
|
+
endIndex++;
|
|
157
|
+
}
|
|
158
|
+
else if (nextLine === ">") {
|
|
159
|
+
endIndex++;
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
result: { type, content },
|
|
167
|
+
endIndex: endIndex - 1,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
// ── 辅助函数 ───────────────────────────────────────────────────
|
|
171
|
+
/**
|
|
172
|
+
* 检测标题级别
|
|
173
|
+
* @returns 标题级别 (1-6),0 表示不是标题
|
|
174
|
+
*/
|
|
175
|
+
export function parseHeading(line) {
|
|
176
|
+
const match = line.match(/^(#{1,6})\s/);
|
|
177
|
+
return match ? match[1].length : 0;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* 检测是否为代码块开始
|
|
181
|
+
*/
|
|
182
|
+
export function isCodeBlockStart(line) {
|
|
183
|
+
const match = line.match(/^```(\w*)/);
|
|
184
|
+
if (match) {
|
|
185
|
+
return { isStart: true, lang: match[1] || "" };
|
|
186
|
+
}
|
|
187
|
+
return { isStart: false, lang: "" };
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* 检测是否为代码块结束
|
|
191
|
+
*/
|
|
192
|
+
export function isCodeBlockEnd(line) {
|
|
193
|
+
return line.trim() === "```";
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* 检测是否为引用块
|
|
197
|
+
*/
|
|
198
|
+
export function isQuote(line) {
|
|
199
|
+
return line.trim().startsWith("> ");
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* 检测是否为无序列表
|
|
203
|
+
*/
|
|
204
|
+
export function isBulletList(line) {
|
|
205
|
+
return /^(\s*)[-*]\s+/.test(line) && !parseTodo(line);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* 检测是否为有序列表
|
|
209
|
+
*/
|
|
210
|
+
export function isOrderedList(line) {
|
|
211
|
+
return /^(\s*)(\d+)\.\s+/.test(line);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* 检测是否为分割线
|
|
215
|
+
*/
|
|
216
|
+
export function isDivider(line) {
|
|
217
|
+
const trimmed = line.trim();
|
|
218
|
+
return trimmed === "---" || trimmed === "***" || trimmed === "___";
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/format/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 内容清理模块
|
|
3
|
+
* 处理 blob URL、外部图片等无效内容
|
|
4
|
+
*/
|
|
5
|
+
export interface SanitizeResult {
|
|
6
|
+
content: string;
|
|
7
|
+
warnings: string[];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* 清理内容中的无效 URL
|
|
11
|
+
* 1. blob: URL - 完全移除
|
|
12
|
+
* 2. 外部图片 URL - 转为链接 + emoji
|
|
13
|
+
*/
|
|
14
|
+
export declare function sanitizeContent(content: string): SanitizeResult;
|
|
15
|
+
/**
|
|
16
|
+
* 格式化警告消息
|
|
17
|
+
*/
|
|
18
|
+
export declare function formatWarnings(warnings: string[]): string;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 内容清理模块
|
|
3
|
+
* 处理 blob URL、外部图片等无效内容
|
|
4
|
+
*/
|
|
5
|
+
import { EXTERNAL_IMAGE_EMOJI } from "./constants.js";
|
|
6
|
+
/**
|
|
7
|
+
* 清理内容中的无效 URL
|
|
8
|
+
* 1. blob: URL - 完全移除
|
|
9
|
+
* 2. 外部图片 URL - 转为链接 + emoji
|
|
10
|
+
*/
|
|
11
|
+
export function sanitizeContent(content) {
|
|
12
|
+
const warnings = [];
|
|
13
|
+
// 1. 处理 blob URL
|
|
14
|
+
const blobMatches = content.match(/!\[[^\]]*\]\(blob:[^)]+\)/gi) || [];
|
|
15
|
+
if (blobMatches.length > 0) {
|
|
16
|
+
console.warn(`[WARN] Filtered ${blobMatches.length} blob URL image(s)`);
|
|
17
|
+
// 移除 Markdown 图片 
|
|
18
|
+
content = content.replace(/!\[[^\]]*\]\(blob:[^)]+\)/gi, '');
|
|
19
|
+
// 保留文字,移除 blob 链接 [...](blob:...)
|
|
20
|
+
content = content.replace(/\[([^\]]+)\]\(blob:[^)]+\)/gi, '$1');
|
|
21
|
+
// 移除独立的 blob URL
|
|
22
|
+
content = content.replace(/blob:https?:\/\/[^\s\)]+/gi, '');
|
|
23
|
+
warnings.push(`已过滤 ${blobMatches.length} 个无效图片`);
|
|
24
|
+
}
|
|
25
|
+
// 2. 处理外部图片(非 blob: 的 https?:// 图片)
|
|
26
|
+
// 飞书卡片/文档不支持外部图片 URL,转为普通链接
|
|
27
|
+
const externalImgMatches = content.match(/!\[([^\]]*)\]\((https?:\/\/[^)]+)\)/gi) || [];
|
|
28
|
+
if (externalImgMatches.length > 0) {
|
|
29
|
+
console.warn(`[WARN] Converting ${externalImgMatches.length} external image URL(s) to links`);
|
|
30
|
+
// 转换: → [alt](https://...) 🖼️
|
|
31
|
+
content = content.replace(/!\[([^\]]*)\]\((https?:\/\/[^)]+)\)/gi, (_, alt, url) => {
|
|
32
|
+
const displayText = alt || "图片";
|
|
33
|
+
return `[${displayText}](${url}) ${EXTERNAL_IMAGE_EMOJI}`;
|
|
34
|
+
});
|
|
35
|
+
warnings.push(`已转换 ${externalImgMatches.length} 个外部图片为链接`);
|
|
36
|
+
}
|
|
37
|
+
return { content, warnings };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 格式化警告消息
|
|
41
|
+
*/
|
|
42
|
+
export function formatWarnings(warnings) {
|
|
43
|
+
if (warnings.length === 0)
|
|
44
|
+
return "";
|
|
45
|
+
return "\n\n(" + warnings.join(",") + ")";
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=sanitize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/format/sanitize.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAOtD;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,iBAAiB;IACjB,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,IAAI,EAAE,CAAC;IACvE,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC,mBAAmB,WAAW,CAAC,MAAM,oBAAoB,CAAC,CAAC;QAExE,kCAAkC;QAClC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,6BAA6B,EAAE,EAAE,CAAC,CAAC;QAE7D,kCAAkC;QAClC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,8BAA8B,EAAE,IAAI,CAAC,CAAC;QAEhE,iBAAiB;QACjB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAC;QAE5D,QAAQ,CAAC,IAAI,CAAC,OAAO,WAAW,CAAC,MAAM,QAAQ,CAAC,CAAC;IACnD,CAAC;IAED,oCAAoC;IACpC,4BAA4B;IAC5B,MAAM,kBAAkB,GAAG,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,IAAI,EAAE,CAAC;IACxF,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,OAAO,CAAC,IAAI,CAAC,qBAAqB,kBAAkB,CAAC,MAAM,iCAAiC,CAAC,CAAC;QAE9F,kDAAkD;QAClD,OAAO,GAAG,OAAO,CAAC,OAAO,CACvB,uCAAuC,EACvC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;YACd,MAAM,WAAW,GAAG,GAAG,IAAI,IAAI,CAAC;YAChC,OAAO,IAAI,WAAW,KAAK,GAAG,KAAK,oBAAoB,EAAE,CAAC;QAC5D,CAAC,CACF,CAAC;QAEF,QAAQ,CAAC,IAAI,CAAC,OAAO,kBAAkB,CAAC,MAAM,WAAW,CAAC,CAAC;IAC7D,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,QAAkB;IAC/C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,OAAO,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;AAC5C,CAAC"}
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.1.
|
|
1
|
+
export declare const VERSION = "0.1.8";
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "larkcc",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Claude Code in Feishu/Lark - AI coding assistant bot",
|
|
5
5
|
"author": "sujie <13156660820@163.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,21 +40,22 @@
|
|
|
40
40
|
"scripts": {
|
|
41
41
|
"prebuild": "node scripts/generate-version.js",
|
|
42
42
|
"dev": "tsx watch src/index.ts",
|
|
43
|
-
"build": "tsc",
|
|
43
|
+
"build": "tsc && mkdir -p dist/commands && cp src/commands/default-prompts.yml dist/commands/",
|
|
44
44
|
"start": "node dist/index.js"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@anthropic-ai/claude-agent-sdk": "latest",
|
|
48
48
|
"@larksuiteoapi/node-sdk": "^1",
|
|
49
|
+
"chalk": "^5",
|
|
49
50
|
"commander": "^12",
|
|
50
51
|
"js-yaml": "^4",
|
|
51
|
-
"ora": "^8"
|
|
52
|
-
"chalk": "^5"
|
|
52
|
+
"ora": "^8"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"
|
|
56
|
-
"typescript": "^5",
|
|
55
|
+
"@types/js-yaml": "^4",
|
|
57
56
|
"@types/node": "^22",
|
|
58
|
-
"
|
|
57
|
+
"semver": "^7.7.4",
|
|
58
|
+
"tsx": "^4",
|
|
59
|
+
"typescript": "^5"
|
|
59
60
|
}
|
|
60
61
|
}
|