diff --git a/.github/workflows/check-for-resources-update.yml b/.github/workflows/check-for-resources-update.yml
new file mode 100644
index 000000000..f95a8aa82
--- /dev/null
+++ b/.github/workflows/check-for-resources-update.yml
@@ -0,0 +1,30 @@
+name: Check for utils resources update
+on:
+ workflow_dispatch: null
+ schedule:
+ - cron: 0 0 * * 0 # At 00:00 on Sunday, see https://crontab.guru/#0_0_*_*_0
+
+permissions:
+ contents: write
+ pull-requests: write
+
+jobs:
+ check-for-resources-update:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ - name: Install Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: 18
+ - name: Install Packages
+ run: npm install
+ - name: Update
+ run: npm run update-resources
+ - uses: peter-evans/create-pull-request@v7
+ with:
+ commit-message: Updates resources with latest
+ branch: update-unicode-alias
+ branch-suffix: timestamp
+ title: Updates resources with latest
diff --git a/lib/utils/deprecated-html-elements.json b/lib/utils/deprecated-html-elements.json
index 1d9d67968..63a3f7162 100644
--- a/lib/utils/deprecated-html-elements.json
+++ b/lib/utils/deprecated-html-elements.json
@@ -6,14 +6,10 @@
"big",
"blink",
"center",
- "command",
- "content",
"dir",
- "element",
"font",
"frame",
"frameset",
- "image",
"isindex",
"keygen",
"listing",
@@ -24,8 +20,10 @@
"nobr",
"noembed",
"noframes",
+ "param",
"plaintext",
- "shadow",
+ "rb",
+ "rtc",
"spacer",
"strike",
"tt",
diff --git a/lib/utils/html-elements.json b/lib/utils/html-elements.json
index 6911e3482..829b6f841 100644
--- a/lib/utils/html-elements.json
+++ b/lib/utils/html-elements.json
@@ -1,120 +1,116 @@
[
- "html",
- "body",
- "base",
- "head",
- "link",
- "meta",
- "style",
- "title",
+ "a",
+ "abbr",
"address",
+ "area",
"article",
"aside",
+ "audio",
+ "b",
+ "base",
+ "bdi",
+ "bdo",
+ "blockquote",
+ "body",
+ "br",
+ "button",
+ "canvas",
+ "caption",
+ "cite",
+ "code",
+ "col",
+ "colgroup",
+ "data",
+ "datalist",
+ "dd",
+ "del",
+ "details",
+ "dfn",
+ "dialog",
+ "div",
+ "dl",
+ "dt",
+ "em",
+ "embed",
+ "fencedframe",
+ "fieldset",
+ "figcaption",
+ "figure",
"footer",
- "header",
+ "form",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
+ "head",
+ "header",
"hgroup",
- "nav",
- "section",
- "div",
- "dd",
- "dl",
- "dt",
- "figcaption",
- "figure",
"hr",
+ "html",
+ "i",
+ "iframe",
"img",
+ "input",
+ "ins",
+ "kbd",
+ "label",
+ "legend",
"li",
+ "link",
"main",
+ "map",
+ "mark",
+ "menu",
+ "meta",
+ "meter",
+ "nav",
+ "noscript",
+ "object",
"ol",
+ "optgroup",
+ "option",
+ "output",
"p",
+ "picture",
+ "portal",
"pre",
- "ul",
- "a",
- "b",
- "abbr",
- "bdi",
- "bdo",
- "br",
- "cite",
- "code",
- "data",
- "dfn",
- "em",
- "i",
- "kbd",
- "mark",
+ "progress",
"q",
"rp",
"rt",
- "rtc",
"ruby",
"s",
"samp",
+ "script",
+ "search",
+ "section",
+ "select",
+ "slot",
"small",
+ "source",
"span",
"strong",
+ "style",
"sub",
+ "summary",
"sup",
- "time",
- "u",
- "var",
- "wbr",
- "area",
- "audio",
- "map",
- "track",
- "video",
- "embed",
- "object",
- "param",
- "source",
- "canvas",
- "script",
- "noscript",
- "del",
- "ins",
- "caption",
- "col",
- "colgroup",
"table",
- "thead",
"tbody",
- "tfoot",
"td",
+ "template",
+ "textarea",
+ "tfoot",
"th",
+ "thead",
+ "time",
+ "title",
"tr",
- "button",
- "datalist",
- "fieldset",
- "form",
- "input",
- "label",
- "legend",
- "meter",
- "optgroup",
- "option",
- "output",
- "progress",
- "select",
- "textarea",
- "details",
- "dialog",
- "menu",
- "menuitem",
- "summary",
- "content",
- "element",
- "shadow",
- "template",
- "slot",
- "blockquote",
- "iframe",
- "noframes",
- "picture"
+ "track",
+ "u",
+ "ul",
+ "var",
+ "video",
+ "wbr"
]
diff --git a/lib/utils/index.js b/lib/utils/index.js
index 167edf208..8d0dfa80d 100644
--- a/lib/utils/index.js
+++ b/lib/utils/index.js
@@ -1581,7 +1581,7 @@ module.exports = {
* Get the Vue component definition type from given node
* Vue.component('xxx', {}) || component('xxx', {})
* @param {ObjectExpression} node Node to check
- * @returns {'component' | 'mixin' | 'extend' | 'createApp' | 'defineComponent' | null}
+ * @returns {'component' | 'mixin' | 'extend' | 'createApp' | 'defineComponent' | 'defineNuxtComponent' | null}
*/
getVueComponentDefinitionType,
/**
@@ -2755,7 +2755,7 @@ function isVueComponentFile(node, path) {
* Get the Vue component definition type from given node
* Vue.component('xxx', {}) || component('xxx', {})
* @param {ObjectExpression} node Node to check
- * @returns {'component' | 'mixin' | 'extend' | 'createApp' | 'defineComponent' | null}
+ * @returns {'component' | 'mixin' | 'extend' | 'createApp' | 'defineComponent' | 'defineNuxtComponent' | null}
*/
function getVueComponentDefinitionType(node) {
const parent = getParent(node)
@@ -2811,6 +2811,12 @@ function getVueComponentDefinitionType(node) {
const isDestructedVueComponent = isObjectArgument(parent)
return isDestructedVueComponent ? 'defineComponent' : null
}
+ if (callee.name === 'defineNuxtComponent') {
+ // for Nuxt 3.x
+ // defineNuxtComponent({})
+ const isDestructedVueComponent = isObjectArgument(parent)
+ return isDestructedVueComponent ? 'defineNuxtComponent' : null
+ }
}
}
@@ -2955,7 +2961,9 @@ function isSFCObject(context, node) {
}
const { callee } = parent
if (
- (callee.type === 'Identifier' && callee.name === 'defineComponent') ||
+ (callee.type === 'Identifier' &&
+ (callee.name === 'defineComponent' ||
+ callee.name === 'defineNuxtComponent')) ||
(callee.type === 'MemberExpression' &&
callee.object.type === 'Identifier' &&
callee.object.name === 'Vue' &&
diff --git a/lib/utils/svg-elements.json b/lib/utils/svg-elements.json
index 7e5ba6052..f214aad24 100644
--- a/lib/utils/svg-elements.json
+++ b/lib/utils/svg-elements.json
@@ -3,13 +3,10 @@
"animate",
"animateMotion",
"animateTransform",
- "audio",
- "canvas",
"circle",
"clipPath",
"defs",
"desc",
- "discard",
"ellipse",
"feBlend",
"feColorMatrix",
@@ -39,7 +36,6 @@
"filter",
"foreignObject",
"g",
- "iframe",
"image",
"line",
"linearGradient",
@@ -64,8 +60,6 @@
"textPath",
"title",
"tspan",
- "unknown",
"use",
- "video",
"view"
]
diff --git a/package.json b/package.json
index 503f711f1..307cdc0aa 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
"preversion": "npm test && git add .",
"version": "env-cmd -e version npm run update && npm run lint -- --fix && git add .",
"update": "node ./tools/update.js",
+ "update-resources": "node ./tools/update-resources.js",
"docs:watch": "vitepress dev docs",
"predocs:build": "npm run update",
"docs:build": "vitepress build docs"
@@ -90,6 +91,7 @@
"eslint-plugin-vue": "file:.",
"espree": "^9.6.1",
"events": "^3.3.0",
+ "jsdom": "^22.0.0",
"markdownlint-cli": "^0.42.0",
"mocha": "^10.7.3",
"nyc": "^17.1.0",
diff --git a/tests/lib/rules/no-reserved-component-names.js b/tests/lib/rules/no-reserved-component-names.js
index 231e1f98d..809d35103 100644
--- a/tests/lib/rules/no-reserved-component-names.js
+++ b/tests/lib/rules/no-reserved-component-names.js
@@ -247,12 +247,6 @@ const invalidElements = [
'menuitem',
'summary',
'Summary',
- 'content',
- 'Content',
- 'element',
- 'Element',
- 'shadow',
- 'Shadow',
'template',
'Template',
'slot',
@@ -278,8 +272,6 @@ const invalidElements = [
'Defs',
'desc',
'Desc',
- 'discard',
- 'Discard',
'ellipse',
'Ellipse',
'feBlend',
@@ -351,8 +343,6 @@ const invalidElements = [
'textPath',
'tspan',
'Tspan',
- 'unknown',
- 'Unknown',
'use',
'Use',
'view',
@@ -373,8 +363,6 @@ const invalidElements = [
'Blink',
'center',
'Center',
- 'command',
- 'Command',
'dir',
'Dir',
'font',
diff --git a/tests/lib/rules/no-undef-components.js b/tests/lib/rules/no-undef-components.js
index e9992e39d..37a3bec68 100644
--- a/tests/lib/rules/no-undef-components.js
+++ b/tests/lib/rules/no-undef-components.js
@@ -269,6 +269,21 @@ tester.run('no-undef-components', rule, {
}
]
},
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+
+ `
+ },
{
filename: 'test.vue',
code: `
diff --git a/tests/lib/rules/order-in-components.js b/tests/lib/rules/order-in-components.js
index 2cbe721c5..130a319b0 100644
--- a/tests/lib/rules/order-in-components.js
+++ b/tests/lib/rules/order-in-components.js
@@ -234,6 +234,84 @@ ruleTester.run('order-in-components', rule, {
}
]
},
+ {
+ filename: 'test.vue',
+ code: `
+ import { defineComponent } from 'vue'
+ export default defineComponent({
+ name: 'app',
+ data () {
+ return {
+ msg: 'Welcome to Your Vue.js App'
+ }
+ },
+ props: {
+ propA: Number,
+ },
+ })
+ `,
+ output: `
+ import { defineComponent } from 'vue'
+ export default defineComponent({
+ name: 'app',
+ props: {
+ propA: Number,
+ },
+ data () {
+ return {
+ msg: 'Welcome to Your Vue.js App'
+ }
+ },
+ })
+ `,
+ languageOptions,
+ errors: [
+ {
+ message:
+ 'The "props" property should be above the "data" property on line 5.',
+ line: 10
+ }
+ ]
+ },
+ {
+ filename: 'test.vue',
+ code: `
+ import { defineNuxtComponent } from '#app'
+ export default defineNuxtComponent({
+ name: 'app',
+ data () {
+ return {
+ msg: 'Welcome to Your Vue.js App'
+ }
+ },
+ props: {
+ propA: Number,
+ },
+ })
+ `,
+ output: `
+ import { defineNuxtComponent } from '#app'
+ export default defineNuxtComponent({
+ name: 'app',
+ props: {
+ propA: Number,
+ },
+ data () {
+ return {
+ msg: 'Welcome to Your Vue.js App'
+ }
+ },
+ })
+ `,
+ languageOptions,
+ errors: [
+ {
+ message:
+ 'The "props" property should be above the "data" property on line 5.',
+ line: 10
+ }
+ ]
+ },
{
filename: 'test.jsx',
code: `
diff --git a/tests/lib/utils/vue-component.js b/tests/lib/utils/vue-component.js
index 8970672ad..12fcd904f 100644
--- a/tests/lib/utils/vue-component.js
+++ b/tests/lib/utils/vue-component.js
@@ -325,6 +325,12 @@ function invalidTests(ext) {
code: `export default defineComponent({})`,
languageOptions,
errors: [makeError(1)]
+ },
+ {
+ filename: `test.${ext}`,
+ code: `export default defineNuxtComponent({})`,
+ languageOptions,
+ errors: [makeError(1)]
}
]
}
diff --git a/tools/lib/http.js b/tools/lib/http.js
new file mode 100644
index 000000000..27ff970f4
--- /dev/null
+++ b/tools/lib/http.js
@@ -0,0 +1,6 @@
+module.exports = {
+ httpGet
+}
+function httpGet(url) {
+ return fetch(url).then((res) => res.text())
+}
diff --git a/tools/update-html-resources.js b/tools/update-html-resources.js
new file mode 100644
index 000000000..fcbdacbb0
--- /dev/null
+++ b/tools/update-html-resources.js
@@ -0,0 +1,105 @@
+'use strict'
+
+const fs = require('fs')
+const jsdom = require('jsdom')
+const { httpGet } = require('./lib/http')
+
+main()
+
+async function main() {
+ const [bcdJson, obsoleteHtml] = await Promise.all([
+ httpGet('https://unpkg.com/@mdn/browser-compat-data/data.json'),
+ httpGet('https://html.spec.whatwg.org/multipage/obsolete.html')
+ ])
+ const bcd = JSON.parse(bcdJson)
+
+ updateDeprecatedHTMLElements()
+ updateHTMLElements()
+ updateSVGElements()
+
+ // ------------------------------------------------------------------------------
+ // Update deprecated-html-elements.json
+ // ------------------------------------------------------------------------------
+ function updateDeprecatedHTMLElements() {
+ const DEPRECATED_HTML_ELEMENTS_PATH = require.resolve(
+ '../lib/utils/deprecated-html-elements.json'
+ )
+ const elements = new Set()
+
+ const domDl = jsdom.JSDOM.fragment(obsoleteHtml).querySelector(
+ '[id="non-conforming-features"] ~ dl'
+ )
+ for (const code of domDl.querySelectorAll('dt code')) {
+ const name = code.textContent.trim()
+ if (name) elements.add(name)
+ }
+
+ if (elements.size === 0) {
+ throw new Error('No deprecated HTML elements found')
+ }
+
+ fs.writeFileSync(
+ DEPRECATED_HTML_ELEMENTS_PATH,
+ `${JSON.stringify([...elements].sort(), null, 2)}\n`,
+ 'utf8'
+ )
+ }
+
+ // ------------------------------------------------------------------------------
+ // Update html-elements.json
+ // ------------------------------------------------------------------------------
+ function updateHTMLElements() {
+ const HTML_ELEMENTS_PATH = require.resolve(
+ '../lib/utils/html-elements.json'
+ )
+ const elements = new Set()
+ const deprecatedHtmlElements = new Set(
+ require('../lib/utils/deprecated-html-elements.json')
+ )
+
+ for (const [name, element] of Object.entries(bcd.html.elements)) {
+ if (deprecatedHtmlElements.has(name)) {
+ continue
+ }
+ if (element.__compat.status.deprecated) {
+ continue
+ }
+ elements.add(name)
+ }
+
+ if (elements.size === 0) {
+ throw new Error('No HTML elements found')
+ }
+
+ fs.writeFileSync(
+ HTML_ELEMENTS_PATH,
+ `${JSON.stringify([...elements].sort(), null, 2)}\n`,
+ 'utf8'
+ )
+ }
+
+ // ------------------------------------------------------------------------------
+ // Update svg-elements.json
+ // ------------------------------------------------------------------------------
+ function updateSVGElements() {
+ const SVG_ELEMENTS_PATH = require.resolve('../lib/utils/svg-elements.json')
+ const elements = new Set()
+
+ for (const [name, element] of Object.entries(bcd.svg.elements)) {
+ if (element.__compat.status.deprecated) {
+ continue
+ }
+ elements.add(name)
+ }
+
+ if (elements.size === 0) {
+ throw new Error('No SVG elements found')
+ }
+
+ fs.writeFileSync(
+ SVG_ELEMENTS_PATH,
+ `${JSON.stringify([...elements].sort(), null, 2)}\n`,
+ 'utf8'
+ )
+ }
+}
diff --git a/tools/update-resources.js b/tools/update-resources.js
new file mode 100644
index 000000000..a157c61ef
--- /dev/null
+++ b/tools/update-resources.js
@@ -0,0 +1,4 @@
+'use strict'
+
+require('./update-vue3-export-names')
+require('./update-html-resources')
diff --git a/tools/update-vue3-export-names.js b/tools/update-vue3-export-names.js
index 37e07e03d..0dabecb3a 100644
--- a/tools/update-vue3-export-names.js
+++ b/tools/update-vue3-export-names.js
@@ -6,9 +6,8 @@
const fs = require('fs')
const path = require('path')
-const https = require('https')
-const { URL } = require('url')
const tsParser = require('@typescript-eslint/parser')
+const { httpGet } = require('./lib/http')
main()
@@ -144,33 +143,3 @@ async function resolveTypeContents(m) {
}
return await httpGet(`https://unpkg.com/${m}/${typesPath}`)
}
-
-function httpGet(url) {
- return new Promise((resolve, reject) => {
- let result = ''
- https
- .get(url, (res) => {
- if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400) {
- // redirect
- let redirectUrl = res.headers.location
- if (!redirectUrl.startsWith('http')) {
- const baseUrl = new URL(url)
- baseUrl.pathname = redirectUrl
- redirectUrl = String(baseUrl)
- }
- res.destroy()
- resolve(httpGet(redirectUrl))
- return
- }
- res.setEncoding('utf8')
- res.on('data', (chunk) => {
- result += String(chunk)
- })
- res.on('end', () => {
- resolve(result)
- })
- res.on('error', reject)
- })
- .on('error', reject)
- })
-}
diff --git a/tools/update.js b/tools/update.js
index de792d507..64da1be1b 100644
--- a/tools/update.js
+++ b/tools/update.js
@@ -11,7 +11,3 @@ require('./update-lib-flat-configs')
require('./update-lib-index')
require('./update-docs')
require('./update-docs-rules-index')
-
-if (process.env.IN_VERSION_SCRIPT) {
- require('./update-vue3-export-names')
-}