monaco-latex
Version:
LaTeX language support for Monaco Editor
115 lines (114 loc) • 4.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createFoldingProvider = exports.LaTeXFoldingRangeProvider = void 0;
class LaTeXFoldingRangeProvider {
constructor(monaco) {
this.monaco = monaco;
}
provideFoldingRanges(model, context, token) {
const ranges = [];
const lineCount = model.getLineCount();
// Stack for tracking nested environments
const envStack = [];
// Stack for sections (hierarchical)
const sectionStack = [];
const sectionLevels = {
part: 0,
chapter: 1,
section: 2,
subsection: 3,
subsubsection: 4,
paragraph: 5,
subparagraph: 6,
};
// Multi-line comment tracking
let commentStart = null;
for (let lineNumber = 1; lineNumber <= lineCount; lineNumber++) {
const line = model.getLineContent(lineNumber);
// Check for \begin{environment}
const beginMatch = line.match(/\\begin\{(\w+\*?)\}/);
if (beginMatch) {
envStack.push({ name: beginMatch[1], line: lineNumber });
}
// Check for \end{environment}
const endMatch = line.match(/\\end\{(\w+\*?)\}/);
if (endMatch && envStack.length > 0) {
// Find matching begin
for (let i = envStack.length - 1; i >= 0; i--) {
if (envStack[i].name === endMatch[1]) {
if (lineNumber > envStack[i].line) {
ranges.push({
start: envStack[i].line,
end: lineNumber,
kind: this.monaco.languages.FoldingRangeKind.Region,
});
}
envStack.splice(i, 1);
break;
}
}
}
// Check for sections
const sectionMatch = line.match(/\\(part|chapter|section|subsection|subsubsection|paragraph|subparagraph)\*?\s*[\[{]/);
if (sectionMatch) {
const level = sectionLevels[sectionMatch[1]];
// Close any sections at same or higher level (lower number = higher level)
while (sectionStack.length > 0 &&
sectionStack[sectionStack.length - 1].level >= level) {
const prev = sectionStack.pop();
if (lineNumber - prev.line > 1) {
ranges.push({
start: prev.line,
end: lineNumber - 1,
kind: this.monaco.languages.FoldingRangeKind.Region,
});
}
}
sectionStack.push({ level, line: lineNumber });
}
// Check for comment blocks (consecutive comment lines)
const isComment = line.trim().startsWith('%');
if (isComment && commentStart === null) {
commentStart = lineNumber;
}
else if (!isComment && commentStart !== null) {
if (lineNumber - commentStart > 2) {
ranges.push({
start: commentStart,
end: lineNumber - 1,
kind: this.monaco.languages.FoldingRangeKind.Comment,
});
}
commentStart = null;
}
}
// Close remaining sections at end of document
while (sectionStack.length > 0) {
const prev = sectionStack.pop();
if (lineCount - prev.line > 1) {
ranges.push({
start: prev.line,
end: lineCount,
kind: this.monaco.languages.FoldingRangeKind.Region,
});
}
}
// Close any unclosed comment block
if (commentStart !== null && lineCount - commentStart > 2) {
ranges.push({
start: commentStart,
end: lineCount,
kind: this.monaco.languages.FoldingRangeKind.Comment,
});
}
return ranges;
}
}
exports.LaTeXFoldingRangeProvider = LaTeXFoldingRangeProvider;
/**
* Creates a folding range provider for LaTeX.
*/
function createFoldingProvider(monaco) {
return new LaTeXFoldingRangeProvider(monaco);
}
exports.createFoldingProvider = createFoldingProvider;