MCPcopy Create free account
hub / github.com/Moyf/easy-copy / detectCodeBlockFromLines

Function detectCodeBlockFromLines

src/codeBlockDetect.ts:35–108  ·  view source on GitHub ↗
(
	lines: string[],
	cursorLine: number,
	behavior: CodeBlockBehavior,
)

Source from the content-addressed store, hash-verified

33 * @returns ContextData(命中代码块)或 null
34 */
35export function detectCodeBlockFromLines(
36 lines: string[],
37 cursorLine: number,
38 behavior: CodeBlockBehavior,
39): ContextData | null {
40 if (behavior === CodeBlockBehavior.DISABLED) return null;
41
42 const totalLines = lines.length;
43
44 // 阶段一:用栈追踪嵌套层级,找到光标所在的最内层开始围栏。
45 //
46 // 栈为空(不在任何块内):
47 // 遇到有效围栏行(parseFenceLength >= 3)→ push 进栈
48 // 栈非空(在某块内):
49 // 遇到满足 isClosingFence(长度 >= 栈顶 openLen 的纯反引号行)→ pop
50 // 遇到带 info string 的围栏行(不是结束围栏)→ push(进入内层块)
51 // 遇到短于 openLen 的纯反引号行 → 视为内容,忽略
52
53 const stack: Array<{ fenceStart: number; openLen: number }> = [];
54
55 for (let i = 0; i <= cursorLine; i++) {
56 const len = parseFenceLength(lines[i]);
57 if (len === 0) continue;
58
59 if (stack.length === 0) {
60 stack.push({ fenceStart: i, openLen: len });
61 } else {
62 const { openLen } = stack[stack.length - 1];
63 if (isClosingFence(lines[i], openLen)) {
64 // 满足关闭当前层的条件
65 stack.pop();
66 } else if (!isClosingFence(lines[i], len)) {
67 // 有反引号开头,但后面跟了 info string(不是纯围栏行)
68 // → 内层块的开始围栏
69 stack.push({ fenceStart: i, openLen: len });
70 }
71 // 其他情况:纯反引号行但长度不足以关闭当前层 → 内容,忽略
72 }
73 }
74
75 if (stack.length === 0) return null;
76
77 const { fenceStart, openLen } = stack[stack.length - 1];
78
79 // 光标正好在开始围栏行上,不算「块内」
80 if (fenceStart === cursorLine) return null;
81
82 // 阶段二:从 fenceStart+1 向下找匹配的结束围栏
83 let fenceEnd = -1;
84 for (let i = fenceStart + 1; i < totalLines; i++) {
85 if (isClosingFence(lines[i], openLen)) {
86 fenceEnd = i;
87 break;
88 }
89 }
90 if (fenceEnd === -1) return null;
91 if (cursorLine >= fenceEnd) return null;
92

Callers 2

detectCodeBlockMethod · 0.90

Calls 2

parseFenceLengthFunction · 0.85
isClosingFenceFunction · 0.85

Tested by

no test coverage detected