svelte-language-server
Version:
A language server for Svelte
113 lines • 4.76 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getFoldingRanges = getFoldingRanges;
const vscode_languageserver_types_1 = require("vscode-languageserver-types");
const parseHtml_1 = require("../../lib/documents/parseHtml");
const COMMENT_START = '<!--';
const regionRegex = /^\s*#(region\b)|(endregion\b)/;
function getFoldingRanges(document, capability = {}) {
const foldingRanges = [];
const foldingStacks = [];
const text = document.getText();
let offset = 0;
let pendingCommentStart = text.indexOf(COMMENT_START, offset);
collectionFoldingRangeForNodes(document.html.roots, 0, text.length);
if (!capability.lineFoldingOnly) {
return foldingRanges.filter((r) => r.startLine <= r.endLine);
}
const lineFoldingResults = new Map();
for (const r of foldingRanges) {
const startLine = r.startLine;
const endLine = r.kind === vscode_languageserver_types_1.FoldingRangeKind.Comment || r.kind === vscode_languageserver_types_1.FoldingRangeKind.Region
? r.endLine
: previousLineOfEndLine(startLine, r.endLine);
if (startLine < endLine && !lineFoldingResults.has(startLine)) {
const foldingRange = {
startLine,
endLine
};
if (r.kind) {
foldingRange.kind = r.kind;
}
lineFoldingResults.set(startLine, foldingRange);
}
}
return Array.from(lineFoldingResults.values());
function collectFoldingRanges(node) {
foldingStacks.push(node);
if (node.startTagEnd !== undefined && node.endTagStart !== undefined) {
collectionFoldingRangeForNodes(node.children, node.startTagEnd, node.endTagStart);
}
const index = foldingStacks.lastIndexOf(node);
if (index !== -1) {
// discard everything after the current node, it's most likely a overlapping folding range.
foldingStacks.length = index;
addFoldingRange(node.start, node.end);
}
}
function collectionFoldingRangeForNodes(nodes, containerStart, containerEnd) {
if (!nodes.length) {
checkCommentsInRange(containerStart, containerEnd);
return;
}
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
const commentCheckStart = i === 0 ? containerStart : nodes[i - 1].end;
checkCommentsInRange(commentCheckStart, node.start);
collectFoldingRanges(node);
}
const lastNode = nodes[nodes.length - 1];
checkCommentsInRange(lastNode.end, containerEnd);
}
function checkCommentsInRange(start, end) {
if (pendingCommentStart < start || pendingCommentStart > end) {
return;
}
const comments = (0, parseHtml_1.scanCommentWithinTextOrComment)(text, start, end);
for (const comment of comments) {
const commentText = text.substring(comment.start, comment.end);
const match = regionRegex.exec(commentText);
if (!match) {
addFoldingRange(comment.start, comment.end, vscode_languageserver_types_1.FoldingRangeKind.Comment);
continue;
}
const isStartRegion = !!match[1];
if (isStartRegion) {
foldingStacks.push({ start: comment.start, tag: '#region' });
continue;
}
let startRegionIndex = foldingStacks.length - 1;
while (startRegionIndex >= 0) {
const s = foldingStacks[startRegionIndex];
if (s.tag === '#region') {
break;
}
startRegionIndex--;
}
if (startRegionIndex === -1) {
continue;
}
const startOffset = foldingStacks[startRegionIndex].start;
foldingStacks.length = startRegionIndex;
if (startOffset !== undefined) {
addFoldingRange(startOffset, comment.end, vscode_languageserver_types_1.FoldingRangeKind.Region);
}
}
pendingCommentStart = text.indexOf(COMMENT_START, end);
}
function addFoldingRange(start, end, kind) {
const startPos = document.positionAt(start);
const endPos = document.positionAt(end);
foldingRanges.push({
startLine: startPos.line,
startCharacter: startPos.character,
endLine: endPos.line,
endCharacter: endPos.character,
kind
});
}
}
function previousLineOfEndLine(startLine, endLine) {
return Math.max(endLine - 1, startLine);
}
//# sourceMappingURL=getFoldingRanges.js.map