108
return markHeaders;
109
}
111
>
// Process text in overlapping chunks for better performance
112
>
for (let startLine = 1; startLine <= endLineNumber; startLine += CHUNK_SIZE - MAX_SECTION_LINES) {
113
>
const endLine = Math.min(startLine + CHUNK_SIZE - 1, endLineNumber);
114
>
const lines: string[] = [];
115
>
116
>
// Collect lines for the current chunk
117
>
for (let i = startLine; i <= endLine; i++) {
118
>
lines.push(model.getLineContent(i));
119
>
}
120
>
121
>
const text = lines.join('\n');
122
>
regex.lastIndex = 0;
123
>
124
>
let match: RegExpExecArray | null;
125
>
while ((match = regex.exec(text)) !== null) {
126
>
// Calculate which line this match starts on by counting newlines before it
127
>
const precedingText = text.substring(0, match.index);
128
>
const lineOffset = (precedingText.match(/\n/g) || []).length;
129
>
const lineNumber = startLine + lineOffset;
130
>
131
>
// Calculate match height to check overlap properly
132
>
const matchLines = match[0].split('\n');
133
>
const matchHeight = matchLines.length;
134
>
const matchEndLine = lineNumber + matchHeight - 1;
135
>
136
>
// Calculate start column - need to find the start of the line containing the match
137
>
const lineStartIndex = precedingText.lastIndexOf('\n') + 1;
138
>
const startColumn = match.index - lineStartIndex + 1;
139
>
140
>
// Calculate end column - need to handle multi-line matches
141
>
const lastMatchLine = matchLines[matchLines.length - 1];
142
>
const endColumn = matchHeight === 1 ? startColumn + match[0].length : lastMatchLine.length + 1;
143
>
144
>
const range = {
145
>
startLineNumber: lineNumber,
146
>
startColumn,
147
>
endLineNumber: matchEndLine,
148
>
endColumn
149
>
};
150
>
151
>
const text2 = (match.groups ?? {})['label'] ?? '';
152
>
const hasSeparatorLine = ((match.groups ?? {})['separator'] ?? '') !== '';
153
>
154
>
const sectionHeader = {
155
>
range,
156
>
text: text2,
157
>
hasSeparatorLine,
158
>
shouldBeInComments: true
159
>
};
160
>
161
>
if (sectionHeader.text || sectionHeader.hasSeparatorLine) {
162
>
// only push if the previous one doesn't have this same linbe
163
>
if (markHeaders.length === 0 || markHeaders[markHeaders.length - 1].range.endLineNumber < sectionHeader.range.startLineNumber) {
164
>
markHeaders.push(sectionHeader);
165
>
}
166
>
}
167
>
168
>
// Move lastIndex past the current match to avoid infinite loop
169
>
regex.lastIndex = match.index + match[0].length;
170
>
}
171
>
}
172
>
173
>
return markHeaders;
174
>
}
175
176
function getHeaderText(text: string): { text: string; hasSeparatorLine: boolean } {