From ce69f89247b169b42f79649cf89c7a10bfe289a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Fri, 22 Nov 2024 16:36:44 +0100 Subject: [PATCH 1/9] chore(consistent-selector-style): added rule scaffolding --- .changeset/early-trainers-know.md | 5 ++ README.md | 1 + docs/rules.md | 1 + docs/rules/consistent-selector-style.md | 51 +++++++++++++++++++ .../eslint-plugin-svelte/src/rule-types.ts | 5 ++ .../src/rules/consistent-selector-style.ts | 17 +++++++ .../eslint-plugin-svelte/src/utils/rules.ts | 2 + .../src/rules/consistent-selector-style.ts | 12 +++++ 8 files changed, 94 insertions(+) create mode 100644 .changeset/early-trainers-know.md create mode 100644 docs/rules/consistent-selector-style.md create mode 100644 packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts create mode 100644 packages/eslint-plugin-svelte/tests/src/rules/consistent-selector-style.ts diff --git a/.changeset/early-trainers-know.md b/.changeset/early-trainers-know.md new file mode 100644 index 000000000..c379b3735 --- /dev/null +++ b/.changeset/early-trainers-know.md @@ -0,0 +1,5 @@ +--- +'eslint-plugin-svelte': minor +--- + +feat: added the `consistent-selector-style` rule diff --git a/README.md b/README.md index b2bac0116..ac522d6e1 100644 --- a/README.md +++ b/README.md @@ -380,6 +380,7 @@ These rules relate to style guidelines, and are therefore quite subjective: | Rule ID | Description | | |:--------|:------------|:---| +| [svelte/consistent-selector-style](https://sveltejs.github.io/eslint-plugin-svelte/rules/consistent-selector-style/) | enforce a consistent style for CSS selectors | | | [svelte/derived-has-same-inputs-outputs](https://sveltejs.github.io/eslint-plugin-svelte/rules/derived-has-same-inputs-outputs/) | derived store should use same variable names between values and callback | | | [svelte/first-attribute-linebreak](https://sveltejs.github.io/eslint-plugin-svelte/rules/first-attribute-linebreak/) | enforce the location of first attribute | :wrench: | | [svelte/html-closing-bracket-new-line](https://sveltejs.github.io/eslint-plugin-svelte/rules/html-closing-bracket-new-line/) | Require or disallow a line break before tag's closing brackets | :wrench: | diff --git a/docs/rules.md b/docs/rules.md index f07b703a2..f6f5a9f5c 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -77,6 +77,7 @@ These rules relate to style guidelines, and are therefore quite subjective: | Rule ID | Description | | | :------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------- | :------- | +| [svelte/consistent-selector-style](./rules/consistent-selector-style.md) | enforce a consistent style for CSS selectors | | | [svelte/derived-has-same-inputs-outputs](./rules/derived-has-same-inputs-outputs.md) | derived store should use same variable names between values and callback | | | [svelte/first-attribute-linebreak](./rules/first-attribute-linebreak.md) | enforce the location of first attribute | :wrench: | | [svelte/html-closing-bracket-new-line](./rules/html-closing-bracket-new-line.md) | Require or disallow a line break before tag's closing brackets | :wrench: | diff --git a/docs/rules/consistent-selector-style.md b/docs/rules/consistent-selector-style.md new file mode 100644 index 000000000..0f6d943c6 --- /dev/null +++ b/docs/rules/consistent-selector-style.md @@ -0,0 +1,51 @@ +--- +pageClass: 'rule-details' +sidebarDepth: 0 +title: 'svelte/consistent-selector-style' +description: 'enforce a consistent style for CSS selectors' +--- + +# svelte/consistent-selector-style + +> enforce a consistent style for CSS selectors + +- :exclamation: **_This rule has not been released yet._** + +## :book: Rule Details + +This rule reports ???. + + + + + +```svelte + + + + + +``` + + + +## :wrench: Options + +```json +{ + "svelte/consistent-selector-style": ["error", {}] +} +``` + +- + +## :books: Further Reading + +- + +## :mag: Implementation + +- [Rule source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts) +- [Test source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/tests/src/rules/consistent-selector-style.ts) diff --git a/packages/eslint-plugin-svelte/src/rule-types.ts b/packages/eslint-plugin-svelte/src/rule-types.ts index 3bc21b67f..0295cbaf1 100644 --- a/packages/eslint-plugin-svelte/src/rule-types.ts +++ b/packages/eslint-plugin-svelte/src/rule-types.ts @@ -34,6 +34,11 @@ export interface RuleOptions { * @see https://sveltejs.github.io/eslint-plugin-svelte/rules/comment-directive/ */ 'svelte/comment-directive'?: Linter.RuleEntry + /** + * enforce a consistent style for CSS selectors + * @see https://sveltejs.github.io/eslint-plugin-svelte/rules/consistent-selector-style/ + */ + 'svelte/consistent-selector-style'?: Linter.RuleEntry<[]> /** * derived store should use same variable names between values and callback * @see https://sveltejs.github.io/eslint-plugin-svelte/rules/derived-has-same-inputs-outputs/ diff --git a/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts b/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts new file mode 100644 index 000000000..ad89e96f9 --- /dev/null +++ b/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts @@ -0,0 +1,17 @@ +import { createRule } from '../utils'; + +export default createRule('consistent-selector-style', { + meta: { + docs: { + description: 'enforce a consistent style for CSS selectors', + category: 'Stylistic Issues', + recommended: false + }, + schema: [], + messages: {}, + type: 'suggestion' + }, + create(context) { + return {}; + } +}); diff --git a/packages/eslint-plugin-svelte/src/utils/rules.ts b/packages/eslint-plugin-svelte/src/utils/rules.ts index 43d6772b7..2a2ddeeda 100644 --- a/packages/eslint-plugin-svelte/src/utils/rules.ts +++ b/packages/eslint-plugin-svelte/src/utils/rules.ts @@ -6,6 +6,7 @@ import typescriptEslintNoUnnecessaryCondition from '../rules/@typescript-eslint/ import blockLang from '../rules/block-lang.js'; import buttonHasType from '../rules/button-has-type.js'; import commentDirective from '../rules/comment-directive.js'; +import consistentSelectorStyle from '../rules/consistent-selector-style.js'; import derivedHasSameInputsOutputs from '../rules/derived-has-same-inputs-outputs.js'; import experimentalRequireSlotTypes from '../rules/experimental-require-slot-types.js'; import experimentalRequireStrictEvents from '../rules/experimental-require-strict-events.js'; @@ -77,6 +78,7 @@ export const rules = [ blockLang, buttonHasType, commentDirective, + consistentSelectorStyle, derivedHasSameInputsOutputs, experimentalRequireSlotTypes, experimentalRequireStrictEvents, diff --git a/packages/eslint-plugin-svelte/tests/src/rules/consistent-selector-style.ts b/packages/eslint-plugin-svelte/tests/src/rules/consistent-selector-style.ts new file mode 100644 index 000000000..edd626103 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/src/rules/consistent-selector-style.ts @@ -0,0 +1,12 @@ +import { RuleTester } from '../../utils/eslint-compat'; +import rule from '../../../src/rules/consistent-selector-style'; +import { loadTestCases } from '../../utils/utils'; + +const tester = new RuleTester({ + languageOptions: { + ecmaVersion: 2020, + sourceType: 'module' + } +}); + +tester.run('consistent-selector-style', rule as any, loadTestCases('consistent-selector-style')); From 7b59f7d36dea236429bd0953b3765e3099f69176 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Thu, 5 Dec 2024 19:46:15 +0100 Subject: [PATCH 2/9] test(consistent-selector-style): added rule tests --- .../invalid/id-class-type/_config.json | 3 + .../should-be-id-combination01-errors.yaml | 48 ++++++ .../should-be-id-combination01-input.svelte | 24 +++ .../id-class-type/should-be-id01-errors.yaml | 48 ++++++ .../id-class-type/should-be-id01-input.svelte | 51 ++++++ .../invalid/id-type-class/_config.json | 3 + .../id-type-class/should-be-id01-errors.yaml | 48 ++++++ .../id-type-class/should-be-id01-input.svelte | 51 ++++++ .../should-be-type01-errors.yaml | 28 ++++ .../should-be-type01-input.svelte | 33 ++++ .../invalid/type-class-id/_config.json | 3 + .../should-be-type01-errors.yaml | 44 +++++ .../should-be-type01-input.svelte | 51 ++++++ ...should-be-id-with-components01-errors.yaml | 28 ++++ ...hould-be-id-with-components01-input.svelte | 41 +++++ .../type-id-class/should-be-id01-errors.yaml | 28 ++++ .../type-id-class/should-be-id01-input.svelte | 33 ++++ ...ould-be-type-with-components01-errors.yaml | 44 +++++ ...uld-be-type-with-components01-input.svelte | 61 +++++++ .../should-be-type01-errors.yaml | 44 +++++ .../should-be-type01-input.svelte | 51 ++++++ .../valid/class-id-type/_config.json | 3 + .../class-id-type/class-scss01-input.svelte | 15 ++ .../valid/class-id-type/class01-input.svelte | 31 ++++ .../valid/class-type-id/_config.json | 3 + .../class-type-id/class-scss01-input.svelte | 15 ++ .../valid/class-type-id/class01-input.svelte | 31 ++++ .../valid/id-class-type/_config.json | 3 + .../valid/id-class-type/class01-input.svelte | 35 ++++ .../id-class-type/id-scss01-input.svelte | 15 ++ .../valid/id-class-type/id01-input.svelte | 31 ++++ .../valid/id-type-class/_config.json | 3 + .../valid/id-type-class/class01-input.svelte | 35 ++++ .../id-type-class/id-scss01-input.svelte | 15 ++ .../valid/id-type-class/id01-input.svelte | 31 ++++ .../valid/id-type-class/type01-input.svelte | 35 ++++ .../valid/type-class-id/_config.json | 3 + .../valid/type-class-id/class01-input.svelte | 35 ++++ .../type-class-id/type-scss01-input.svelte | 13 ++ .../valid/type-class-id/type01-input.svelte | 35 ++++ .../valid/type-id-class/class01-input.svelte | 37 +++++ .../valid/type-id-class/global01-input.svelte | 157 ++++++++++++++++++ .../valid/type-id-class/id01-input.svelte | 33 ++++ .../type-id-class/type-scss01-input.svelte | 13 ++ .../valid/type-id-class/type01-input.svelte | 35 ++++ 45 files changed, 1427 insertions(+) create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/_config.json create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/should-be-id-combination01-errors.yaml create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/should-be-id-combination01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/should-be-id01-errors.yaml create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/should-be-id01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/_config.json create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/should-be-id01-errors.yaml create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/should-be-id01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/should-be-type01-errors.yaml create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/should-be-type01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-class-id/_config.json create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-class-id/should-be-type01-errors.yaml create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-class-id/should-be-type01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-id-with-components01-errors.yaml create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-id-with-components01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-id01-errors.yaml create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-id01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-type-with-components01-errors.yaml create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-type-with-components01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-type01-errors.yaml create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-type01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-id-type/_config.json create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-id-type/class-scss01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-id-type/class01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-type-id/_config.json create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-type-id/class-scss01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-type-id/class01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-class-type/_config.json create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-class-type/class01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-class-type/id-scss01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-class-type/id01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/_config.json create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/class01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/id-scss01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/id01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/type01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-class-id/_config.json create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-class-id/class01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-class-id/type-scss01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-class-id/type01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/class01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/global01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/id01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/type-scss01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/type01-input.svelte diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/_config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/_config.json new file mode 100644 index 000000000..785bad119 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/_config.json @@ -0,0 +1,3 @@ +{ + "options": [{ "style": ["id", "class", "type"] }] +} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/should-be-id-combination01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/should-be-id-combination01-errors.yaml new file mode 100644 index 000000000..20b348a6c --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/should-be-id-combination01-errors.yaml @@ -0,0 +1,48 @@ +- message: Selector should select by ID instead of class + line: 12 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 13 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 14 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 15 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 15 + column: 11 + suggestions: null +- message: Selector should select by ID instead of class + line: 16 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 17 + column: 3 + suggestions: null +- message: Selector should select by ID instead of element type + line: 18 + column: 3 + suggestions: null +- message: Selector should select by ID instead of element type + line: 19 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 20 + column: 3 + suggestions: null +- message: Selector should select by ID instead of element type + line: 20 + column: 11 + suggestions: null +- message: Selector should select by ID instead of element type + line: 21 + column: 3 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/should-be-id-combination01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/should-be-id-combination01-input.svelte new file mode 100644 index 000000000..7240fadf3 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/should-be-id-combination01-input.svelte @@ -0,0 +1,24 @@ +Click me! + +Click me two! + +Text 1 + +Text 3 + +Italic + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/should-be-id01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/should-be-id01-errors.yaml new file mode 100644 index 000000000..0ed971448 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/should-be-id01-errors.yaml @@ -0,0 +1,48 @@ +- message: Selector should select by ID instead of class + line: 12 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 16 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 20 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 24 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 24 + column: 11 + suggestions: null +- message: Selector should select by ID instead of class + line: 28 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 32 + column: 3 + suggestions: null +- message: Selector should select by ID instead of element type + line: 36 + column: 3 + suggestions: null +- message: Selector should select by ID instead of element type + line: 40 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 44 + column: 3 + suggestions: null +- message: Selector should select by ID instead of element type + line: 44 + column: 11 + suggestions: null +- message: Selector should select by ID instead of element type + line: 48 + column: 3 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/should-be-id01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/should-be-id01-input.svelte new file mode 100644 index 000000000..f58dd4518 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-class-type/should-be-id01-input.svelte @@ -0,0 +1,51 @@ +Click me! + +Click me two! + +Text 1 + +Text 3 + +Italic + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/_config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/_config.json new file mode 100644 index 000000000..76b7a1bea --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/_config.json @@ -0,0 +1,3 @@ +{ + "options": [{ "style": ["id", "type", "class"] }] +} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/should-be-id01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/should-be-id01-errors.yaml new file mode 100644 index 000000000..0ed971448 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/should-be-id01-errors.yaml @@ -0,0 +1,48 @@ +- message: Selector should select by ID instead of class + line: 12 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 16 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 20 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 24 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 24 + column: 11 + suggestions: null +- message: Selector should select by ID instead of class + line: 28 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 32 + column: 3 + suggestions: null +- message: Selector should select by ID instead of element type + line: 36 + column: 3 + suggestions: null +- message: Selector should select by ID instead of element type + line: 40 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 44 + column: 3 + suggestions: null +- message: Selector should select by ID instead of element type + line: 44 + column: 11 + suggestions: null +- message: Selector should select by ID instead of element type + line: 48 + column: 3 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/should-be-id01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/should-be-id01-input.svelte new file mode 100644 index 000000000..f58dd4518 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/should-be-id01-input.svelte @@ -0,0 +1,51 @@ +Click me! + +Click me two! + +Text 1 + +Text 3 + +Italic + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/should-be-type01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/should-be-type01-errors.yaml new file mode 100644 index 000000000..f09167627 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/should-be-type01-errors.yaml @@ -0,0 +1,28 @@ +- message: Selector should select by element type instead of class + line: 10 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 14 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 18 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 22 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 22 + column: 11 + suggestions: null +- message: Selector should select by element type instead of class + line: 26 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 30 + column: 3 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/should-be-type01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/should-be-type01-input.svelte new file mode 100644 index 000000000..87b25c29d --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/id-type-class/should-be-type01-input.svelte @@ -0,0 +1,33 @@ +Click me! + +Click me two! + +Text 1 + +Text 2 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-class-id/_config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-class-id/_config.json new file mode 100644 index 000000000..249f96ef9 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-class-id/_config.json @@ -0,0 +1,3 @@ +{ + "options": [{ "style": ["type", "class", "id"] }] +} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-class-id/should-be-type01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-class-id/should-be-type01-errors.yaml new file mode 100644 index 000000000..57e5e2be5 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-class-id/should-be-type01-errors.yaml @@ -0,0 +1,44 @@ +- message: Selector should select by element type instead of class + line: 12 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 16 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 20 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 24 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 24 + column: 11 + suggestions: null +- message: Selector should select by element type instead of class + line: 28 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 32 + column: 3 + suggestions: null +- message: Selector should select by element type instead of ID + line: 36 + column: 3 + suggestions: null +- message: Selector should select by element type instead of ID + line: 40 + column: 3 + suggestions: null +- message: Selector should select by element type instead of ID + line: 44 + column: 7 + suggestions: null +- message: Selector should select by element type instead of ID + line: 48 + column: 3 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-class-id/should-be-type01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-class-id/should-be-type01-input.svelte new file mode 100644 index 000000000..1d1fa7078 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-class-id/should-be-type01-input.svelte @@ -0,0 +1,51 @@ +Click me! + +Click me two! + +Text 1 + +Text 2 + +Italic + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-id-with-components01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-id-with-components01-errors.yaml new file mode 100644 index 000000000..e153ca3c9 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-id-with-components01-errors.yaml @@ -0,0 +1,28 @@ +- message: Selector should select by ID instead of class + line: 18 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 22 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 26 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 30 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 30 + column: 11 + suggestions: null +- message: Selector should select by ID instead of class + line: 34 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 38 + column: 3 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-id-with-components01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-id-with-components01-input.svelte new file mode 100644 index 000000000..bd34fdaf6 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-id-with-components01-input.svelte @@ -0,0 +1,41 @@ + + +Click me! + +Component + +Click me two! + +Text 1 + +Component + +Text 3 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-id01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-id01-errors.yaml new file mode 100644 index 000000000..f2f218ba8 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-id01-errors.yaml @@ -0,0 +1,28 @@ +- message: Selector should select by ID instead of class + line: 10 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 14 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 18 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 22 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 22 + column: 11 + suggestions: null +- message: Selector should select by ID instead of class + line: 26 + column: 3 + suggestions: null +- message: Selector should select by ID instead of class + line: 30 + column: 3 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-id01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-id01-input.svelte new file mode 100644 index 000000000..6dee3410d --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-id01-input.svelte @@ -0,0 +1,33 @@ +Click me! + +Click me two! + +Text 1 + +Text 3 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-type-with-components01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-type-with-components01-errors.yaml new file mode 100644 index 000000000..c047f4278 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-type-with-components01-errors.yaml @@ -0,0 +1,44 @@ +- message: Selector should select by element type instead of class + line: 22 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 26 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 30 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 34 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 34 + column: 11 + suggestions: null +- message: Selector should select by element type instead of class + line: 38 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 42 + column: 3 + suggestions: null +- message: Selector should select by element type instead of ID + line: 46 + column: 3 + suggestions: null +- message: Selector should select by element type instead of ID + line: 50 + column: 3 + suggestions: null +- message: Selector should select by element type instead of ID + line: 54 + column: 7 + suggestions: null +- message: Selector should select by element type instead of ID + line: 58 + column: 3 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-type-with-components01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-type-with-components01-input.svelte new file mode 100644 index 000000000..b892b9f79 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-type-with-components01-input.svelte @@ -0,0 +1,61 @@ + + +Click me! + +Click me two! + +Component + +Text 1 + +Text 2 + +Component + +Italic + +Component + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-type01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-type01-errors.yaml new file mode 100644 index 000000000..57e5e2be5 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-type01-errors.yaml @@ -0,0 +1,44 @@ +- message: Selector should select by element type instead of class + line: 12 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 16 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 20 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 24 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 24 + column: 11 + suggestions: null +- message: Selector should select by element type instead of class + line: 28 + column: 3 + suggestions: null +- message: Selector should select by element type instead of class + line: 32 + column: 3 + suggestions: null +- message: Selector should select by element type instead of ID + line: 36 + column: 3 + suggestions: null +- message: Selector should select by element type instead of ID + line: 40 + column: 3 + suggestions: null +- message: Selector should select by element type instead of ID + line: 44 + column: 7 + suggestions: null +- message: Selector should select by element type instead of ID + line: 48 + column: 3 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-type01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-type01-input.svelte new file mode 100644 index 000000000..1d1fa7078 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/type-id-class/should-be-type01-input.svelte @@ -0,0 +1,51 @@ +Click me! + +Click me two! + +Text 1 + +Text 2 + +Italic + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-id-type/_config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-id-type/_config.json new file mode 100644 index 000000000..60025219d --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-id-type/_config.json @@ -0,0 +1,3 @@ +{ + "options": [{ "style": ["class", "id", "type"] }] +} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-id-type/class-scss01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-id-type/class-scss01-input.svelte new file mode 100644 index 000000000..04ace664c --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-id-type/class-scss01-input.svelte @@ -0,0 +1,15 @@ +Click me! + +Text 1 + +Text 2 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-id-type/class01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-id-type/class01-input.svelte new file mode 100644 index 000000000..405f8c459 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-id-type/class01-input.svelte @@ -0,0 +1,31 @@ +Click me! + +Text 1 + +Text 2 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-type-id/_config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-type-id/_config.json new file mode 100644 index 000000000..be9cf9216 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-type-id/_config.json @@ -0,0 +1,3 @@ +{ + "options": [{ "style": ["class", "type", "id"] }] +} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-type-id/class-scss01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-type-id/class-scss01-input.svelte new file mode 100644 index 000000000..04ace664c --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-type-id/class-scss01-input.svelte @@ -0,0 +1,15 @@ +Click me! + +Text 1 + +Text 2 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-type-id/class01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-type-id/class01-input.svelte new file mode 100644 index 000000000..405f8c459 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/class-type-id/class01-input.svelte @@ -0,0 +1,31 @@ +Click me! + +Text 1 + +Text 2 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-class-type/_config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-class-type/_config.json new file mode 100644 index 000000000..785bad119 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-class-type/_config.json @@ -0,0 +1,3 @@ +{ + "options": [{ "style": ["id", "class", "type"] }] +} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-class-type/class01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-class-type/class01-input.svelte new file mode 100644 index 000000000..f3564d8eb --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-class-type/class01-input.svelte @@ -0,0 +1,35 @@ +Click me! + +Click me two! + +Text 1 + +Text 2 + +Text 2 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-class-type/id-scss01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-class-type/id-scss01-input.svelte new file mode 100644 index 000000000..824d6e651 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-class-type/id-scss01-input.svelte @@ -0,0 +1,15 @@ +Click me! + +Text 1 + +Text 2 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-class-type/id01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-class-type/id01-input.svelte new file mode 100644 index 000000000..79afbb38b --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-class-type/id01-input.svelte @@ -0,0 +1,31 @@ +Click me! + +Text 1 + +Text 2 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/_config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/_config.json new file mode 100644 index 000000000..76b7a1bea --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/_config.json @@ -0,0 +1,3 @@ +{ + "options": [{ "style": ["id", "type", "class"] }] +} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/class01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/class01-input.svelte new file mode 100644 index 000000000..878799bde --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/class01-input.svelte @@ -0,0 +1,35 @@ +Click me! + +Click me two! + +Text 1 + +Text 2 + +Text 2 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/id-scss01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/id-scss01-input.svelte new file mode 100644 index 000000000..824d6e651 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/id-scss01-input.svelte @@ -0,0 +1,15 @@ +Click me! + +Text 1 + +Text 2 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/id01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/id01-input.svelte new file mode 100644 index 000000000..79afbb38b --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/id01-input.svelte @@ -0,0 +1,31 @@ +Click me! + +Text 1 + +Text 2 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/type01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/type01-input.svelte new file mode 100644 index 000000000..f8e9f2aa5 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/id-type-class/type01-input.svelte @@ -0,0 +1,35 @@ +Click me! + +Click me two! + +Text 1 + +Text 2 + +Text 2 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-class-id/_config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-class-id/_config.json new file mode 100644 index 000000000..249f96ef9 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-class-id/_config.json @@ -0,0 +1,3 @@ +{ + "options": [{ "style": ["type", "class", "id"] }] +} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-class-id/class01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-class-id/class01-input.svelte new file mode 100644 index 000000000..b770c0572 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-class-id/class01-input.svelte @@ -0,0 +1,35 @@ +Click me! + +Click me two! + +Text 1 + +Text 2 + +Text 3 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-class-id/type-scss01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-class-id/type-scss01-input.svelte new file mode 100644 index 000000000..4edab8017 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-class-id/type-scss01-input.svelte @@ -0,0 +1,13 @@ +Click me! + +Text 1 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-class-id/type01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-class-id/type01-input.svelte new file mode 100644 index 000000000..f8e9f2aa5 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-class-id/type01-input.svelte @@ -0,0 +1,35 @@ +Click me! + +Click me two! + +Text 1 + +Text 2 + +Text 2 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/class01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/class01-input.svelte new file mode 100644 index 000000000..92e8c4e31 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/class01-input.svelte @@ -0,0 +1,37 @@ +Click me! + +Click me two! + +Click me three! + +Text 1 + +Text 2 + +Text 3 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/global01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/global01-input.svelte new file mode 100644 index 000000000..a63fa30e5 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/global01-input.svelte @@ -0,0 +1,157 @@ +Click me! + +Click me two! + +Text 1 + +Text 2 + +Text 2 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/id01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/id01-input.svelte new file mode 100644 index 000000000..363844f29 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/id01-input.svelte @@ -0,0 +1,33 @@ +Click me! + +Click me too! + +Text 1 + +Text 2 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/type-scss01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/type-scss01-input.svelte new file mode 100644 index 000000000..4edab8017 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/type-scss01-input.svelte @@ -0,0 +1,13 @@ +Click me! + +Text 1 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/type01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/type01-input.svelte new file mode 100644 index 000000000..f8e9f2aa5 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id-class/type01-input.svelte @@ -0,0 +1,35 @@ +Click me! + +Click me two! + +Text 1 + +Text 2 + +Text 2 + + From 65d0fd310da74f56e88e62e121f1dcb19276ff5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Sat, 14 Dec 2024 14:48:59 +0100 Subject: [PATCH 3/9] feat(consistent-selector-style): added rule implementation --- .../eslint-plugin-svelte/src/rule-types.ts | 7 +- .../src/rules/consistent-selector-style.ts | 281 +++++++++++++++++- .../src/rules/no-unused-class-name.ts | 38 +-- .../src/utils/ast-utils.ts | 24 ++ 4 files changed, 309 insertions(+), 41 deletions(-) diff --git a/packages/eslint-plugin-svelte/src/rule-types.ts b/packages/eslint-plugin-svelte/src/rule-types.ts index 0295cbaf1..72953c665 100644 --- a/packages/eslint-plugin-svelte/src/rule-types.ts +++ b/packages/eslint-plugin-svelte/src/rule-types.ts @@ -38,7 +38,7 @@ export interface RuleOptions { * enforce a consistent style for CSS selectors * @see https://sveltejs.github.io/eslint-plugin-svelte/rules/consistent-selector-style/ */ - 'svelte/consistent-selector-style'?: Linter.RuleEntry<[]> + 'svelte/consistent-selector-style'?: Linter.RuleEntry /** * derived store should use same variable names between values and callback * @see https://sveltejs.github.io/eslint-plugin-svelte/rules/derived-has-same-inputs-outputs/ @@ -392,6 +392,11 @@ type SvelteButtonHasType = []|[{ type SvelteCommentDirective = []|[{ reportUnusedDisableDirectives?: boolean }] +// ----- svelte/consistent-selector-style ----- +type SvelteConsistentSelectorStyle = []|[{ + + style?: [("class" | "id" | "type"), ("class" | "id" | "type"), ("class" | "id" | "type")] +}] // ----- svelte/first-attribute-linebreak ----- type SvelteFirstAttributeLinebreak = []|[{ multiline?: ("below" | "beside") diff --git a/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts b/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts index ad89e96f9..b635373ea 100644 --- a/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts +++ b/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts @@ -1,17 +1,288 @@ -import { createRule } from '../utils'; +import type { AST } from 'svelte-eslint-parser'; +import type { AnyNode } from 'postcss'; +import type { + ClassName as SelectorClass, + Identifier as SelectorIdentifier, + Node as SelectorNode, + Tag as SelectorTag +} from 'postcss-selector-parser'; +import { findClassesInAttribute } from '../utils/ast-utils.js'; +import { getSourceCode } from '../utils/compat.js'; +import { createRule } from '../utils/index.js'; +import type { RuleContext, SourceCode } from '../types.js'; + +interface RuleGlobals { + style: string[]; + classSelections: Map; + idSelections: Map; + typeSelections: Map; + context: RuleContext; + getStyleSelectorAST: NonNullable; + styleSelectorNodeLoc: NonNullable; +} export default createRule('consistent-selector-style', { meta: { docs: { description: 'enforce a consistent style for CSS selectors', category: 'Stylistic Issues', - recommended: false + recommended: false, + conflictWithPrettier: false + }, + schema: [ + { + type: 'object', + properties: { + // TODO: Add option to include global selectors + style: { + type: 'array', + items: { + enum: ['class', 'id', 'type'] + }, + minItems: 3, // TODO: Allow fewer items + maxItems: 3, + uniqueItems: true + } + }, + additionalProperties: false + } + ], + messages: { + classShouldBeId: 'Selector should select by ID instead of class', + classShouldBeType: 'Selector should select by element type instead of class', + idShouldBeClass: 'Selector should select by class instead of ID', + idShouldBeType: 'Selector should select by element type instead of ID', + typeShouldBeClass: 'Selector should select by class instead of element type', + typeShouldBeId: 'Selector should select by ID instead of element type' }, - schema: [], - messages: {}, type: 'suggestion' }, create(context) { - return {}; + const sourceCode = getSourceCode(context); + if (!sourceCode.parserServices.isSvelte) { + return {}; + } + + const style = context.options[0]?.style ?? ['type', 'id', 'class']; + + const classSelections: Map = new Map(); + const idSelections: Map = new Map(); + const typeSelections: Map = new Map(); + + return { + SvelteElement(node) { + if (node.kind !== 'html') { + return; + } + addToArrayMap(typeSelections, node.name.name, node); + const classes = node.startTag.attributes.flatMap(findClassesInAttribute); + for (const className of classes) { + addToArrayMap(classSelections, className, node); + } + for (const attribute of node.startTag.attributes) { + if (attribute.type !== 'SvelteAttribute' || attribute.key.name !== 'id') { + continue; + } + for (const value of attribute.value) { + if (value.type === 'SvelteLiteral') { + addToArrayMap(idSelections, value.value, node); + } + } + } + }, + 'Program:exit'() { + const styleContext = sourceCode.parserServices.getStyleContext!(); + if ( + styleContext.status !== 'success' || + sourceCode.parserServices.getStyleSelectorAST === undefined || + sourceCode.parserServices.styleSelectorNodeLoc === undefined + ) { + return; + } + checkSelectorsInPostCSSNode(styleContext.sourceAst, { + style, + classSelections, + idSelections, + typeSelections, + context, + getStyleSelectorAST: sourceCode.parserServices.getStyleSelectorAST, + styleSelectorNodeLoc: sourceCode.parserServices.styleSelectorNodeLoc + }); + } + }; } }); + +/** + * Helper function to add a value to a Map of arrays + */ +function addToArrayMap( + map: Map, + key: string, + value: AST.SvelteHTMLElement +): void { + map.set(key, (map.get(key) ?? []).concat(value)); +} + +/** + * Checks selectors in a given PostCSS node + */ +function checkSelectorsInPostCSSNode(node: AnyNode, ruleGlobals: RuleGlobals): void { + if (node.type === 'rule') { + checkSelector(ruleGlobals.getStyleSelectorAST(node), ruleGlobals); + } + if ( + (node.type === 'root' || + (node.type === 'rule' && node.selector !== ':global') || + node.type === 'atrule') && + node.nodes !== undefined + ) { + node.nodes.flatMap((node) => checkSelectorsInPostCSSNode(node, ruleGlobals)); + } +} + +/** + * Checks an individual selector + */ +function checkSelector(node: SelectorNode, ruleGlobals: RuleGlobals): void { + if (node.type === 'class') { + checkClassSelector(node, ruleGlobals); + } + if (node.type === 'id') { + checkIdSelector(node, ruleGlobals); + } + if (node.type === 'tag') { + checkTypeSelector(node, ruleGlobals); + } + if ( + (node.type === 'pseudo' && node.value !== ':global') || + node.type === 'root' || + node.type === 'selector' + ) { + node.nodes.flatMap((node) => checkSelector(node, ruleGlobals)); + } +} + +/** + * Checks a class selector + */ +function checkClassSelector(node: SelectorClass, ruleGlobals: RuleGlobals): void { + const selection = ruleGlobals.classSelections.get(node.value) ?? []; + for (const styleValue of ruleGlobals.style) { + if (styleValue === 'class') { + return; + } + if (styleValue === 'id' && couldBeId(selection)) { + ruleGlobals.context.report({ + messageId: 'classShouldBeId', + loc: ruleGlobals.styleSelectorNodeLoc(node) as AST.SourceLocation + }); + return; + } + if (styleValue === 'type' && couldBeType(selection, ruleGlobals.typeSelections)) { + ruleGlobals.context.report({ + messageId: 'classShouldBeType', + loc: ruleGlobals.styleSelectorNodeLoc(node) as AST.SourceLocation + }); + return; + } + } +} + +/** + * Checks an ID selector + */ +function checkIdSelector(node: SelectorIdentifier, ruleGlobals: RuleGlobals): void { + const selection = ruleGlobals.idSelections.get(node.value) ?? []; + for (const styleValue of ruleGlobals.style) { + if (styleValue === 'class') { + ruleGlobals.context.report({ + messageId: 'idShouldBeClass', + loc: ruleGlobals.styleSelectorNodeLoc(node) as AST.SourceLocation + }); + return; + } + if (styleValue === 'id') { + return; + } + if (styleValue === 'type' && couldBeType(selection, ruleGlobals.typeSelections)) { + ruleGlobals.context.report({ + messageId: 'idShouldBeType', + loc: ruleGlobals.styleSelectorNodeLoc(node) as AST.SourceLocation + }); + return; + } + } +} + +/** + * Checks a type selector + */ +function checkTypeSelector(node: SelectorTag, ruleGlobals: RuleGlobals): void { + const selection = ruleGlobals.typeSelections.get(node.value) ?? []; + for (const styleValue of ruleGlobals.style) { + if (styleValue === 'class') { + ruleGlobals.context.report({ + messageId: 'typeShouldBeClass', + loc: ruleGlobals.styleSelectorNodeLoc(node) as AST.SourceLocation + }); + return; + } + if (styleValue === 'id' && couldBeId(selection)) { + ruleGlobals.context.report({ + messageId: 'typeShouldBeId', + loc: ruleGlobals.styleSelectorNodeLoc(node) as AST.SourceLocation + }); + return; + } + if (styleValue === 'type') { + return; + } + } +} + +/** + * Checks whether a given selection could be obtained using an ID selector + */ +function couldBeId(selection: AST.SvelteHTMLElement[]): boolean { + return selection.length <= 1; +} + +/** + * Checks whether a given selection could be obtained using a type selector + */ +function couldBeType( + selection: AST.SvelteHTMLElement[], + typeSelections: Map +): boolean { + const types = new Set(selection.map((node) => node.name.name)); + if (types.size > 1) { + return false; + } + if (types.size < 1) { + return true; + } + const type = [...types][0]; + const typeSelection = typeSelections.get(type); + return typeSelection !== undefined && arrayEquals(typeSelection, selection); +} + +/** + * Compares two arrays for item equality + */ +function arrayEquals(array1: AST.SvelteHTMLElement[], array2: AST.SvelteHTMLElement[]): boolean { + function comparator(a: AST.SvelteHTMLElement, b: AST.SvelteHTMLElement): number { + return a.range[0] - b.range[0]; + } + + const array2Sorted = array2.slice().sort(comparator); + return ( + array1.length === array2.length && + array1 + .slice() + .sort(comparator) + .every(function (value, index) { + return value === array2Sorted[index]; + }) + ); +} diff --git a/packages/eslint-plugin-svelte/src/rules/no-unused-class-name.ts b/packages/eslint-plugin-svelte/src/rules/no-unused-class-name.ts index 9f58e5335..6757e231e 100644 --- a/packages/eslint-plugin-svelte/src/rules/no-unused-class-name.ts +++ b/packages/eslint-plugin-svelte/src/rules/no-unused-class-name.ts @@ -1,16 +1,8 @@ import { createRule } from '../utils/index.js'; -import type { - SourceLocation, - SvelteAttribute, - SvelteDirective, - SvelteGenericsDirective, - SvelteShorthandAttribute, - SvelteSpecialDirective, - SvelteSpreadAttribute, - SvelteStyleDirective -} from 'svelte-eslint-parser/lib/ast'; +import type { AST } from 'svelte-eslint-parser'; import type { AnyNode } from 'postcss'; import type { Node as SelectorNode } from 'postcss-selector-parser'; +import { findClassesInAttribute } from '../utils/ast-utils.js'; import { getSourceCode } from '../utils/compat.js'; import type { SourceCode } from '../types.js'; @@ -44,7 +36,7 @@ export default createRule('no-unused-class-name', { return {}; } const allowedClassNames = context.options[0]?.allowedClassNames ?? []; - const classesUsedInTemplate: Record = {}; + const classesUsedInTemplate: Record = {}; return { SvelteElement(node) { @@ -78,30 +70,6 @@ export default createRule('no-unused-class-name', { } }); -/** - * Extract all class names used in a HTML element attribute. - */ -function findClassesInAttribute( - attribute: - | SvelteAttribute - | SvelteShorthandAttribute - | SvelteSpreadAttribute - | SvelteDirective - | SvelteStyleDirective - | SvelteSpecialDirective - | SvelteGenericsDirective -): string[] { - if (attribute.type === 'SvelteAttribute' && attribute.key.name === 'class') { - return attribute.value.flatMap((value) => - value.type === 'SvelteLiteral' ? value.value.trim().split(/\s+/u) : [] - ); - } - if (attribute.type === 'SvelteDirective' && attribute.kind === 'Class') { - return [attribute.key.name.name]; - } - return []; -} - /** * Extract all class names used in a PostCSS node. */ diff --git a/packages/eslint-plugin-svelte/src/utils/ast-utils.ts b/packages/eslint-plugin-svelte/src/utils/ast-utils.ts index e844ab842..1b804baef 100644 --- a/packages/eslint-plugin-svelte/src/utils/ast-utils.ts +++ b/packages/eslint-plugin-svelte/src/utils/ast-utils.ts @@ -545,6 +545,30 @@ function getAttributeValueRangeTokens( }; } +/** + * Extract all class names used in a HTML element attribute. + */ +export function findClassesInAttribute( + attribute: + | SvAST.SvelteAttribute + | SvAST.SvelteShorthandAttribute + | SvAST.SvelteSpreadAttribute + | SvAST.SvelteDirective + | SvAST.SvelteStyleDirective + | SvAST.SvelteSpecialDirective + | SvAST.SvelteGenericsDirective +): string[] { + if (attribute.type === 'SvelteAttribute' && attribute.key.name === 'class') { + return attribute.value.flatMap((value) => + value.type === 'SvelteLiteral' ? value.value.trim().split(/\s+/u) : [] + ); + } + if (attribute.type === 'SvelteDirective' && attribute.kind === 'Class') { + return [attribute.key.name.name]; + } + return []; +} + /** * Returns name of SvelteElement */ From f97385934a0f882d50962799879e83d02246ea1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Sat, 14 Dec 2024 16:23:19 +0100 Subject: [PATCH 4/9] feat(consistent-selector-style): enabled support for partial style --- .../eslint-plugin-svelte/src/rule-types.ts | 2 +- .../src/rules/consistent-selector-style.ts | 1 - .../valid/type-id/_config.json | 3 ++ .../valid/type-id/class01-input.svelte | 37 ++++++++++++++++ .../valid/type-id/id01-input.svelte | 33 ++++++++++++++ .../valid/type-id/type-scss01-input.svelte | 13 ++++++ .../valid/type-id/type01-input.svelte | 35 +++++++++++++++ .../valid/type/_config.json | 3 ++ .../valid/type/class01-input.svelte | 44 +++++++++++++++++++ .../valid/type/id01-input.svelte | 33 ++++++++++++++ .../valid/type/type-scss01-input.svelte | 13 ++++++ .../valid/type/type01-input.svelte | 35 +++++++++++++++ 12 files changed, 250 insertions(+), 2 deletions(-) create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/_config.json create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/class01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/id01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/type-scss01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/type01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/_config.json create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/class01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/id01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/type-scss01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/type01-input.svelte diff --git a/packages/eslint-plugin-svelte/src/rule-types.ts b/packages/eslint-plugin-svelte/src/rule-types.ts index 72953c665..22e07dde9 100644 --- a/packages/eslint-plugin-svelte/src/rule-types.ts +++ b/packages/eslint-plugin-svelte/src/rule-types.ts @@ -395,7 +395,7 @@ type SvelteCommentDirective = []|[{ // ----- svelte/consistent-selector-style ----- type SvelteConsistentSelectorStyle = []|[{ - style?: [("class" | "id" | "type"), ("class" | "id" | "type"), ("class" | "id" | "type")] + style?: []|[("class" | "id" | "type")]|[("class" | "id" | "type"), ("class" | "id" | "type")]|[("class" | "id" | "type"), ("class" | "id" | "type"), ("class" | "id" | "type")] }] // ----- svelte/first-attribute-linebreak ----- type SvelteFirstAttributeLinebreak = []|[{ diff --git a/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts b/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts index b635373ea..c66425223 100644 --- a/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts +++ b/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts @@ -39,7 +39,6 @@ export default createRule('consistent-selector-style', { items: { enum: ['class', 'id', 'type'] }, - minItems: 3, // TODO: Allow fewer items maxItems: 3, uniqueItems: true } diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/_config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/_config.json new file mode 100644 index 000000000..8d5a6bf74 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/_config.json @@ -0,0 +1,3 @@ +{ + "options": [{ "style": ["type", "id"] }] +} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/class01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/class01-input.svelte new file mode 100644 index 000000000..92e8c4e31 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/class01-input.svelte @@ -0,0 +1,37 @@ +Click me! + +Click me two! + +Click me three! + +Text 1 + +Text 2 + +Text 3 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/id01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/id01-input.svelte new file mode 100644 index 000000000..363844f29 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/id01-input.svelte @@ -0,0 +1,33 @@ +Click me! + +Click me too! + +Text 1 + +Text 2 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/type-scss01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/type-scss01-input.svelte new file mode 100644 index 000000000..4edab8017 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/type-scss01-input.svelte @@ -0,0 +1,13 @@ +Click me! + +Text 1 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/type01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/type01-input.svelte new file mode 100644 index 000000000..f8e9f2aa5 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type-id/type01-input.svelte @@ -0,0 +1,35 @@ +Click me! + +Click me two! + +Text 1 + +Text 2 + +Text 2 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/_config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/_config.json new file mode 100644 index 000000000..0afc12b50 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/_config.json @@ -0,0 +1,3 @@ +{ + "options": [{ "style": ["type"] }] +} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/class01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/class01-input.svelte new file mode 100644 index 000000000..2f1bc20a7 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/class01-input.svelte @@ -0,0 +1,44 @@ +Click me! + +Click me two! + +Click me three! + +Click me three! + +Text 1 + +Text 2 + +Text 3 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/id01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/id01-input.svelte new file mode 100644 index 000000000..363844f29 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/id01-input.svelte @@ -0,0 +1,33 @@ +Click me! + +Click me too! + +Text 1 + +Text 2 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/type-scss01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/type-scss01-input.svelte new file mode 100644 index 000000000..4edab8017 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/type-scss01-input.svelte @@ -0,0 +1,13 @@ +Click me! + +Text 1 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/type01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/type01-input.svelte new file mode 100644 index 000000000..f8e9f2aa5 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/valid/type/type01-input.svelte @@ -0,0 +1,35 @@ +Click me! + +Click me two! + +Text 1 + +Text 2 + +Text 2 + + From 399fbc6ff655735737293e7386e86c699adf6f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Sat, 14 Dec 2024 22:18:08 +0100 Subject: [PATCH 5/9] feat(consistent-selector-style): added support for checking :global styles --- .../eslint-plugin-svelte/src/rule-types.ts | 1 + .../src/rules/consistent-selector-style.ts | 11 ++- .../invalid/global/_config.json | 3 + .../invalid/global/should-be-id01-errors.yaml | 56 +++++++++++ .../global/should-be-id01-input.svelte | 59 ++++++++++++ .../global/should-be-type01-errors.yaml | 88 ++++++++++++++++++ .../global/should-be-type01-input.svelte | 93 +++++++++++++++++++ 7 files changed, 308 insertions(+), 3 deletions(-) create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/_config.json create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/should-be-id01-errors.yaml create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/should-be-id01-input.svelte create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/should-be-type01-errors.yaml create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/should-be-type01-input.svelte diff --git a/packages/eslint-plugin-svelte/src/rule-types.ts b/packages/eslint-plugin-svelte/src/rule-types.ts index 22e07dde9..3b3e4eaa6 100644 --- a/packages/eslint-plugin-svelte/src/rule-types.ts +++ b/packages/eslint-plugin-svelte/src/rule-types.ts @@ -394,6 +394,7 @@ type SvelteCommentDirective = []|[{ }] // ----- svelte/consistent-selector-style ----- type SvelteConsistentSelectorStyle = []|[{ + checkGlobal?: boolean style?: []|[("class" | "id" | "type")]|[("class" | "id" | "type"), ("class" | "id" | "type")]|[("class" | "id" | "type"), ("class" | "id" | "type"), ("class" | "id" | "type")] }] diff --git a/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts b/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts index c66425223..4e43589f3 100644 --- a/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts +++ b/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts @@ -12,6 +12,7 @@ import { createRule } from '../utils/index.js'; import type { RuleContext, SourceCode } from '../types.js'; interface RuleGlobals { + checkGlobal: boolean; style: string[]; classSelections: Map; idSelections: Map; @@ -33,7 +34,9 @@ export default createRule('consistent-selector-style', { { type: 'object', properties: { - // TODO: Add option to include global selectors + checkGlobal: { + type: 'boolean' + }, style: { type: 'array', items: { @@ -62,6 +65,7 @@ export default createRule('consistent-selector-style', { return {}; } + const checkGlobal = context.options[0]?.checkGlobal ?? false; const style = context.options[0]?.style ?? ['type', 'id', 'class']; const classSelections: Map = new Map(); @@ -99,6 +103,7 @@ export default createRule('consistent-selector-style', { return; } checkSelectorsInPostCSSNode(styleContext.sourceAst, { + checkGlobal, style, classSelections, idSelections, @@ -132,7 +137,7 @@ function checkSelectorsInPostCSSNode(node: AnyNode, ruleGlobals: RuleGlobals): v } if ( (node.type === 'root' || - (node.type === 'rule' && node.selector !== ':global') || + (node.type === 'rule' && (node.selector !== ':global' || ruleGlobals.checkGlobal)) || node.type === 'atrule') && node.nodes !== undefined ) { @@ -154,7 +159,7 @@ function checkSelector(node: SelectorNode, ruleGlobals: RuleGlobals): void { checkTypeSelector(node, ruleGlobals); } if ( - (node.type === 'pseudo' && node.value !== ':global') || + (node.type === 'pseudo' && (node.value !== ':global' || ruleGlobals.checkGlobal)) || node.type === 'root' || node.type === 'selector' ) { diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/_config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/_config.json new file mode 100644 index 000000000..872db17e4 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/_config.json @@ -0,0 +1,3 @@ +{ + "options": [{ "checkGlobal": true }] +} diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/should-be-id01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/should-be-id01-errors.yaml new file mode 100644 index 000000000..11974f271 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/should-be-id01-errors.yaml @@ -0,0 +1,56 @@ +- message: Selector should select by ID instead of class + line: 10 + column: 11 + suggestions: null +- message: Selector should select by ID instead of class + line: 14 + column: 11 + suggestions: null +- message: Selector should select by ID instead of class + line: 18 + column: 11 + suggestions: null +- message: Selector should select by ID instead of class + line: 22 + column: 11 + suggestions: null +- message: Selector should select by ID instead of class + line: 22 + column: 19 + suggestions: null +- message: Selector should select by ID instead of class + line: 26 + column: 11 + suggestions: null +- message: Selector should select by ID instead of class + line: 30 + column: 11 + suggestions: null +- message: Selector should select by ID instead of class + line: 35 + column: 5 + suggestions: null +- message: Selector should select by ID instead of class + line: 39 + column: 5 + suggestions: null +- message: Selector should select by ID instead of class + line: 43 + column: 5 + suggestions: null +- message: Selector should select by ID instead of class + line: 47 + column: 5 + suggestions: null +- message: Selector should select by ID instead of class + line: 47 + column: 13 + suggestions: null +- message: Selector should select by ID instead of class + line: 51 + column: 5 + suggestions: null +- message: Selector should select by ID instead of class + line: 55 + column: 5 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/should-be-id01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/should-be-id01-input.svelte new file mode 100644 index 000000000..0e69dd3c7 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/should-be-id01-input.svelte @@ -0,0 +1,59 @@ +Click me! + +Click me two! + +Text 1 + +Text 3 + + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/should-be-type01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/should-be-type01-errors.yaml new file mode 100644 index 000000000..c6811d24e --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/should-be-type01-errors.yaml @@ -0,0 +1,88 @@ +- message: Selector should select by element type instead of class + line: 12 + column: 11 + suggestions: null +- message: Selector should select by element type instead of class + line: 16 + column: 11 + suggestions: null +- message: Selector should select by element type instead of class + line: 20 + column: 11 + suggestions: null +- message: Selector should select by element type instead of class + line: 24 + column: 11 + suggestions: null +- message: Selector should select by element type instead of class + line: 24 + column: 28 + suggestions: null +- message: Selector should select by element type instead of class + line: 28 + column: 11 + suggestions: null +- message: Selector should select by element type instead of class + line: 32 + column: 11 + suggestions: null +- message: Selector should select by element type instead of ID + line: 36 + column: 11 + suggestions: null +- message: Selector should select by element type instead of ID + line: 40 + column: 11 + suggestions: null +- message: Selector should select by element type instead of ID + line: 44 + column: 15 + suggestions: null +- message: Selector should select by element type instead of ID + line: 48 + column: 11 + suggestions: null +- message: Selector should select by element type instead of class + line: 53 + column: 5 + suggestions: null +- message: Selector should select by element type instead of class + line: 57 + column: 5 + suggestions: null +- message: Selector should select by element type instead of class + line: 61 + column: 5 + suggestions: null +- message: Selector should select by element type instead of class + line: 65 + column: 5 + suggestions: null +- message: Selector should select by element type instead of class + line: 65 + column: 13 + suggestions: null +- message: Selector should select by element type instead of class + line: 69 + column: 5 + suggestions: null +- message: Selector should select by element type instead of class + line: 73 + column: 5 + suggestions: null +- message: Selector should select by element type instead of ID + line: 77 + column: 5 + suggestions: null +- message: Selector should select by element type instead of ID + line: 81 + column: 5 + suggestions: null +- message: Selector should select by element type instead of ID + line: 85 + column: 9 + suggestions: null +- message: Selector should select by element type instead of ID + line: 89 + column: 5 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/should-be-type01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/should-be-type01-input.svelte new file mode 100644 index 000000000..b33b92162 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/consistent-selector-style/invalid/global/should-be-type01-input.svelte @@ -0,0 +1,93 @@ +Click me! + +Click me two! + +Text 1 + +Text 2 + +Italic + + From e2157eaa7afd6ed03f75176465a86c0162bb57c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Sun, 15 Dec 2024 00:01:13 +0100 Subject: [PATCH 6/9] docs(consistent-selector-style): documented rule --- docs/rules/consistent-selector-style.md | 64 ++++++++++++++++++++----- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/docs/rules/consistent-selector-style.md b/docs/rules/consistent-selector-style.md index 0f6d943c6..0334ad273 100644 --- a/docs/rules/consistent-selector-style.md +++ b/docs/rules/consistent-selector-style.md @@ -13,37 +13,79 @@ description: 'enforce a consistent style for CSS selectors' ## :book: Rule Details -This rule reports ???. - - +This rule allows you to set a preferred style for your CSS (& other style language) selectors. In CSS, there is a wide list of options for selecting elements, however, the three most basic types select by element type (i.e. tag name), ID or class. This rule allows you to set a preference for some of these three styles over others. Not all selectors can be used in all situations, however. While class selectors can be used in any situation, ID selectors can only be used to select a single element and type selectors are only applicable when the list of selected elements is the list of all elements of the particular type. To help with this, the rule accepts a list of selector style preferences and reports situations when the given selector can be rewritten using a more preferred style. ```svelte - +Click me! - -``` +Click me too! + +Text one + +Text two + +Text three + + +``` ## :wrench: Options ```json { - "svelte/consistent-selector-style": ["error", {}] + "svelte/consistent-selector-style": [ + "error", + { + "checkGlobal": false, + "style": ["type", "id", "class"] + } + ] } ``` -- +- `checkGlobal` ... Whether to check styles in `:global` blocks as well. Default `false`. +- `style` ... A list of style preferences. Default `["type", "id", "class"]`. ## :books: Further Reading -- +- [CSS selector documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors) ## :mag: Implementation From b1253f75e3fdcb180c66c4ef6c8f2ea9c3fe1662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Tue, 14 Jan 2025 10:22:02 +0100 Subject: [PATCH 7/9] docs(consistent-selector-style): Added clearer description of selector styles --- docs/rules/consistent-selector-style.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/rules/consistent-selector-style.md b/docs/rules/consistent-selector-style.md index 0334ad273..12f7990f9 100644 --- a/docs/rules/consistent-selector-style.md +++ b/docs/rules/consistent-selector-style.md @@ -13,7 +13,12 @@ description: 'enforce a consistent style for CSS selectors' ## :book: Rule Details -This rule allows you to set a preferred style for your CSS (& other style language) selectors. In CSS, there is a wide list of options for selecting elements, however, the three most basic types select by element type (i.e. tag name), ID or class. This rule allows you to set a preference for some of these three styles over others. Not all selectors can be used in all situations, however. While class selectors can be used in any situation, ID selectors can only be used to select a single element and type selectors are only applicable when the list of selected elements is the list of all elements of the particular type. To help with this, the rule accepts a list of selector style preferences and reports situations when the given selector can be rewritten using a more preferred style. +This rule allows you to set a preferred style for your CSS (& other style language) selectors. In CSS, there is a wide list of options for selecting elements, however, the three most basic types are: + +- Selecting by element type (i.e. tag name), such as `a {}` +- Selecting by element ID, such as `#link {}` +- Selecting by element class, such as `.link {}` + This rule allows you to set a preference for some of these three styles over others. Not all selectors can be used in all situations, however. While class selectors can be used in any situation, ID selectors can only be used to select a single element and type selectors are only applicable when the list of selected elements is the list of all elements of the particular type. To help with this, the rule accepts a list of selector style preferences and reports situations when the given selector can be rewritten using a more preferred style. From 91940003bb6fdbb18d1c913ed4e31f8c44d77374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Tue, 14 Jan 2025 14:40:06 +0100 Subject: [PATCH 8/9] chore(consistent-selector-style): shorter array equality function --- .../src/rules/consistent-selector-style.ts | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts b/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts index 4e43589f3..c09f6514b 100644 --- a/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts +++ b/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts @@ -275,18 +275,5 @@ function couldBeType( * Compares two arrays for item equality */ function arrayEquals(array1: AST.SvelteHTMLElement[], array2: AST.SvelteHTMLElement[]): boolean { - function comparator(a: AST.SvelteHTMLElement, b: AST.SvelteHTMLElement): number { - return a.range[0] - b.range[0]; - } - - const array2Sorted = array2.slice().sort(comparator); - return ( - array1.length === array2.length && - array1 - .slice() - .sort(comparator) - .every(function (value, index) { - return value === array2Sorted[index]; - }) - ); + return array1.length === array2.length && array1.every((e) => array2.includes(e)); } From 70e1add5398e21300280ec125da6d1428e97ab7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Tue, 14 Jan 2025 15:10:21 +0100 Subject: [PATCH 9/9] chore(consistent-selector-style): moved functions into create() and remove RuleGlobals --- .../src/rules/consistent-selector-style.ts | 272 +++++++++--------- 1 file changed, 128 insertions(+), 144 deletions(-) diff --git a/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts b/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts index c09f6514b..00134c5d3 100644 --- a/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts +++ b/packages/eslint-plugin-svelte/src/rules/consistent-selector-style.ts @@ -9,18 +9,6 @@ import type { import { findClassesInAttribute } from '../utils/ast-utils.js'; import { getSourceCode } from '../utils/compat.js'; import { createRule } from '../utils/index.js'; -import type { RuleContext, SourceCode } from '../types.js'; - -interface RuleGlobals { - checkGlobal: boolean; - style: string[]; - classSelections: Map; - idSelections: Map; - typeSelections: Map; - context: RuleContext; - getStyleSelectorAST: NonNullable; - styleSelectorNodeLoc: NonNullable; -} export default createRule('consistent-selector-style', { meta: { @@ -61,9 +49,15 @@ export default createRule('consistent-selector-style', { }, create(context) { const sourceCode = getSourceCode(context); - if (!sourceCode.parserServices.isSvelte) { + if ( + !sourceCode.parserServices.isSvelte || + sourceCode.parserServices.getStyleSelectorAST === undefined || + sourceCode.parserServices.styleSelectorNodeLoc === undefined + ) { return {}; } + const getStyleSelectorAST = sourceCode.parserServices.getStyleSelectorAST; + const styleSelectorNodeLoc = sourceCode.parserServices.styleSelectorNodeLoc; const checkGlobal = context.options[0]?.checkGlobal ?? false; const style = context.options[0]?.style ?? ['type', 'id', 'class']; @@ -72,6 +66,123 @@ export default createRule('consistent-selector-style', { const idSelections: Map = new Map(); const typeSelections: Map = new Map(); + /** + * Checks selectors in a given PostCSS node + */ + function checkSelectorsInPostCSSNode(node: AnyNode): void { + if (node.type === 'rule') { + checkSelector(getStyleSelectorAST(node)); + } + if ( + (node.type === 'root' || + (node.type === 'rule' && (node.selector !== ':global' || checkGlobal)) || + node.type === 'atrule') && + node.nodes !== undefined + ) { + node.nodes.flatMap((node) => checkSelectorsInPostCSSNode(node)); + } + } + + /** + * Checks an individual selector + */ + function checkSelector(node: SelectorNode): void { + if (node.type === 'class') { + checkClassSelector(node); + } + if (node.type === 'id') { + checkIdSelector(node); + } + if (node.type === 'tag') { + checkTypeSelector(node); + } + if ( + (node.type === 'pseudo' && (node.value !== ':global' || checkGlobal)) || + node.type === 'root' || + node.type === 'selector' + ) { + node.nodes.flatMap((node) => checkSelector(node)); + } + } + + /** + * Checks a class selector + */ + function checkClassSelector(node: SelectorClass): void { + const selection = classSelections.get(node.value) ?? []; + for (const styleValue of style) { + if (styleValue === 'class') { + return; + } + if (styleValue === 'id' && canUseIdSelector(selection)) { + context.report({ + messageId: 'classShouldBeId', + loc: styleSelectorNodeLoc(node) as AST.SourceLocation + }); + return; + } + if (styleValue === 'type' && canUseTypeSelector(selection, typeSelections)) { + context.report({ + messageId: 'classShouldBeType', + loc: styleSelectorNodeLoc(node) as AST.SourceLocation + }); + return; + } + } + } + + /** + * Checks an ID selector + */ + function checkIdSelector(node: SelectorIdentifier): void { + const selection = idSelections.get(node.value) ?? []; + for (const styleValue of style) { + if (styleValue === 'class') { + context.report({ + messageId: 'idShouldBeClass', + loc: styleSelectorNodeLoc(node) as AST.SourceLocation + }); + return; + } + if (styleValue === 'id') { + return; + } + if (styleValue === 'type' && canUseTypeSelector(selection, typeSelections)) { + context.report({ + messageId: 'idShouldBeType', + loc: styleSelectorNodeLoc(node) as AST.SourceLocation + }); + return; + } + } + } + + /** + * Checks a type selector + */ + function checkTypeSelector(node: SelectorTag): void { + const selection = typeSelections.get(node.value) ?? []; + for (const styleValue of style) { + if (styleValue === 'class') { + context.report({ + messageId: 'typeShouldBeClass', + loc: styleSelectorNodeLoc(node) as AST.SourceLocation + }); + return; + } + if (styleValue === 'id' && canUseIdSelector(selection)) { + context.report({ + messageId: 'typeShouldBeId', + loc: styleSelectorNodeLoc(node) as AST.SourceLocation + }); + return; + } + if (styleValue === 'type') { + return; + } + } + } + return { SvelteElement(node) { if (node.kind !== 'html') { @@ -97,21 +208,11 @@ export default createRule('consistent-selector-style', { const styleContext = sourceCode.parserServices.getStyleContext!(); if ( styleContext.status !== 'success' || - sourceCode.parserServices.getStyleSelectorAST === undefined || - sourceCode.parserServices.styleSelectorNodeLoc === undefined + sourceCode.parserServices.getStyleSelectorAST === undefined ) { return; } - checkSelectorsInPostCSSNode(styleContext.sourceAst, { - checkGlobal, - style, - classSelections, - idSelections, - typeSelections, - context, - getStyleSelectorAST: sourceCode.parserServices.getStyleSelectorAST, - styleSelectorNodeLoc: sourceCode.parserServices.styleSelectorNodeLoc - }); + checkSelectorsInPostCSSNode(styleContext.sourceAst); } }; } @@ -128,134 +229,17 @@ function addToArrayMap( map.set(key, (map.get(key) ?? []).concat(value)); } -/** - * Checks selectors in a given PostCSS node - */ -function checkSelectorsInPostCSSNode(node: AnyNode, ruleGlobals: RuleGlobals): void { - if (node.type === 'rule') { - checkSelector(ruleGlobals.getStyleSelectorAST(node), ruleGlobals); - } - if ( - (node.type === 'root' || - (node.type === 'rule' && (node.selector !== ':global' || ruleGlobals.checkGlobal)) || - node.type === 'atrule') && - node.nodes !== undefined - ) { - node.nodes.flatMap((node) => checkSelectorsInPostCSSNode(node, ruleGlobals)); - } -} - -/** - * Checks an individual selector - */ -function checkSelector(node: SelectorNode, ruleGlobals: RuleGlobals): void { - if (node.type === 'class') { - checkClassSelector(node, ruleGlobals); - } - if (node.type === 'id') { - checkIdSelector(node, ruleGlobals); - } - if (node.type === 'tag') { - checkTypeSelector(node, ruleGlobals); - } - if ( - (node.type === 'pseudo' && (node.value !== ':global' || ruleGlobals.checkGlobal)) || - node.type === 'root' || - node.type === 'selector' - ) { - node.nodes.flatMap((node) => checkSelector(node, ruleGlobals)); - } -} - -/** - * Checks a class selector - */ -function checkClassSelector(node: SelectorClass, ruleGlobals: RuleGlobals): void { - const selection = ruleGlobals.classSelections.get(node.value) ?? []; - for (const styleValue of ruleGlobals.style) { - if (styleValue === 'class') { - return; - } - if (styleValue === 'id' && couldBeId(selection)) { - ruleGlobals.context.report({ - messageId: 'classShouldBeId', - loc: ruleGlobals.styleSelectorNodeLoc(node) as AST.SourceLocation - }); - return; - } - if (styleValue === 'type' && couldBeType(selection, ruleGlobals.typeSelections)) { - ruleGlobals.context.report({ - messageId: 'classShouldBeType', - loc: ruleGlobals.styleSelectorNodeLoc(node) as AST.SourceLocation - }); - return; - } - } -} - -/** - * Checks an ID selector - */ -function checkIdSelector(node: SelectorIdentifier, ruleGlobals: RuleGlobals): void { - const selection = ruleGlobals.idSelections.get(node.value) ?? []; - for (const styleValue of ruleGlobals.style) { - if (styleValue === 'class') { - ruleGlobals.context.report({ - messageId: 'idShouldBeClass', - loc: ruleGlobals.styleSelectorNodeLoc(node) as AST.SourceLocation - }); - return; - } - if (styleValue === 'id') { - return; - } - if (styleValue === 'type' && couldBeType(selection, ruleGlobals.typeSelections)) { - ruleGlobals.context.report({ - messageId: 'idShouldBeType', - loc: ruleGlobals.styleSelectorNodeLoc(node) as AST.SourceLocation - }); - return; - } - } -} - -/** - * Checks a type selector - */ -function checkTypeSelector(node: SelectorTag, ruleGlobals: RuleGlobals): void { - const selection = ruleGlobals.typeSelections.get(node.value) ?? []; - for (const styleValue of ruleGlobals.style) { - if (styleValue === 'class') { - ruleGlobals.context.report({ - messageId: 'typeShouldBeClass', - loc: ruleGlobals.styleSelectorNodeLoc(node) as AST.SourceLocation - }); - return; - } - if (styleValue === 'id' && couldBeId(selection)) { - ruleGlobals.context.report({ - messageId: 'typeShouldBeId', - loc: ruleGlobals.styleSelectorNodeLoc(node) as AST.SourceLocation - }); - return; - } - if (styleValue === 'type') { - return; - } - } -} - /** * Checks whether a given selection could be obtained using an ID selector */ -function couldBeId(selection: AST.SvelteHTMLElement[]): boolean { +function canUseIdSelector(selection: AST.SvelteHTMLElement[]): boolean { return selection.length <= 1; } /** * Checks whether a given selection could be obtained using a type selector */ -function couldBeType( +function canUseTypeSelector( selection: AST.SvelteHTMLElement[], typeSelections: Map ): boolean {