svelte-language-server
Version:
A language server for Svelte
100 lines • 3.74 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.isInTag = isInTag;
exports.isAttributeName = isAttributeName;
exports.isAttributeShorthand = isAttributeShorthand;
exports.isEventHandler = isEventHandler;
exports.isElseBlockWithElseIf = isElseBlockWithElseIf;
exports.hasElseBlock = hasElseBlock;
exports.findElseBlockTagStart = findElseBlockTagStart;
exports.findIfBlockEndTagStart = findIfBlockEndTagStart;
exports.walkSvelteAst = walkSvelteAst;
exports.isAwaitBlock = isAwaitBlock;
exports.isEachBlock = isEachBlock;
const estree_walker_1 = require("estree-walker");
function matchesOnly(type, only) {
return (!only ||
// We hide the detail that body/window are also like elements in the context of this usage
(only === 'Element' && ['Element', 'Body', 'Window'].includes(type)) ||
(only === 'InlineComponent' && type === 'InlineComponent'));
}
/**
* Returns true if given node is a component or html element, or if the offset is at the end of the node
* and its parent is a component or html element.
*/
function isInTag(node, offset) {
return (node?.type === 'InlineComponent' ||
node?.type === 'Element' ||
(node?.end === offset &&
(node?.parent?.type === 'InlineComponent' || node?.parent?.type === 'Element')));
}
/**
* Returns when given node represents an HTML Attribute.
* Example: The `class` in `<div class=".."`.
* Note: This method returns `false` for shorthands like `<div {foo}`.
*/
function isAttributeName(node, only) {
return !!node && node.type === 'Attribute' && matchesOnly(node.parent?.type, only);
}
/**
* Returns when given node represents an HTML Attribute shorthand or is inside one.
* Example: The `{foo}` in `<div {foo}`
*/
function isAttributeShorthand(node, only) {
if (!node) {
return false;
}
do {
// We could get the expression, or the shorthand, or the attribute
// Be pragmatic and just go upwards until we can't anymore
if (isAttributeName(node, only)) {
return true;
}
node = node.parent;
} while (node);
return false;
}
/**
* Returns when given node represents an HTML Attribute shorthand or is inside one.
* Example: The `on:click={foo}` in `<div on:click={foo}`
*/
function isEventHandler(node, only) {
return !!node && node.type === 'EventHandler' && matchesOnly(node.parent?.type, only);
}
function isElseBlockWithElseIf(node) {
return (!!node &&
node.type === 'ElseBlock' &&
'children' in node &&
Array.isArray(node.children) &&
node.children.length === 1 &&
node.children[0].type === 'IfBlock');
}
function hasElseBlock(node) {
return 'else' in node && !!node.else;
}
function findElseBlockTagStart(documentText, elseBlock) {
return documentText.lastIndexOf('{', documentText.lastIndexOf(':else', elseBlock.start));
}
function findIfBlockEndTagStart(documentText, ifBlock) {
return documentText.lastIndexOf('{', documentText.lastIndexOf('/if', ifBlock.end));
}
// wrap the estree-walker to make it svelte specific
// the type casting is necessary because estree-walker is not designed for this
// especially in v3 which svelte 4 uses
function walkSvelteAst(htmlAst, walker) {
(0, estree_walker_1.walk)(htmlAst, {
enter(node, parent, key, index) {
walker.enter?.call(this, node, parent, key, index);
},
leave(node, parent, key, index) {
walker.leave?.call(this, node, parent, key, index);
}
});
}
function isAwaitBlock(node) {
return node.type === 'AwaitBlock';
}
function isEachBlock(node) {
return node.type === 'EachBlock';
}
//# sourceMappingURL=svelte-ast-utils.js.map