From c399c10a96ebcea662d8eae68dadd7eed8609099 Mon Sep 17 00:00:00 2001 From: JC Franco Date: Sun, 3 Nov 2024 22:49:57 -0800 Subject: [PATCH] refactor!: remove deprecated `ban-props-on-host`, `enforce-ref-last-prop`, `require-event-emitter-type` rules (#10679) **Related Issue:** #10398 ## Summary Remove deprecated custom ESLint rules. BREAKING CHANGE: The following deprecated rules from `@esri/eslint-plugin-calcite-components` have been removed due to changes introduced in #10310: * `ban-props-on-host` * `enforce-ref-last-prop` * `require-event-emitter-type` Developers should either remain on the current version or remove these rules from their ESLint configuration to avoid potential issues. --- .../README.md | 23 +----- .../docs/enforce-ref-last-prop.md | 19 ----- .../src/configs/base.ts | 7 +- .../src/configs/recommended.ts | 3 - .../src/rules/enforce-ref-last-prop.ts | 68 ------------------ .../src/rules/index.ts | 6 -- .../ban-props-on-host.good.tsx | 18 ----- .../ban-props-on-host.spec.ts | 29 -------- .../ban-props-on-host.wrong.tsx | 11 --- .../enforce-ref-last-prop.good.tsx | 26 ------- .../enforce-ref-last-prop.output.tsx | 70 ------------------- .../enforce-ref-last-prop.spec.ts | 48 ------------- .../enforce-ref-last-prop.wrong.tsx | 68 ------------------ .../require-event-emitter-type.good.tsx | 10 --- .../require-event-emitter-type.spec.ts | 30 -------- .../require-event-emitter-type.wrong.tsx | 13 ---- 16 files changed, 4 insertions(+), 445 deletions(-) delete mode 100644 packages/eslint-plugin-calcite-components/docs/enforce-ref-last-prop.md delete mode 100644 packages/eslint-plugin-calcite-components/src/rules/enforce-ref-last-prop.ts delete mode 100644 packages/eslint-plugin-calcite-components/tests/lib/rules/ban-props-on-host/ban-props-on-host.good.tsx delete mode 100644 packages/eslint-plugin-calcite-components/tests/lib/rules/ban-props-on-host/ban-props-on-host.spec.ts delete mode 100644 packages/eslint-plugin-calcite-components/tests/lib/rules/ban-props-on-host/ban-props-on-host.wrong.tsx delete mode 100644 packages/eslint-plugin-calcite-components/tests/lib/rules/enforce-ref-last-prop/enforce-ref-last-prop.good.tsx delete mode 100644 packages/eslint-plugin-calcite-components/tests/lib/rules/enforce-ref-last-prop/enforce-ref-last-prop.output.tsx delete mode 100644 packages/eslint-plugin-calcite-components/tests/lib/rules/enforce-ref-last-prop/enforce-ref-last-prop.spec.ts delete mode 100644 packages/eslint-plugin-calcite-components/tests/lib/rules/enforce-ref-last-prop/enforce-ref-last-prop.wrong.tsx delete mode 100644 packages/eslint-plugin-calcite-components/tests/lib/rules/require-event-emitter-type/require-event-emitter-type.good.tsx delete mode 100644 packages/eslint-plugin-calcite-components/tests/lib/rules/require-event-emitter-type/require-event-emitter-type.spec.ts delete mode 100644 packages/eslint-plugin-calcite-components/tests/lib/rules/require-event-emitter-type/require-event-emitter-type.wrong.tsx diff --git a/packages/eslint-plugin-calcite-components/README.md b/packages/eslint-plugin-calcite-components/README.md index 177088d7830..71390be35af 100644 --- a/packages/eslint-plugin-calcite-components/README.md +++ b/packages/eslint-plugin-calcite-components/README.md @@ -45,33 +45,14 @@ npm run lint This rule helps prevent usage of specific events and allows suggesting alternatives. -- [`@esri/calcite-components/ban-props-on-host`](./docs/ban-props-on-host.md) +- [`@esri/calcite-components/no-dynamic-createelement`](./docs/no-dynamic-createelement.md) -This rule catches props/attributes that should be in the encapsulated HTML structure and not on the host element. - -- [`@esri/calcite-components/enforce-ref-last-prop`](./docs/enforce-ref-last-prop.md) - -This ensures the node passed into the `ref` callback is in sync with its JSX attributes/properties when invoked. - -- [`@esri/calcite-components/require-event-emitter-type`](./docs/require-event-emitter-type.md) - -This rule helps enforce the payload type to EventEmitters to avoid misleading `any` type on the CustomEvent detail object. +This rule ensures that calls to `document.createElement()` use string literals to avoid dynamic tag creation to enhance plugin compatibility. - [`@esri/calcite-components/strict-boolean-attributes`](./docs/strict-boolean-attributes.md) This rule catches boolean props that are initialized in a way that does not conform to the HTML5 spec. -## Recommended rules - -```json -{ - "@esri/calcite-components/ban-props-on-host": "error", - "@esri/calcite-components/enforce-ref-last-prop": "error", - "@esri/calcite-components/require-event-emitter-type": "error", - "@esri/calcite-components/strict-boolean-attributes": "error" -} -``` - ## Contributing We welcome contributions to this project. See [CONTRIBUTING.md](./CONTRIBUTING.md) for an overview of contribution guidelines. diff --git a/packages/eslint-plugin-calcite-components/docs/enforce-ref-last-prop.md b/packages/eslint-plugin-calcite-components/docs/enforce-ref-last-prop.md deleted file mode 100644 index c54081ede54..00000000000 --- a/packages/eslint-plugin-calcite-components/docs/enforce-ref-last-prop.md +++ /dev/null @@ -1,19 +0,0 @@ -# enforce-ref-last-prop - -**Deprecated** This rule is deprecated and will be removed in a future release. It is no longer needed if you are using Stencil 4.14.1 or greater. - -This ensures the node passed into the `ref` callback is in sync with its JSX attributes/properties when invoked. - -Placing `ref` last helps work around a [Stencil bug](https://github.com/ionic-team/stencil/issues/4074) where the `ref` callback is invoked in the specified order and not after initializing the element with all its attributes/properties. This can cause attributes/properties to be outdated by the time the callback is invoked. - -## Config - -No config is needed - -## Usage - -```json -{ "@esri/calcite-components/enforce-ref-last-prop": "error" } -``` - -> Fix included diff --git a/packages/eslint-plugin-calcite-components/src/configs/base.ts b/packages/eslint-plugin-calcite-components/src/configs/base.ts index 89ff13683e7..7ec0ebc14ce 100644 --- a/packages/eslint-plugin-calcite-components/src/configs/base.ts +++ b/packages/eslint-plugin-calcite-components/src/configs/base.ts @@ -16,11 +16,8 @@ export default { }, plugins: ["@esri/calcite-components"], rules: { - "@esri/calcite-components/ban-props-on-host": 2, - "@esri/calcite-components/enforce-ref-last-prop": 2, - "@esri/calcite-components/no-dynamic-createelement": 2, - "@esri/calcite-components/require-event-emitter-type": 2, - "@esri/calcite-components/strict-boolean-attributes": 2, + "@esri/calcite-components/no-dynamic-createelement": 1, + "@esri/calcite-components/strict-boolean-attributes": 1, }, }, ], diff --git a/packages/eslint-plugin-calcite-components/src/configs/recommended.ts b/packages/eslint-plugin-calcite-components/src/configs/recommended.ts index 65364ff1bea..7969dd0a113 100644 --- a/packages/eslint-plugin-calcite-components/src/configs/recommended.ts +++ b/packages/eslint-plugin-calcite-components/src/configs/recommended.ts @@ -1,9 +1,6 @@ export default { extends: ["plugin:@esri/calcite-components/base"], rules: { - "@esri/calcite-components/ban-props-on-host": 2, - "@esri/calcite-components/enforce-ref-last-prop": 2, - "@esri/calcite-components/require-event-emitter-type": 2, "@esri/calcite-components/strict-boolean-attributes": 2, }, }; diff --git a/packages/eslint-plugin-calcite-components/src/rules/enforce-ref-last-prop.ts b/packages/eslint-plugin-calcite-components/src/rules/enforce-ref-last-prop.ts deleted file mode 100644 index 3d6776b2dd2..00000000000 --- a/packages/eslint-plugin-calcite-components/src/rules/enforce-ref-last-prop.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Rule } from "eslint"; -import type { JSXAttribute, JSXOpeningElement, JSXSpreadAttribute } from "@babel/types"; - -const rule: Rule.RuleModule = { - meta: { - deprecated: true, - docs: { - description: `This ensures the node passed into the ref callback is in sync with its JSX attributes/properties when invoked.`, - recommended: true, - }, - fixable: "code", - schema: [], - type: "problem", - }, - - create(context): Rule.RuleListener { - return { - JSXIdentifier(node) { - const openingElement = node.parent as JSXOpeningElement; - if (openingElement.type === "JSXOpeningElement") { - const attributes = openingElement.attributes - .map((attr) => { - if (attr.type === "JSXAttribute" && attr.name?.type === "JSXIdentifier") { - return attr; - } - }) - .filter(Boolean); - - const refAttribute = attributes.find( - (attr: JSXAttribute | JSXSpreadAttribute) => - attr.type === "JSXAttribute" && attr.name?.type === "JSXIdentifier" && attr.name.name === "ref", - ); - - if (refAttribute) { - const { sourceCode } = context; - const refAttrText = sourceCode.getText(refAttribute as typeof node); - const otherAttrs = attributes.filter((attr) => attr !== refAttribute); - const indentation = new Array(refAttribute.loc.start.column).fill(" ").join(""); - const tokenBeforeRefAttr = sourceCode.getTokenBefore(refAttribute as typeof node); - const eslintDisableComments = sourceCode - .getCommentsBefore(refAttribute as typeof node) - .filter((comment) => comment.value.includes("eslint-disable-next-line")); - const refIsLastWithSortDisablingComment = - attributes.indexOf(refAttribute) === attributes.length - 1 && eslintDisableComments.length !== 0; - - if (!refIsLastWithSortDisablingComment) { - context.report({ - node, - message: `"ref" prop should be placed last in JSX to ensure the node attrs/props are in sync.`, - fix(fixer) { - return [ - fixer.removeRange([tokenBeforeRefAttr.range[1], refAttribute.range[1]]), - fixer.insertTextAfterRange( - otherAttrs[otherAttrs.length - 1].range, - `\n${indentation}// eslint-disable-next-line react/jsx-sort-props -- auto-generated by @esri/calcite-components/enforce-ref-last-prop\n${indentation}${refAttrText}`, - ), - ]; - }, - }); - } - } - } - }, - }; - }, -}; - -export default rule; diff --git a/packages/eslint-plugin-calcite-components/src/rules/index.ts b/packages/eslint-plugin-calcite-components/src/rules/index.ts index 4499f42a295..1ee62ea9221 100644 --- a/packages/eslint-plugin-calcite-components/src/rules/index.ts +++ b/packages/eslint-plugin-calcite-components/src/rules/index.ts @@ -1,15 +1,9 @@ import banEvents from "./ban-events"; -import banPropsOnHost from "./ban-props-on-host"; -import enforceRefLastProp from "./enforce-ref-last-prop"; import noDynamicCreateelement from "./no-dynamic-createelement"; -import requireEventEmitterType from "./require-event-emitter-type"; import strictBooleanAttributes from "./strict-boolean-attributes"; export default { "ban-events": banEvents, - "ban-props-on-host": banPropsOnHost, - "enforce-ref-last-prop": enforceRefLastProp, "no-dynamic-createelement": noDynamicCreateelement, - "require-event-emitter-type": requireEventEmitterType, "strict-boolean-attributes": strictBooleanAttributes, }; diff --git a/packages/eslint-plugin-calcite-components/tests/lib/rules/ban-props-on-host/ban-props-on-host.good.tsx b/packages/eslint-plugin-calcite-components/tests/lib/rules/ban-props-on-host/ban-props-on-host.good.tsx deleted file mode 100644 index 0cf7da152de..00000000000 --- a/packages/eslint-plugin-calcite-components/tests/lib/rules/ban-props-on-host/ban-props-on-host.good.tsx +++ /dev/null @@ -1,18 +0,0 @@ -// @ts-nocheck -@Component({ tag: "sample-tag" }) -export class SampleTag { - render() { - return ( - { - /* click! */ - }} - > - test - - ); - } -} diff --git a/packages/eslint-plugin-calcite-components/tests/lib/rules/ban-props-on-host/ban-props-on-host.spec.ts b/packages/eslint-plugin-calcite-components/tests/lib/rules/ban-props-on-host/ban-props-on-host.spec.ts deleted file mode 100644 index 9f80af3074e..00000000000 --- a/packages/eslint-plugin-calcite-components/tests/lib/rules/ban-props-on-host/ban-props-on-host.spec.ts +++ /dev/null @@ -1,29 +0,0 @@ -import rule from "../../../../src/rules/ban-props-on-host"; -import { ruleTester } from "stencil-eslint-core"; -import * as path from "path"; -import * as fs from "fs"; - -const projectPath = path.resolve(__dirname, "../../../tsconfig.json"); - -describe("stencil rules", () => { - const files = { - good: path.resolve(__dirname, "ban-props-on-host.good.tsx"), - wrong: path.resolve(__dirname, "ban-props-on-host.wrong.tsx"), - }; - ruleTester(projectPath).run("ban-props-on-host", rule, { - valid: [ - { - code: fs.readFileSync(files.good, "utf8"), - filename: files.good, - }, - ], - - invalid: [ - { - code: fs.readFileSync(files.wrong, "utf8"), - filename: files.wrong, - errors: 1, - }, - ], - }); -}); diff --git a/packages/eslint-plugin-calcite-components/tests/lib/rules/ban-props-on-host/ban-props-on-host.wrong.tsx b/packages/eslint-plugin-calcite-components/tests/lib/rules/ban-props-on-host/ban-props-on-host.wrong.tsx deleted file mode 100644 index 1e5d9a6c1c6..00000000000 --- a/packages/eslint-plugin-calcite-components/tests/lib/rules/ban-props-on-host/ban-props-on-host.wrong.tsx +++ /dev/null @@ -1,11 +0,0 @@ -// @ts-nocheck -@Component({ tag: "sample-tag" }) -export class SampleTag { - render() { - return ( - - test - - ); - } -} diff --git a/packages/eslint-plugin-calcite-components/tests/lib/rules/enforce-ref-last-prop/enforce-ref-last-prop.good.tsx b/packages/eslint-plugin-calcite-components/tests/lib/rules/enforce-ref-last-prop/enforce-ref-last-prop.good.tsx deleted file mode 100644 index 94075e73179..00000000000 --- a/packages/eslint-plugin-calcite-components/tests/lib/rules/enforce-ref-last-prop/enforce-ref-last-prop.good.tsx +++ /dev/null @@ -1,26 +0,0 @@ -// @ts-nocheck -@Component({ tag: "sample-tag" }) -export class SampleTag { - render() { - return ( - -
{ - /* click! */ - }} - tabIndex={0} - // eslint-disable-next-line enforce-ref-last-prop -- auto-generated by @esri/calcite-components/enforce-ref-last-prop - ref={(el: HTMLDivElement): void => { - /* refEl */ - }} - > - test Note: we are intentionally specifying `enforce-ref-last-prop` in the disable line as - RuleTester can't be configured with multiple rules and this does not disable the custom - rule, please see the output file for the correctly generated disable line -
-
- ); - } -} diff --git a/packages/eslint-plugin-calcite-components/tests/lib/rules/enforce-ref-last-prop/enforce-ref-last-prop.output.tsx b/packages/eslint-plugin-calcite-components/tests/lib/rules/enforce-ref-last-prop/enforce-ref-last-prop.output.tsx deleted file mode 100644 index e7e1717ea52..00000000000 --- a/packages/eslint-plugin-calcite-components/tests/lib/rules/enforce-ref-last-prop/enforce-ref-last-prop.output.tsx +++ /dev/null @@ -1,70 +0,0 @@ -// @ts-nocheck -@Component({ tag: "sample-tag" }) -export class SampleTag { - render() { - return ( - -
{ - /* click! */ - }} - tabIndex={0} - // eslint-disable-next-line react/jsx-sort-props -- auto-generated by @esri/calcite-components/enforce-ref-last-prop - ref={(el: HTMLDivElement): void => { - /* refEl */ - }} - > - case where ref is not last prop -
-
{ - /* click! */ - }} - tabIndex={0} - // eslint-disable-next-line react/jsx-sort-props -- auto-generated by @esri/calcite-components/enforce-ref-last-prop - ref={(el: HTMLDivElement): void => { - /* refEl */ - }} - > - case where ref last prop, but not commented -
-
{ - /* click! */ - }} - tabIndex={0} - // eslint-disable-next-line react/jsx-sort-props -- auto-generated by @esri/calcite-components/enforce-ref-last-prop - ref={(el: HTMLDivElement): void => { - /* refEl */ - }} - > - case where ref last prop, and already commented Note: this is marked as wrong because - RuleTester can't configure multiple rules, so we ignore the ESLint error from not finding - the disabled rule -
-
{ - /* click! */ - }} - tabIndex={0} - // eslint-disable-next-line react/jsx-sort-props -- auto-generated by @esri/calcite-components/enforce-ref-last-prop - ref={(el: HTMLDivElement): void => { - /* refEl */ - }} - > - case where ref is not last prop and already commented Note: this is marked as wrong - because RuleTester can't configure multiple rules, so we ignore the ESLint error from not - finding the disabled rule -
-
- ); - } -} diff --git a/packages/eslint-plugin-calcite-components/tests/lib/rules/enforce-ref-last-prop/enforce-ref-last-prop.spec.ts b/packages/eslint-plugin-calcite-components/tests/lib/rules/enforce-ref-last-prop/enforce-ref-last-prop.spec.ts deleted file mode 100644 index a439da49680..00000000000 --- a/packages/eslint-plugin-calcite-components/tests/lib/rules/enforce-ref-last-prop/enforce-ref-last-prop.spec.ts +++ /dev/null @@ -1,48 +0,0 @@ -import rule from "../../../../src/rules/enforce-ref-last-prop"; -import { ruleTester } from "stencil-eslint-core"; -import * as path from "path"; -import * as fs from "fs"; - -const projectPath = path.resolve(__dirname, "../../../tsconfig.json"); - -describe("enforce-ref-last-prop rule", () => { - const files = { - good: path.resolve(__dirname, "enforce-ref-last-prop.good.tsx"), - wrong: path.resolve(__dirname, "enforce-ref-last-prop.wrong.tsx"), - output: path.resolve(__dirname, "enforce-ref-last-prop.output.tsx"), - }; - ruleTester(projectPath).run("enforce-ref-last-prop", rule, { - valid: [ - { - code: fs.readFileSync(files.good, "utf8"), - filename: files.good, - }, - ], - - invalid: [ - { - code: fs.readFileSync(files.wrong, "utf8"), - filename: files.wrong, - errors: [ - // we include the disabled rule not found error because RuleTester doesn't support multiple rules - { - message: `"ref" prop should be placed last in JSX to ensure the node attrs/props are in sync.`, - }, - { - message: `"ref" prop should be placed last in JSX to ensure the node attrs/props are in sync.`, - }, - { - message: `Definition for rule 'react/jsx-sort-props' was not found.`, - }, - { - message: `"ref" prop should be placed last in JSX to ensure the node attrs/props are in sync.`, - }, - { - message: `Definition for rule 'react/jsx-sort-props' was not found.`, - }, - ], - output: fs.readFileSync(files.output, "utf8"), - }, - ], - }); -}); diff --git a/packages/eslint-plugin-calcite-components/tests/lib/rules/enforce-ref-last-prop/enforce-ref-last-prop.wrong.tsx b/packages/eslint-plugin-calcite-components/tests/lib/rules/enforce-ref-last-prop/enforce-ref-last-prop.wrong.tsx deleted file mode 100644 index 3fbdfb319b3..00000000000 --- a/packages/eslint-plugin-calcite-components/tests/lib/rules/enforce-ref-last-prop/enforce-ref-last-prop.wrong.tsx +++ /dev/null @@ -1,68 +0,0 @@ -// @ts-nocheck -@Component({ tag: "sample-tag" }) -export class SampleTag { - render() { - return ( - -
{ - /* refEl */ - }} - class="some-class" - id="use-case-1" - onClick={() => { - /* click! */ - }} - tabIndex={0} - > - case where ref is not last prop -
-
{ - /* click! */ - }} - tabIndex={0} - ref={(el: HTMLDivElement): void => { - /* refEl */ - }} - > - case where ref last prop, but not commented -
-
{ - /* click! */ - }} - tabIndex={0} - // eslint-disable-next-line react/jsx-sort-props -- auto-generated by @esri/calcite-components/enforce-ref-last-prop - ref={(el: HTMLDivElement): void => { - /* refEl */ - }} - > - case where ref last prop, and already commented Note: this is marked as wrong because - RuleTester can't configure multiple rules, so we ignore the ESLint error from not finding - the disabled rule -
-
{ - /* refEl */ - }} - class="some-class" - id="use-case-4" - onClick={() => { - /* click! */ - }} - tabIndex={0} - > - case where ref is not last prop and already commented Note: this is marked as wrong - because RuleTester can't configure multiple rules, so we ignore the ESLint error from not - finding the disabled rule -
-
- ); - } -} diff --git a/packages/eslint-plugin-calcite-components/tests/lib/rules/require-event-emitter-type/require-event-emitter-type.good.tsx b/packages/eslint-plugin-calcite-components/tests/lib/rules/require-event-emitter-type/require-event-emitter-type.good.tsx deleted file mode 100644 index 85e6fdc23da..00000000000 --- a/packages/eslint-plugin-calcite-components/tests/lib/rules/require-event-emitter-type/require-event-emitter-type.good.tsx +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-nocheck -@Component({ tag: "sample-tag" }) -export class SampleTag { - @Event() - myEvent: EventEmitter; - - render() { - return test; - } -} diff --git a/packages/eslint-plugin-calcite-components/tests/lib/rules/require-event-emitter-type/require-event-emitter-type.spec.ts b/packages/eslint-plugin-calcite-components/tests/lib/rules/require-event-emitter-type/require-event-emitter-type.spec.ts deleted file mode 100644 index e53ecb758c3..00000000000 --- a/packages/eslint-plugin-calcite-components/tests/lib/rules/require-event-emitter-type/require-event-emitter-type.spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -import rule from "../../../../src/rules/require-event-emitter-type"; -import { ruleTester } from "stencil-eslint-core"; -import * as path from "path"; -import * as fs from "fs"; - -const projectPath = path.resolve(__dirname, "../../../tsconfig.json"); - -describe("stencil rules", () => { - const files = { - good: path.resolve(__dirname, "require-event-emitter-type.good.tsx"), - wrong: path.resolve(__dirname, "require-event-emitter-type.wrong.tsx"), - }; - - ruleTester(projectPath).run("require-event-emitter-type", rule, { - valid: [ - { - code: fs.readFileSync(files.good, "utf8"), - filename: files.good, - }, - ], - - invalid: [ - { - code: fs.readFileSync(files.wrong, "utf8"), - filename: files.wrong, - errors: 2, - }, - ], - }); -}); diff --git a/packages/eslint-plugin-calcite-components/tests/lib/rules/require-event-emitter-type/require-event-emitter-type.wrong.tsx b/packages/eslint-plugin-calcite-components/tests/lib/rules/require-event-emitter-type/require-event-emitter-type.wrong.tsx deleted file mode 100644 index c38e1e414dd..00000000000 --- a/packages/eslint-plugin-calcite-components/tests/lib/rules/require-event-emitter-type/require-event-emitter-type.wrong.tsx +++ /dev/null @@ -1,13 +0,0 @@ -// @ts-nocheck -@Component({ tag: "sample-tag" }) -export class SampleTag { - @Event() - myEvent: EventEmitter; - - @Event() - myImplicitTypeEvent; - - render() { - return test; - } -}