File: /var/www/quadcode.com/node_modules/eslint-plugin-svelte/lib/rules/html-quotes.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("../utils");
const ast_utils_1 = require("../utils/ast-utils");
const ast_utils_2 = require("../utils/ast-utils");
const QUOTE_CHARS = {
double: '"',
single: "'",
};
const QUOTE_NAMES = {
double: "double quotes",
single: "single quotes",
unquoted: "unquoted",
};
exports.default = (0, utils_1.createRule)("html-quotes", {
meta: {
docs: {
description: "enforce quotes style of HTML attributes",
category: "Stylistic Issues",
recommended: false,
conflictWithPrettier: true,
},
fixable: "code",
schema: [
{
type: "object",
properties: {
prefer: { enum: ["double", "single"] },
dynamic: {
type: "object",
properties: {
quoted: { type: "boolean" },
avoidInvalidUnquotedInHTML: { type: "boolean" },
},
additionalProperties: false,
},
},
additionalProperties: false,
},
],
messages: {
expectedEnclosed: "Expected to be enclosed by quotes.",
expectedEnclosedBy: "Expected to be enclosed by {{kind}}.",
unexpectedEnclosed: "Unexpected to be enclosed by any quotes.",
},
type: "layout",
},
create(context) {
const sourceCode = context.getSourceCode();
const preferQuote = context.options[0]?.prefer ?? "double";
const dynamicQuote = context.options[0]?.dynamic?.quoted
? preferQuote
: "unquoted";
const avoidInvalidUnquotedInHTML = Boolean(context.options[0]?.dynamic?.avoidInvalidUnquotedInHTML);
function canBeUnquotedInHTML(text) {
return !/[\s"'<=>`]/u.test(text);
}
function verifyQuote(prefer, quoteAndRange) {
if (!quoteAndRange) {
return;
}
if (quoteAndRange.quote === prefer) {
return;
}
let messageId;
let expectedQuote = prefer;
if (quoteAndRange.quote !== "unquoted") {
if (expectedQuote === "unquoted") {
messageId = "unexpectedEnclosed";
}
else {
const contentText = sourceCode.text.slice(quoteAndRange.range[0] + 1, quoteAndRange.range[1] - 1);
const needEscape = contentText.includes(QUOTE_CHARS[expectedQuote]);
if (needEscape) {
return;
}
messageId = "expectedEnclosedBy";
}
}
else {
const contentText = sourceCode.text.slice(...quoteAndRange.range);
const needEscapeDoubleQuote = contentText.includes('"');
const needEscapeSingleQuote = contentText.includes("'");
if (needEscapeDoubleQuote && needEscapeSingleQuote) {
return;
}
if (needEscapeDoubleQuote && expectedQuote === "double") {
expectedQuote = "single";
messageId = "expectedEnclosed";
}
else if (needEscapeSingleQuote && expectedQuote === "single") {
expectedQuote = "double";
messageId = "expectedEnclosed";
}
else {
messageId = "expectedEnclosedBy";
}
}
context.report({
loc: {
start: sourceCode.getLocFromIndex(quoteAndRange.range[0]),
end: sourceCode.getLocFromIndex(quoteAndRange.range[1]),
},
messageId,
data: { kind: QUOTE_NAMES[expectedQuote] },
*fix(fixer) {
if (expectedQuote !== "unquoted") {
yield fixer.insertTextBeforeRange([quoteAndRange.range[0], quoteAndRange.range[0]], QUOTE_CHARS[expectedQuote]);
}
if (quoteAndRange.quote !== "unquoted") {
yield fixer.removeRange([
quoteAndRange.range[0],
quoteAndRange.range[0] + 1,
]);
yield fixer.removeRange([
quoteAndRange.range[1] - 1,
quoteAndRange.range[1],
]);
}
if (expectedQuote !== "unquoted") {
yield fixer.insertTextAfterRange([quoteAndRange.range[1], quoteAndRange.range[1]], QUOTE_CHARS[expectedQuote]);
}
},
});
}
function verifyForValues(attr) {
const quoteAndRange = (0, ast_utils_2.getAttributeValueQuoteAndRange)(attr, sourceCode);
verifyQuote(preferQuote, quoteAndRange);
}
function verifyForDynamicMustacheTag(attr, valueNode) {
const quoteAndRange = (0, ast_utils_2.getAttributeValueQuoteAndRange)(attr, sourceCode);
const text = sourceCode.text.slice(...valueNode.range);
verifyQuote(avoidInvalidUnquotedInHTML && !canBeUnquotedInHTML(text)
? preferQuote
: dynamicQuote, quoteAndRange);
}
function verifyForDirective(attr) {
const mustacheTokens = (0, ast_utils_1.getMustacheTokens)(attr, sourceCode);
if (!mustacheTokens) {
return;
}
const quoteAndRange = (0, ast_utils_2.getAttributeValueQuoteAndRange)(attr, sourceCode);
const text = sourceCode.text.slice(mustacheTokens.openToken.range[0], mustacheTokens.closeToken.range[1]);
verifyQuote(avoidInvalidUnquotedInHTML && !canBeUnquotedInHTML(text)
? preferQuote
: dynamicQuote, quoteAndRange);
}
return {
"SvelteAttribute, SvelteStyleDirective"(node) {
if (node.value.length === 1 &&
node.value[0].type === "SvelteMustacheTag") {
verifyForDynamicMustacheTag(node, node.value[0]);
}
else if (node.value.length >= 1) {
verifyForValues(node);
}
},
"SvelteDirective, SvelteSpecialDirective"(node) {
if (node.expression == null) {
return;
}
if (node.key.range[0] <= node.expression.range[0] &&
node.expression.range[1] <= node.key.range[1]) {
return;
}
verifyForDirective(node);
},
};
},
});