Files
FrenoCorp/node_modules/eslint-plugin-solid/dist/rules/self-closing-comp.js
Michael Freno 7c684a42cc FRE-600: Fix code review blockers
- Consolidated duplicate UndoManagers to single instance
- Fixed connection promise to only resolve on 'connected' status
- Fixed WebSocketProvider import (WebsocketProvider)
- Added proper doc.destroy() cleanup
- Renamed isPresenceInitialized property to avoid conflict

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-25 00:08:01 -04:00

117 lines
5.0 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@typescript-eslint/utils");
const utils_2 = require("../utils");
const createRule = utils_1.ESLintUtils.RuleCreator.withoutDocs;
function isComponent(node) {
return ((node.name.type === "JSXIdentifier" && !(0, utils_2.isDOMElementName)(node.name.name)) ||
node.name.type === "JSXMemberExpression");
}
const voidDOMElementRegex = /^(?:area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)$/;
function isVoidDOMElementName(name) {
return voidDOMElementRegex.test(name);
}
function childrenIsEmpty(node) {
return node.parent.children.length === 0;
}
function childrenIsMultilineSpaces(node) {
const childrens = node.parent.children;
return (childrens.length === 1 &&
childrens[0].type === "JSXText" &&
childrens[0].value.indexOf("\n") !== -1 &&
childrens[0].value.replace(/(?!\xA0)\s/g, "") === "");
}
exports.default = createRule({
meta: {
type: "layout",
docs: {
description: "Disallow extra closing tags for components without children.",
url: "https://github.com/solidjs-community/eslint-plugin-solid/blob/main/docs/self-closing-comp.md",
},
fixable: "code",
schema: [
{
type: "object",
properties: {
component: {
type: "string",
description: "which Solid components should be self-closing when possible",
enum: ["all", "none"],
default: "all",
},
html: {
type: "string",
description: "which native elements should be self-closing when possible",
enum: ["all", "void", "none"],
default: "all",
},
},
additionalProperties: false,
},
],
messages: {
selfClose: "Empty components are self-closing.",
dontSelfClose: "This element should not be self-closing.",
},
},
defaultOptions: [],
create(context) {
function shouldBeSelfClosedWhenPossible(node) {
if (isComponent(node)) {
const whichComponents = context.options[0]?.component ?? "all";
return whichComponents === "all";
}
else if (node.name.type === "JSXIdentifier" && (0, utils_2.isDOMElementName)(node.name.name)) {
const whichComponents = context.options[0]?.html ?? "all";
switch (whichComponents) {
case "all":
return true;
case "void":
return isVoidDOMElementName(node.name.name);
case "none":
return false;
}
}
return true;
}
return {
JSXOpeningElement(node) {
const canSelfClose = childrenIsEmpty(node) || childrenIsMultilineSpaces(node);
if (canSelfClose) {
const shouldSelfClose = shouldBeSelfClosedWhenPossible(node);
if (shouldSelfClose && !node.selfClosing) {
context.report({
node,
messageId: "selfClose",
fix(fixer) {
const openingElementEnding = node.range[1] - 1;
const closingElementEnding = node.parent.closingElement.range[1];
const range = [openingElementEnding, closingElementEnding];
return fixer.replaceTextRange(range, " />");
},
});
}
else if (!shouldSelfClose && node.selfClosing) {
context.report({
node,
messageId: "dontSelfClose",
fix(fixer) {
const sourceCode = context.getSourceCode();
const tagName = context.getSourceCode().getText(node.name);
const selfCloseEnding = node.range[1];
const lastTokens = sourceCode.getLastTokens(node, { count: 3 });
const isSpaceBeforeSelfClose = sourceCode.isSpaceBetween?.(lastTokens[0], lastTokens[1]);
const range = [
isSpaceBeforeSelfClose ? selfCloseEnding - 3 : selfCloseEnding - 2,
selfCloseEnding,
];
return fixer.replaceTextRange(range, `></${tagName}>`);
},
});
}
}
},
};
},
});