diff --git a/lib/rules/component-name-in-template-casing.js b/lib/rules/component-name-in-template-casing.js
index 629f51209..d330f60da 100644
--- a/lib/rules/component-name-in-template-casing.js
+++ b/lib/rules/component-name-in-template-casing.js
@@ -122,9 +122,12 @@ module.exports = {
}
if (
- (!utils.isHtmlElementNode(node) && !utils.isSvgElementNode(node)) ||
+ (!utils.isHtmlElementNode(node) &&
+ !utils.isSvgElementNode(node) &&
+ !utils.isMathElementNode(node)) ||
utils.isHtmlWellKnownElementName(node.rawName) ||
utils.isSvgWellKnownElementName(node.rawName) ||
+ utils.isMathWellKnownElementName(node.rawName) ||
utils.isVueBuiltInElementName(node.rawName)
) {
return false
diff --git a/lib/rules/html-self-closing.js b/lib/rules/html-self-closing.js
index 531ddfc2b..5b98d8cf7 100644
--- a/lib/rules/html-self-closing.js
+++ b/lib/rules/html-self-closing.js
@@ -63,7 +63,7 @@ function getElementType(node) {
if (utils.isSvgElementNode(node)) {
return 'SVG'
}
- if (utils.isMathMLElementNode(node)) {
+ if (utils.isMathElementNode(node)) {
return 'MATH'
}
return 'UNKNOWN'
diff --git a/lib/rules/no-deprecated-html-element-is.js b/lib/rules/no-deprecated-html-element-is.js
index 7a0fd6225..5253ef2b7 100644
--- a/lib/rules/no-deprecated-html-element-is.js
+++ b/lib/rules/no-deprecated-html-element-is.js
@@ -27,7 +27,8 @@ module.exports = {
function isValidElement(node) {
return (
!utils.isHtmlWellKnownElementName(node.rawName) &&
- !utils.isSvgWellKnownElementName(node.rawName)
+ !utils.isSvgWellKnownElementName(node.rawName) &&
+ !utils.isMathWellKnownElementName(node.rawName)
)
}
return utils.defineTemplateBodyVisitor(context, {
diff --git a/lib/rules/no-undef-components.js b/lib/rules/no-undef-components.js
index 9eb74ad05..4371add7c 100644
--- a/lib/rules/no-undef-components.js
+++ b/lib/rules/no-undef-components.js
@@ -149,6 +149,7 @@ module.exports = {
if (
utils.isHtmlWellKnownElementName(rawName) ||
utils.isSvgWellKnownElementName(rawName) ||
+ utils.isMathWellKnownElementName(rawName) ||
utils.isBuiltInComponentName(kebabCaseName)
) {
return false
@@ -177,7 +178,11 @@ module.exports = {
/** @type {TemplateListener} */
const templateBodyVisitor = {
VElement(node) {
- if (!utils.isHtmlElementNode(node) && !utils.isSvgElementNode(node)) {
+ if (
+ !utils.isHtmlElementNode(node) &&
+ !utils.isSvgElementNode(node) &&
+ !utils.isMathElementNode(node)
+ ) {
return
}
verifyName(node.rawName, node.startTag)
diff --git a/lib/rules/no-unused-components.js b/lib/rules/no-unused-components.js
index 75b08fa14..9ba889ccc 100644
--- a/lib/rules/no-unused-components.js
+++ b/lib/rules/no-unused-components.js
@@ -52,9 +52,12 @@ module.exports = {
/** @param {VElement} node */
VElement(node) {
if (
- (!utils.isHtmlElementNode(node) && !utils.isSvgElementNode(node)) ||
+ (!utils.isHtmlElementNode(node) &&
+ !utils.isSvgElementNode(node) &&
+ !utils.isMathElementNode(node)) ||
utils.isHtmlWellKnownElementName(node.rawName) ||
- utils.isSvgWellKnownElementName(node.rawName)
+ utils.isSvgWellKnownElementName(node.rawName) ||
+ utils.isMathWellKnownElementName(node.rawName)
) {
return
}
diff --git a/lib/rules/require-typed-ref.js b/lib/rules/require-typed-ref.js
index 60a82432a..c05e6c829 100644
--- a/lib/rules/require-typed-ref.js
+++ b/lib/rules/require-typed-ref.js
@@ -44,13 +44,23 @@ module.exports = {
return {}
}
- const scriptSetup = utils.getScriptSetupElement(context)
- if (
- scriptSetup &&
- !utils.hasAttribute(scriptSetup, 'lang', 'ts') &&
- !utils.hasAttribute(scriptSetup, 'lang', 'typescript')
- ) {
- return {}
+ if (utils.isVueFile(filename)) {
+ const sourceCode = context.getSourceCode()
+ const documentFragment =
+ sourceCode.parserServices.getDocumentFragment &&
+ sourceCode.parserServices.getDocumentFragment()
+ if (!documentFragment) {
+ return {}
+ }
+ const scripts = documentFragment.children.filter(
+ /** @returns {element is VElement} */
+ (element) => utils.isVElement(element) && element.name === 'script'
+ )
+ if (
+ scripts.every((script) => !utils.hasAttribute(script, 'lang', 'ts'))
+ ) {
+ return {}
+ }
}
const defines = iterateDefineRefs(
diff --git a/lib/rules/script-setup-uses-vars.js b/lib/rules/script-setup-uses-vars.js
index 703d0cb9a..a1d873a6b 100644
--- a/lib/rules/script-setup-uses-vars.js
+++ b/lib/rules/script-setup-uses-vars.js
@@ -94,10 +94,13 @@ module.exports = {
},
VElement(node) {
if (
- (!utils.isHtmlElementNode(node) && !utils.isSvgElementNode(node)) ||
+ (!utils.isHtmlElementNode(node) &&
+ !utils.isSvgElementNode(node) &&
+ !utils.isMathElementNode(node)) ||
(node.rawName === node.name &&
(utils.isHtmlWellKnownElementName(node.rawName) ||
- utils.isSvgWellKnownElementName(node.rawName))) ||
+ utils.isSvgWellKnownElementName(node.rawName) ||
+ utils.isMathWellKnownElementName(node.rawName))) ||
utils.isBuiltInComponentName(node.rawName)
) {
return
diff --git a/lib/utils/index.js b/lib/utils/index.js
index f16bcef2c..9671c00d4 100644
--- a/lib/utils/index.js
+++ b/lib/utils/index.js
@@ -51,6 +51,7 @@ const { getScope } = require('./scope')
const HTML_ELEMENT_NAMES = new Set(require('./html-elements.json'))
const SVG_ELEMENT_NAMES = new Set(require('./svg-elements.json'))
+const MATH_ELEMENT_NAMES = new Set(require('./math-elements.json'))
const VOID_ELEMENT_NAMES = new Set(require('./void-elements.json'))
const VUE2_BUILTIN_COMPONENT_NAMES = new Set(
require('./vue2-builtin-components')
@@ -948,6 +949,8 @@ module.exports = {
!this.isHtmlWellKnownElementName(node.rawName)) ||
(this.isSvgElementNode(node) &&
!this.isSvgWellKnownElementName(node.rawName)) ||
+ (this.isMathElementNode(node) &&
+ !this.isMathWellKnownElementName(node.rawName)) ||
hasAttribute(node, 'is') ||
hasDirective(node, 'bind', 'is') ||
hasDirective(node, 'is')
@@ -977,7 +980,7 @@ module.exports = {
* @param {VElement} node The node to check.
* @returns {boolean} `true` if the node is a MathML element.
*/
- isMathMLElementNode(node) {
+ isMathElementNode(node) {
return node.namespace === NS.MathML
},
@@ -999,6 +1002,15 @@ module.exports = {
return SVG_ELEMENT_NAMES.has(name)
},
+ /**
+ * Check whether the given name is a well-known MathML element or not.
+ * @param {string} name The name to check.
+ * @returns {boolean} `true` if the name is a well-known MathML element name.
+ */
+ isMathWellKnownElementName(name) {
+ return MATH_ELEMENT_NAMES.has(name)
+ },
+
/**
* Check whether the given name is a void element name or not.
* @param {string} name The name to check.
@@ -3121,7 +3133,7 @@ function getWithDefaultsProps(node) {
for (const prop of param.properties) {
if (prop.type !== 'Property') {
- return {}
+ continue
}
const name = getStaticPropertyName(prop)
if (name != null) {
diff --git a/lib/utils/math-elements.json b/lib/utils/math-elements.json
new file mode 100644
index 000000000..46ac91ac5
--- /dev/null
+++ b/lib/utils/math-elements.json
@@ -0,0 +1,34 @@
+[
+ "math",
+ "maction",
+ "annotation",
+ "annotation-xml",
+ "menclose",
+ "merror",
+ "mfenced",
+ "mfrac",
+ "mi",
+ "mmultiscripts",
+ "mn",
+ "mo",
+ "mover",
+ "mpadded",
+ "mphantom",
+ "mprescripts",
+ "mroot",
+ "mrow",
+ "ms",
+ "semantics",
+ "mspace",
+ "msqrt",
+ "mstyle",
+ "msub",
+ "msup",
+ "msubsup",
+ "mtable",
+ "mtd",
+ "mtext",
+ "mtr",
+ "munder",
+ "munderover"
+]
diff --git a/package.json b/package.json
index ee2e37c71..b57a57e83 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "eslint-plugin-vue",
- "version": "9.25.0",
+ "version": "9.26.0",
"description": "Official ESLint plugin for Vue.js",
"main": "lib/index.js",
"scripts": {
diff --git a/tests/lib/rules/require-default-prop.js b/tests/lib/rules/require-default-prop.js
index 97aea4919..834f319aa 100644
--- a/tests/lib/rules/require-default-prop.js
+++ b/tests/lib/rules/require-default-prop.js
@@ -329,6 +329,28 @@ ruleTester.run('require-default-prop', rule, {
...languageOptions,
parserOptions: { parser: require.resolve('@typescript-eslint/parser') }
}
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+ `,
+ languageOptions: {
+ parser: require('vue-eslint-parser'),
+ ...languageOptions,
+ parserOptions: { parser: require.resolve('@typescript-eslint/parser') }
+ }
}
],
@@ -544,6 +566,33 @@ ruleTester.run('require-default-prop', rule, {
...languageOptions
}
},
+ {
+ filename: 'test.vue',
+ code: `
+
+ `,
+ errors: [
+ {
+ message: "Prop 'bar' requires default value to be set.",
+ line: 8
+ }
+ ],
+ languageOptions: {
+ parser: require('vue-eslint-parser'),
+ ...languageOptions,
+ parserOptions: { parser: require.resolve('@typescript-eslint/parser') }
+ }
+ },
...(semver.lt(
require('@typescript-eslint/parser/package.json').version,
'4.0.0'
diff --git a/tests/lib/rules/require-typed-ref.js b/tests/lib/rules/require-typed-ref.js
index 6e8797943..5b18bcb3c 100644
--- a/tests/lib/rules/require-typed-ref.js
+++ b/tests/lib/rules/require-typed-ref.js
@@ -86,6 +86,20 @@ tester.run('require-typed-ref', rule, {
`,
languageOptions: { parser: require('vue-eslint-parser') }
},
+ {
+ filename: 'test.vue',
+ code: `
+
+ `,
+ languageOptions: { parser: require('vue-eslint-parser') }
+ },
{
filename: 'test.js',
code: `
@@ -217,6 +231,30 @@ tester.run('require-typed-ref', rule, {
],
languageOptions: { parser: require('vue-eslint-parser') }
},
+ {
+ filename: 'test.vue',
+ code: `
+
+ }
+ `,
+ errors: [
+ {
+ messageId: 'noType',
+ line: 6,
+ column: 29,
+ endLine: 6,
+ endColumn: 34
+ }
+ ],
+ languageOptions: { parser: require('vue-eslint-parser') }
+ },
{
filename: 'test.ts',
code: `
diff --git a/tools/update-vue3-export-names.js b/tools/update-vue3-export-names.js
index e86d77c93..37e07e03d 100644
--- a/tools/update-vue3-export-names.js
+++ b/tools/update-vue3-export-names.js
@@ -158,6 +158,7 @@ function httpGet(url) {
baseUrl.pathname = redirectUrl
redirectUrl = String(baseUrl)
}
+ res.destroy()
resolve(httpGet(redirectUrl))
return
}