diff --git a/.eslintrc.js b/.eslintrc.js index f461e5c..5042164 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -6,10 +6,11 @@ module.exports = { env: { node: true, }, - extends: ['plugin:github/recommended'], + extends: ['plugin:github/recommended', 'plugin:eslint-plugin/recommended'], rules: { 'i18n-text/no-en': 'off', 'import/no-commonjs': 'off', + 'eslint-plugin/require-meta-docs-url': 'error', }, overrides: [ { diff --git a/README.md b/README.md index 2c2cfb8..9198359 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ -# eslint-plugin-custom-elements +# eslint-plugin-custom-elements (archived) + +> [!WARNING]\ +> This project has been merged with [eslint-plugin-wc](https://github.com/43081j/eslint-plugin-wc). Please head there for updates and maintenance. This is an ESLint Plugin to help provide best practices for writing Custom Elements aka Web Components. It provides a set of custom rules which can be enforced for files that declare classes that extend from HTMLElement. diff --git a/lib/rules/define-tag-after-class-definition.js b/lib/rules/define-tag-after-class-definition.js index 28e83f4..d3879f6 100644 --- a/lib/rules/define-tag-after-class-definition.js +++ b/lib/rules/define-tag-after-class-definition.js @@ -4,8 +4,8 @@ module.exports = { meta: { type: 'suggestion', docs: {description: '', url: require('../url')(module)}, + schema: [], }, - schema: [], create(context) { const classes = ClassRefTracker.customElements(context) return { diff --git a/lib/rules/expose-class-on-global.js b/lib/rules/expose-class-on-global.js index ca76cfb..bbec1e0 100644 --- a/lib/rules/expose-class-on-global.js +++ b/lib/rules/expose-class-on-global.js @@ -4,8 +4,8 @@ module.exports = { meta: { type: 'suggestion', docs: {description: '', url: require('../url')(module)}, + schema: [], }, - schema: [], create(context) { const classes = ClassRefTracker.customElements(context) return { diff --git a/lib/rules/extends-correct-class.js b/lib/rules/extends-correct-class.js index 79735b8..c59b080 100644 --- a/lib/rules/extends-correct-class.js +++ b/lib/rules/extends-correct-class.js @@ -33,15 +33,15 @@ module.exports = { meta: { type: 'problem', docs: {description: '', url: require('../url')(module)}, - }, - schema: [ - { - type: 'object', - properties: { - allowedSuperNames: {type: 'array', items: {type: 'string'}}, + schema: [ + { + type: 'object', + properties: { + allowedSuperNames: {type: 'array', items: {type: 'string'}}, + }, }, - }, - ], + ], + }, create(context) { const classes = new ClassRefTracker(context) return { diff --git a/lib/rules/file-name-matches-element.js b/lib/rules/file-name-matches-element.js index c6b897e..98b1de6 100644 --- a/lib/rules/file-name-matches-element.js +++ b/lib/rules/file-name-matches-element.js @@ -19,31 +19,31 @@ module.exports = { meta: { type: 'suggestion', docs: {description: '', url: require('../url')(module)}, - }, - schema: [ - { - type: 'object', - properties: { - transform: { - oneOf: [ - {enum: ['none', 'snake', 'kebab', 'pascal']}, - { - type: 'array', - items: {enum: ['none', 'snake', 'kebab', 'pascal']}, - minItems: 1, - maxItems: 4, - }, - ], - }, - suffix: { - onfOf: [{type: 'string'}, {type: 'array', items: {type: 'string'}}], - }, - matchDirectory: { - type: 'boolean', + schema: [ + { + type: 'object', + properties: { + transform: { + oneOf: [ + {enum: ['none', 'snake', 'kebab', 'pascal']}, + { + type: 'array', + items: {enum: ['none', 'snake', 'kebab', 'pascal']}, + minItems: 1, + maxItems: 4, + }, + ], + }, + suffix: { + onfOf: [{type: 'string'}, {type: 'array', items: {type: 'string'}}], + }, + matchDirectory: { + type: 'boolean', + }, }, }, - }, - ], + ], + }, create(context) { if (!hasFileName(context)) return {} return { diff --git a/lib/rules/no-constructor.js b/lib/rules/no-constructor.js index 1c7e349..476c377 100644 --- a/lib/rules/no-constructor.js +++ b/lib/rules/no-constructor.js @@ -3,8 +3,8 @@ module.exports = { meta: { type: 'suggestion', docs: {description: '', url: require('../url')(module)}, + schema: [], }, - schema: [], create(context) { return { [`${s.HTMLElementClass} MethodDefinition[key.name="constructor"]`](node) { diff --git a/lib/rules/no-customized-built-in-elements.js b/lib/rules/no-customized-built-in-elements.js index 39e2d09..c3d7dc4 100644 --- a/lib/rules/no-customized-built-in-elements.js +++ b/lib/rules/no-customized-built-in-elements.js @@ -5,8 +5,8 @@ module.exports = { meta: { type: 'problem', docs: {description: '', url: require('../url')(module)}, + schema: [], }, - schema: [], create(context) { return { [s.HTMLElementClass](node) { diff --git a/lib/rules/no-dom-traversal-in-attributechangedcallback.js b/lib/rules/no-dom-traversal-in-attributechangedcallback.js index 1f1e606..4475d3b 100644 --- a/lib/rules/no-dom-traversal-in-attributechangedcallback.js +++ b/lib/rules/no-dom-traversal-in-attributechangedcallback.js @@ -4,8 +4,8 @@ module.exports = { meta: { type: 'suggestion', docs: {description: '', url: require('../url')(module)}, + schema: [], }, - schema: [], create(context) { return { [`${s.HTMLElementClass} MethodDefinition[key.name="attributeChangedCallback"] MemberExpression`](node) { diff --git a/lib/rules/no-dom-traversal-in-connectedcallback.js b/lib/rules/no-dom-traversal-in-connectedcallback.js index 19dafc3..df0d8ed 100644 --- a/lib/rules/no-dom-traversal-in-connectedcallback.js +++ b/lib/rules/no-dom-traversal-in-connectedcallback.js @@ -4,8 +4,8 @@ module.exports = { meta: { type: 'suggestion', docs: {description: '', url: require('../url')(module)}, + schema: [], }, - schema: [], create(context) { return { [`${s.HTMLElementClass} MethodDefinition[key.name="connectedCallback"] MemberExpression`](node) { diff --git a/lib/rules/no-exports-with-element.js b/lib/rules/no-exports-with-element.js index e1549b0..81b6291 100644 --- a/lib/rules/no-exports-with-element.js +++ b/lib/rules/no-exports-with-element.js @@ -5,8 +5,8 @@ module.exports = { meta: { type: 'layout', docs: {description: '', url: require('../url')(module)}, + schema: [], }, - schema: [], create(context) { const classes = ClassRefTracker.customElements(context) const eventClasses = ClassRefTracker.customEvents(context) diff --git a/lib/rules/no-method-prefixed-with-on.js b/lib/rules/no-method-prefixed-with-on.js index 73bd859..881a014 100644 --- a/lib/rules/no-method-prefixed-with-on.js +++ b/lib/rules/no-method-prefixed-with-on.js @@ -4,8 +4,8 @@ module.exports = { meta: { type: 'suggestion', docs: {description: '', url: require('../url')(module)}, + schema: [], }, - schema: [], create(context) { return { [`${s.HTMLElementClass} MethodDefinition[key.name=/^on.*$/i]`](node) { diff --git a/lib/rules/no-unchecked-define.js b/lib/rules/no-unchecked-define.js index 8e95905..d36a995 100644 --- a/lib/rules/no-unchecked-define.js +++ b/lib/rules/no-unchecked-define.js @@ -6,8 +6,8 @@ module.exports = { meta: { type: 'layout', docs: {description: '', url: require('../url')(module)}, + schema: [], }, - schema: [], create(context) { definedCustomElements = new Map() return { diff --git a/lib/rules/one-element-per-file.js b/lib/rules/one-element-per-file.js index 8d19c2f..7bfe1ae 100644 --- a/lib/rules/one-element-per-file.js +++ b/lib/rules/one-element-per-file.js @@ -3,8 +3,8 @@ module.exports = { meta: { type: 'layout', docs: {description: '', url: require('../url')(module)}, + schema: [], }, - schema: [], create(context) { let classCount = 0 return { diff --git a/lib/rules/tag-name-matches-class.js b/lib/rules/tag-name-matches-class.js index 41f8480..12f0bf8 100644 --- a/lib/rules/tag-name-matches-class.js +++ b/lib/rules/tag-name-matches-class.js @@ -19,20 +19,20 @@ module.exports = { meta: { type: 'suggestion', docs: {description: '', url: require('../url')(module)}, - }, - schema: [ - { - type: 'object', - properties: { - suffix: { - onfOf: [{type: 'string'}, {type: 'array', items: {type: 'string'}}], - }, - prefix: { - onfOf: [{type: 'string'}, {type: 'array', items: {type: 'string'}}], + schema: [ + { + type: 'object', + properties: { + suffix: { + onfOf: [{type: 'string'}, {type: 'array', items: {type: 'string'}}], + }, + prefix: { + onfOf: [{type: 'string'}, {type: 'array', items: {type: 'string'}}], + }, }, }, - }, - ], + ], + }, create(context) { return { [s.customElements.define](node) { diff --git a/lib/rules/valid-tag-name.js b/lib/rules/valid-tag-name.js index 4aaa912..1c2e2a0 100644 --- a/lib/rules/valid-tag-name.js +++ b/lib/rules/valid-tag-name.js @@ -4,22 +4,22 @@ module.exports = { meta: { type: 'problem', docs: {description: '', url: require('../url')(module)}, - }, - schema: [ - { - type: 'object', - properties: { - disallowNamespaces: {type: 'boolean'}, - onlyAlphanum: {type: 'boolean'}, - prefix: { - oneOf: [{type: 'string'}, {type: 'array', items: {type: 'string'}}], - }, - suffix: { - oneOf: [{type: 'string'}, {type: 'array', items: {type: 'string'}}], + schema: [ + { + type: 'object', + properties: { + disallowNamespaces: {type: 'boolean'}, + onlyAlphanum: {type: 'boolean'}, + prefix: { + oneOf: [{type: 'string'}, {type: 'array', items: {type: 'string'}}], + }, + suffix: { + oneOf: [{type: 'string'}, {type: 'array', items: {type: 'string'}}], + }, }, }, - }, - ], + ], + }, create(context) { return { [s.customElements.define](node) { diff --git a/package-lock.json b/package-lock.json index 26f5080..49f0d3c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "eslint": "^8.28.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-eslint-plugin": "^5.0.7", "eslint-plugin-github": "^4.4.1", "eslint-plugin-import": "^2.26.0", "eslint-plugin-prettier": "^4.2.1", @@ -1089,6 +1090,31 @@ "node": ">=0.8.0" } }, + "node_modules/eslint-plugin-eslint-plugin": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-plugin/-/eslint-plugin-eslint-plugin-5.0.7.tgz", + "integrity": "sha512-hcz4Bze1ECwv3Q/Bi/ZMZZNiuvI2YclNuxjnczkblQ0skrlPhdO83rSM7felf5n+7ZJOZi4GS8y8gNiRtvI0hA==", + "dev": true, + "dependencies": { + "eslint-utils": "^3.0.0", + "estraverse": "^5.3.0" + }, + "engines": { + "node": "^14.17.0 || ^16.0.0 || >= 18.0.0" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-eslint-plugin/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/eslint-plugin-filenames": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/eslint-plugin-filenames/-/eslint-plugin-filenames-1.3.2.tgz", @@ -2157,9 +2183,9 @@ "dev": true }, "node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "dependencies": { "minimist": "^1.2.0" @@ -3219,9 +3245,9 @@ } }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", + "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -4103,6 +4129,24 @@ } } }, + "eslint-plugin-eslint-plugin": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-plugin/-/eslint-plugin-eslint-plugin-5.0.7.tgz", + "integrity": "sha512-hcz4Bze1ECwv3Q/Bi/ZMZZNiuvI2YclNuxjnczkblQ0skrlPhdO83rSM7felf5n+7ZJOZi4GS8y8gNiRtvI0hA==", + "dev": true, + "requires": { + "eslint-utils": "^3.0.0", + "estraverse": "^5.3.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, "eslint-plugin-filenames": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/eslint-plugin-filenames/-/eslint-plugin-filenames-1.3.2.tgz", @@ -4843,9 +4887,9 @@ "dev": true }, "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "requires": { "minimist": "^1.2.0" @@ -5583,9 +5627,9 @@ } }, "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", + "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", "dev": true }, "workerpool": { diff --git a/package.json b/package.json index a8d9903..22bcd96 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "eslint": "^8.28.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-eslint-plugin": "^5.0.7", "eslint-plugin-github": "^4.4.1", "eslint-plugin-import": "^2.26.0", "eslint-plugin-prettier": "^4.2.1", diff --git a/test/check-rules.js b/test/check-rules.js index 164ccdd..5e3cf87 100644 --- a/test/check-rules.js +++ b/test/check-rules.js @@ -124,7 +124,7 @@ describe('documentation', () => { '## Rule Details', '👎 Examples of **incorrect** code for this rule:', '👍 Examples of **correct** code for this rule:', - config.rules?.[doc]?.schema?.length ? '### Options' : '', + config.rules?.[doc]?.meta.schema?.length ? '### Options' : '', '## When Not To Use It', '## Version', ].filter(Boolean) diff --git a/test/file-name-matches-element.js b/test/file-name-matches-element.js index 0b736f0..8f047f2 100644 --- a/test/file-name-matches-element.js +++ b/test/file-name-matches-element.js @@ -38,7 +38,6 @@ ruleTester.run('file-name-matches-element', rule, { {code, filename: 'foo_bar.js', options: [{transform: ['kebab', 'snake', 'pascal'], suffix: 'Element'}]}, {code, filename: 'foo_bar_element.js', options: [{transform: ['kebab', 'snake'], suffix: ['Element']}]}, {code, filename: 'fooBarElement.js', options: [{transform: ['kebab', 'pascal'], suffix: ['ElEmEnT']}]}, - {code, filename: 'foo_bar_element.js', options: [{transform: ['kebab', 'snake'], suffix: ['Element']}]}, {code, filename: 'bar_element.js', options: [{transform: ['kebab', 'snake'], prefix: ['Foo']}]}, {code, filename: 'bar_element.js', options: [{transform: ['kebab', 'snake'], prefix: ['fOo']}]}, { diff --git a/test/tag-name-matches-class.js b/test/tag-name-matches-class.js index 8a01a7f..21ea512 100644 --- a/test/tag-name-matches-class.js +++ b/test/tag-name-matches-class.js @@ -8,7 +8,6 @@ ruleTester.run('tag-name-matches-class', rule, { {code: "customElements.define('foo-bar-element', FooBarElement)"}, {code: "customElements.define('foo-bar', FooBar)", options: [{suffix: ['Element']}]}, {code: "customElements.define('foo-bar', FooBarElement)", options: [{suffix: ['Element']}]}, - {code: "customElements.define('foo-bar', FooBarElement)", options: [{suffix: ['Element']}]}, {code: "customElements.define('foo-bar', FooBarComponent)", options: [{suffix: 'Component'}]}, {code: "customElements.define('foo-bar', FooBarElement)", options: [{suffix: ['Element', 'Component']}]}, {code: "customElements.define('foo-bar', FooBarComponent)", options: [{suffix: ['Element', 'Component']}]}, diff --git a/test/valid-tag-name.js b/test/valid-tag-name.js index e881f70..f156d49 100644 --- a/test/valid-tag-name.js +++ b/test/valid-tag-name.js @@ -8,7 +8,6 @@ ruleTester.run('valid-tag-name', rule, { {code: 'customElements.define("foo-bar")'}, {code: "customElements.define('foo-bar')"}, {code: 'customElements.define(`foo-bar`)'}, - {code: 'customElements.define("foo-bar")'}, {code: 'customElements.define("m---···---")'}, {code: 'customElements.define("aÀ-")'}, {code: 'customElements.define("leiðinlegt-tíst")'}, @@ -104,20 +103,6 @@ ruleTester.run('valid-tag-name', rule, { }, ], }, - { - code: 'customElements.define("a-😶‍🌫️")', - options: [ - { - onlyAlphanum: true, - }, - ], - errors: [ - { - message: 'Non ASCII Custom Elements have been disallowed', - type: 'Literal', - }, - ], - }, { code: 'customElements.define("ng-element")', options: [