diff --git a/README.md b/README.md index 23401e7..98f02c3 100644 --- a/README.md +++ b/README.md @@ -170,6 +170,7 @@ Flat configs are also available as `plugin.configs['flat/recommended']` and `plu | โœ” | ๐Ÿ”ง | Rule | Description | | :---: | :---: | :--- | :--- | +| โœ” | ๐Ÿ”ง | [solid/boolean-attr](docs/boolean-attr.md) | Enforce explicit boolean attribute evaluation when the attribute is enumerated | | โœ” | ๐Ÿ”ง | [solid/components-return-once](docs/components-return-once.md) | Disallow early returns in components. Solid components only run once, and so conditionals should be inside JSX. | | โœ” | ๐Ÿ”ง | [solid/event-handlers](docs/event-handlers.md) | Enforce naming DOM element event handlers consistently and prevent Solid's analysis from misunderstanding whether a prop should be an event handler. | | โœ” | ๐Ÿ”ง | [solid/imports](docs/imports.md) | Enforce consistent imports from "solid-js", "solid-js/web", and "solid-js/store". | diff --git a/docs/boolean-attr.md b/docs/boolean-attr.md new file mode 100644 index 0000000..b005e84 --- /dev/null +++ b/docs/boolean-attr.md @@ -0,0 +1,14 @@ + +# solid/boolean-attr +Enforce explicit boolean attribute evaluation when the attribute is enumerated +This rule is **an error** by default. + +[View source](../src/rules/boolean-attr.ts) ยท [View tests](../test/rules/boolean-attr.test.ts) + + + + + + + + diff --git a/src/configs/recommended.ts b/src/configs/recommended.ts index b0ec525..19eac0e 100644 --- a/src/configs/recommended.ts +++ b/src/configs/recommended.ts @@ -27,6 +27,7 @@ const recommended = { "solid/components-return-once": 1, "solid/no-destructure": 2, "solid/prefer-for": 2, + "solid/boolean-attr": 2, "solid/reactivity": 1, "solid/event-handlers": 1, // these rules are mostly style suggestions diff --git a/src/plugin.ts b/src/plugin.ts index 0b6346b..a7b98db 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -6,6 +6,7 @@ // eslint-disable-next-line @typescript-eslint/no-unused-vars import type { TSESLint } from "@typescript-eslint/utils"; +import booleanAttr from "./rules/boolean-attr"; import componentsReturnOnce from "./rules/components-return-once"; import eventHandlers from "./rules/event-handlers"; import imports from "./rules/imports"; @@ -34,6 +35,7 @@ const { name, version } = require("../package.json"); const meta = { name, version }; const allRules = { + "boolean-attr": booleanAttr, "components-return-once": componentsReturnOnce, "event-handlers": eventHandlers, imports, diff --git a/src/rules/boolean-attr.ts b/src/rules/boolean-attr.ts new file mode 100644 index 0000000..7b542f8 --- /dev/null +++ b/src/rules/boolean-attr.ts @@ -0,0 +1,48 @@ +/** + * FIXME: remove this comments and import when below issue is fixed. + * This import is necessary for type generation due to a bug in the TypeScript compiler. + * See: https://github.com/microsoft/TypeScript/issues/42873 + */ +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import type { TSESLint } from "@typescript-eslint/utils"; + +import { ESLintUtils } from "@typescript-eslint/utils"; + +const createRule = ESLintUtils.RuleCreator.withoutDocs; + +type MessageIds = "explicitEnumeratedAttribute"; +type Options = []; + +export default createRule({ + meta: { + type: "problem", + docs: { + description: "Enforce explicit boolean attribute evaluation when the attribute is enumerated", + url: "https://github.com/solidjs-community/eslint-plugin-solid/blob/main/docs/boolean-attr.md", + }, + fixable: "code", + schema: [], + messages: { + explicitEnumeratedAttribute: + "This attribute is enumerated and not Boolean. A value of true or false is mandatory," + + 'and shorthand like `` is forbidden. The correct usage is ``.', + }, + }, + defaultOptions: [], + create(context) { + return { + JSXAttribute(node) { + if (node.name.name != "draggable" || node.value) return; + + context.report({ + node, + messageId: "explicitEnumeratedAttribute", + + fix: (fixer) => { + return [fixer.insertTextAfter(node, '="true"')]; + }, + }); + }, + }; + }, +}); diff --git a/test/rules/boolean-attr.test.ts b/test/rules/boolean-attr.test.ts new file mode 100644 index 0000000..101cc3c --- /dev/null +++ b/test/rules/boolean-attr.test.ts @@ -0,0 +1,19 @@ +import { run } from "../ruleTester"; +import rule from "../../src/rules/boolean-attr"; + +export const cases = run("boolean-attr", rule, { + valid: [ + `let el =
Hello, world!
`, + `let el =
Hello, world!
`, + `let el =
Hello, world!
`, + `let el =
Hello, world!
`, + `let el =
Hello, world!
`, + ], + invalid: [ + { + code: `let el =
Hello, world!
`, + errors: [{ messageId: "explicitEnumeratedAttribute" }], + output: `let el =
Hello, world!
`, + }, + ], +});