File: /var/www/quadcode.com/node_modules/eslint-plugin-svelte/lib/rules/html-self-closing.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("../utils");
const ast_utils_1 = require("../utils/ast-utils");
const TYPE_MESSAGES = {
normal: "HTML elements",
void: "HTML void elements",
component: "Svelte custom components",
svelte: "Svelte special elements",
};
exports.default = (0, utils_1.createRule)("html-self-closing", {
meta: {
docs: {
description: "enforce self-closing style",
category: "Stylistic Issues",
recommended: false,
conflictWithPrettier: true,
},
type: "layout",
fixable: "code",
messages: {
requireClosing: "Require self-closing on {{type}}.",
disallowClosing: "Disallow self-closing on {{type}}.",
},
schema: [
{
anyOf: [
{
properties: {
void: {
enum: ["never", "always", "ignore"],
},
normal: {
enum: ["never", "always", "ignore"],
},
component: {
enum: ["never", "always", "ignore"],
},
svelte: {
enum: ["never", "always", "ignore"],
},
},
additionalProperties: false,
},
{
enum: ["all", "html", "none"],
},
],
},
],
},
create(context) {
let options = {
void: "always",
normal: "always",
component: "always",
svelte: "always",
};
const option = context.options?.[0];
switch (option) {
case "none":
options = {
void: "never",
normal: "never",
component: "never",
svelte: "never",
};
break;
case "html":
options = {
void: "always",
normal: "never",
component: "never",
svelte: "always",
};
break;
default:
if (typeof option !== "object" || option === null)
break;
options = {
...options,
...option,
};
break;
}
function getElementType(node) {
if (node.kind === "component")
return "component";
if (node.kind === "special")
return "svelte";
if ((0, ast_utils_1.isVoidHtmlElement)(node))
return "void";
return "normal";
}
function isElementEmpty(node) {
if (node.children.length <= 0)
return true;
for (const child of node.children) {
if (child.type !== "SvelteText")
return false;
if (!/^\s*$/.test(child.value))
return false;
}
return true;
}
function report(node, shouldBeClosed) {
const elementType = getElementType(node);
context.report({
node,
loc: {
start: context
.getSourceCode()
.getLocFromIndex(node.startTag.range[1] - (node.startTag.selfClosing ? 2 : 1)),
end: node.loc.end,
},
messageId: shouldBeClosed ? "requireClosing" : "disallowClosing",
data: {
type: TYPE_MESSAGES[elementType],
},
*fix(fixer) {
if (shouldBeClosed) {
for (const child of node.children) {
yield fixer.removeRange(child.range);
}
yield fixer.insertTextBeforeRange([node.startTag.range[1] - 1, node.startTag.range[1]], "/");
if (node.endTag)
yield fixer.removeRange(node.endTag.range);
}
else {
yield fixer.removeRange([
node.startTag.range[1] - 2,
node.startTag.range[1] - 1,
]);
if (!(0, ast_utils_1.isVoidHtmlElement)(node))
yield fixer.insertTextAfter(node, `</${(0, ast_utils_1.getNodeName)(node)}>`);
}
},
});
}
return {
SvelteElement(node) {
if (!isElementEmpty(node))
return;
const elementType = getElementType(node);
const elementTypeOptions = options[elementType];
if (elementTypeOptions === "ignore")
return;
const shouldBeClosed = elementTypeOptions === "always";
if (shouldBeClosed && !node.startTag.selfClosing) {
report(node, true);
}
else if (!shouldBeClosed && node.startTag.selfClosing) {
report(node, false);
}
},
};
},
});