Files

116 lines
3.7 KiB
JavaScript

'use strict';
const require_runtime = require('../_virtual/_rolldown/runtime.js');
const require_index = require('../utils/index.js');
//#region lib/rules/no-child-content.js
/**
* @author Flo Edelmann
* See LICENSE file in root directory for full license.
*/
var require_no_child_content = /* @__PURE__ */ require_runtime.__commonJSMin(((exports, module) => {
const { defineTemplateBodyVisitor } = require_index.default;
/**
* @typedef {object} RuleOption
* @property {string[]} additionalDirectives
*/
/**
* @param {VNode | Token} node
* @returns {boolean}
*/
function isWhiteSpaceTextNode(node) {
return node.type === "VText" && node.value.trim() === "";
}
/**
* @param {Position} pos1
* @param {Position} pos2
* @returns {'less' | 'equal' | 'greater'}
*/
function comparePositions(pos1, pos2) {
if (pos1.line < pos2.line || pos1.line === pos2.line && pos1.column < pos2.column) return "less";
if (pos1.line > pos2.line || pos1.line === pos2.line && pos1.column > pos2.column) return "greater";
return "equal";
}
/**
* @param {(VNode | Token)[]} nodes
* @returns {SourceLocation | undefined}
*/
function getLocationRange(nodes) {
/** @type {Position | undefined} */
let start;
/** @type {Position | undefined} */
let end;
for (const node of nodes) {
if (!start || comparePositions(node.loc.start, start) === "less") start = node.loc.start;
if (!end || comparePositions(node.loc.end, end) === "greater") end = node.loc.end;
}
if (start === void 0 || end === void 0) return;
return {
start,
end
};
}
module.exports = {
meta: {
type: "problem",
docs: {
description: "disallow element's child contents which would be overwritten by a directive like `v-html` or `v-text`",
categories: ["vue3-essential", "vue2-essential"],
url: "https://eslint.vuejs.org/rules/no-child-content.html"
},
fixable: null,
hasSuggestions: true,
schema: [{
type: "object",
additionalProperties: false,
properties: { additionalDirectives: {
type: "array",
uniqueItems: true,
minItems: 1,
items: { type: "string" }
} },
required: ["additionalDirectives"]
}],
messages: {
disallowedChildContent: "Child content is disallowed because it will be overwritten by the v-{{ directiveName }} directive.",
removeChildContent: "Remove child content."
}
},
create(context) {
const directives = new Set(["html", "text"]);
/** @type {RuleOption | undefined} */
const option = context.options[0];
if (option !== void 0) for (const directive of option.additionalDirectives) directives.add(directive);
return defineTemplateBodyVisitor(context, { "VAttribute[directive=true]"(directiveNode) {
const directiveName = directiveNode.key.name.name;
const elementNode = directiveNode.parent.parent;
if (elementNode.endTag === null || !directives.has(directiveName)) return;
const elementComments = context.sourceCode.parserServices.getTemplateBodyTokenStore().getTokensBetween(elementNode.startTag, elementNode.endTag, {
includeComments: true,
filter: (token) => token.type === "HTMLComment"
});
const childNodes = [...elementNode.children, ...elementComments];
if (childNodes.some((childNode) => !isWhiteSpaceTextNode(childNode))) context.report({
node: elementNode,
loc: getLocationRange(childNodes),
messageId: "disallowedChildContent",
data: { directiveName },
suggest: [{
messageId: "removeChildContent",
*fix(fixer) {
for (const childNode of childNodes) yield fixer.remove(childNode);
}
}]
});
} });
}
};
}));
//#endregion
Object.defineProperty(exports, 'default', {
enumerable: true,
get: function () {
return require_no_child_content();
}
});