eslint-plugin-conventions 4.0.5 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +131 -0
  2. package/LICENSE +23 -0
  3. package/README.md +51 -21
  4. package/package.json +20 -3
  5. package/src/index.d.ts +49 -0
  6. package/src/index.js +15 -1
  7. package/src/index.js.map +1 -1
  8. package/src/lib/eslint-plugin-conventions.js.map +1 -1
  9. package/src/oxlint.d.ts +20 -0
  10. package/src/oxlint.js +22 -0
  11. package/src/oxlint.js.map +1 -0
  12. package/src/rules/conventions/analytics-event-naming.d.ts +41 -0
  13. package/src/rules/conventions/analytics-event-naming.js +104 -0
  14. package/src/rules/conventions/analytics-event-naming.js.map +1 -0
  15. package/src/rules/conventions/consistent-existence-index-check.js +5 -1
  16. package/src/rules/conventions/consistent-existence-index-check.js.map +1 -1
  17. package/src/rules/conventions/expiring-todo-comments.js +18 -2
  18. package/src/rules/conventions/expiring-todo-comments.js.map +1 -1
  19. package/src/rules/conventions/filename-case.js +9 -1
  20. package/src/rules/conventions/filename-case.js.map +1 -1
  21. package/src/rules/conventions/no-commented-code.js +3 -2
  22. package/src/rules/conventions/no-commented-code.js.map +1 -1
  23. package/src/rules/conventions/no-console-spaces.js +5 -0
  24. package/src/rules/conventions/no-console-spaces.js.map +1 -1
  25. package/src/rules/conventions/no-json-schema-tags.js +2 -1
  26. package/src/rules/conventions/no-json-schema-tags.js.map +1 -1
  27. package/src/rules/conventions/no-magic-numbers.d.ts +41 -0
  28. package/src/rules/conventions/no-magic-numbers.js +205 -0
  29. package/src/rules/conventions/no-magic-numbers.js.map +1 -0
  30. package/src/rules/conventions/no-raw-cross-property-href.d.ts +24 -0
  31. package/src/rules/conventions/no-raw-cross-property-href.js +86 -0
  32. package/src/rules/conventions/no-raw-cross-property-href.js.map +1 -0
  33. package/src/rules/conventions/prefer-code-point.js +4 -1
  34. package/src/rules/conventions/prefer-code-point.js.map +1 -1
  35. package/src/rules/conventions/prefer-dependency-version-strategy.d.ts +5 -5
  36. package/src/rules/conventions/prefer-dependency-version-strategy.js +1 -0
  37. package/src/rules/conventions/prefer-dependency-version-strategy.js.map +1 -1
  38. package/src/rules/conventions/prefer-dom-node-text-content.js +3 -0
  39. package/src/rules/conventions/prefer-dom-node-text-content.js.map +1 -1
  40. package/src/rules/conventions/require-data-testid.d.ts +56 -0
  41. package/src/rules/conventions/require-data-testid.js +209 -0
  42. package/src/rules/conventions/require-data-testid.js.map +1 -0
  43. package/src/rules/conventions/utm-taxonomy.d.ts +25 -0
  44. package/src/rules/conventions/utm-taxonomy.js +113 -0
  45. package/src/rules/conventions/utm-taxonomy.js.map +1 -0
  46. package/src/rules/deprecation/no-deprecated-api.js +4 -0
  47. package/src/rules/deprecation/no-deprecated-api.js.map +1 -1
package/CHANGELOG.md ADDED
@@ -0,0 +1,131 @@
1
+ ## 4.1.0
2
+
3
+ ### Minor Changes
4
+
5
+ - [#129](https://github.com/ofri-peretz/eslint/pull/129) [`90b970c`](https://github.com/ofri-peretz/eslint/commit/90b970c547f867ee79ec393ecb4da3f3e22f11f0) Thanks [@ofri-peretz](https://github.com/ofri-peretz)! - Three new rules at `error` severity enforcing the Observability cluster of the design philosophies (ANALYTICS_PHILOSOPHY.md + UTM_PHILOSOPHY.md):
6
+ - **`utm-taxonomy`** — `utm_source` and `utm_medium` query-param values in any URL string literal must match the fixed taxonomy. Free-text values (`Blog`, `blog_v2`, `BLOG`) destroy joinability in PostHog and are forbidden.
7
+ - **`no-raw-cross-property-href`** — Hand-written `<a href="https://*.interlace.tools/…">` and `<a href="https://ofriperetz.dev/…">` JSX literals are flagged. The blessed escape hatch is the per-property `buildUtmHref()` helper from `lib/utm.ts`.
8
+ - **`analytics-event-naming`** — Vendor-neutral. Matches `<obj>.capture()` (PostHog), `<obj>.track()` (Segment / Mixpanel / Amplitude), and bare `track()` (our primitive). Event names must follow `category:object_action` (lowercase snake_case) with action from a fixed verb list; `$`-prefixed reserved events are exempt; template-literal event names are forbidden.
9
+
10
+ Also fixes `compareVersions` in `expiring-todo-comments` to normalise wildcards (`24.x` in `engines.node`) — without this, `parseSemver` returned `null` and the comparator falsely matched every `>= engine TODO` as expired.
11
+
12
+ - [#148](https://github.com/ofri-peretz/eslint/pull/148) [`82718c2`](https://github.com/ofri-peretz/eslint/commit/82718c282895710d42c36d4679fb24d47f1c35c7) Thanks [@ofri-peretz](https://github.com/ofri-peretz)! - feat(no-magic-numbers): add conventions/no-magic-numbers — closes prob_magic_numbers ILB-Arena-Quality FN
13
+
14
+ Flags numeric literals that lack a named constant, catching the magic number
15
+ code smell that makes intent unclear.
16
+
17
+ **Built-in allowlist:** `-1, 0, 1, 2` are always allowed as universally idiomatic.
18
+
19
+ **Context-aware skips (by default):**
20
+ - `const` / `export const` declarations — the literal IS the named constant
21
+ - Array index access: `items[3]` (`ignoreArrayIndexes: true`)
22
+ - Default parameter values: `function f(n = 1000) {}`
23
+ - TypeScript enum initializers: `enum Status { Active = 1 }`
24
+ - Numeric object property keys: `{ 404: 'Not Found' }`
25
+
26
+ **Options:** `ignore`, `ignoreArrayIndexes`, `ignoreDefaultValues`, `ignoreEnums`, `ignoreBitwiseExpressions`.
27
+
28
+ Added at `warn` severity in `conventions/recommended`.
29
+
30
+ ### Patch Changes
31
+
32
+ - [#154](https://github.com/ofri-peretz/eslint/pull/154) [`62e67a1`](https://github.com/ofri-peretz/eslint/commit/62e67a154a858b284899e17cfe39606e6bc08427) Thanks [@ofri-peretz](https://github.com/ofri-peretz)! - `no-magic-numbers`: add extract-const suggestion fixer. IDEs now offer a one-click "Extract to named constant" action that inserts a `const MAGIC_<value>` declaration before the containing statement and replaces the literal.
33
+
34
+ - Updated dependencies [[`736a5fe`](https://github.com/ofri-peretz/eslint/commit/736a5fed47e673f6157ea900b29fe2a54e4bc7df)]:
35
+ - @interlace/eslint-devkit@1.4.1
36
+
37
+ ## 4.0.7 (2026-02-09)
38
+
39
+ This was a version bump only for eslint-plugin-conventions to align it with other projects, there were no code changes.
40
+
41
+ ## [4.0.5] - 2026-02-08
42
+
43
+ This was a version bump only for eslint-plugin-conventions to align it with other projects, there were no code changes.
44
+
45
+ ## [4.0.4] - 2026-02-08
46
+
47
+ ### Bug Fixes
48
+
49
+ - align codecov component IDs with full package names ([2831b968](https://github.com/ofri-peretz/eslint/commit/2831b968))
50
+
51
+ ### Documentation
52
+
53
+ - fix changelog header format across all packages ([c3a15082](https://github.com/ofri-peretz/eslint/commit/c3a15082))
54
+
55
+ ### ❤️ Thank You
56
+
57
+ - Ofri Peretz
58
+
59
+ ## [4.0.3] - 2026-02-06
60
+
61
+ ### Bug Fixes
62
+
63
+ - align codecov component names and update docs components ([0a59a86c](https://github.com/ofri-peretz/eslint/commit/0a59a86c))
64
+
65
+ ### ❤️ Thank You
66
+
67
+ - Ofri Peretz
68
+
69
+ ## [4.0.2] - 2026-02-02
70
+
71
+ This was a version bump only for eslint-plugin-conventions to align it with other projects, there were no code changes.
72
+
73
+ # Changelog
74
+
75
+ All notable changes to `eslint-plugin-conventions` will be documented in this file.
76
+
77
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
78
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
79
+
80
+ ### Documentation
81
+
82
+ - 📘 Launched new documentation site: [eslint.interlace.tools](https://eslint.interlace.tools/)
83
+ - 📝 Achieved 100% documentation parity (both .md and .mdx files)
84
+
85
+ ## [4.0.1] - 2026-02-02
86
+
87
+ This was a version bump only for eslint-plugin-conventions to align it with other projects, there were no code changes.
88
+
89
+ ## [4.0.0] - 2026-02-02
90
+
91
+ This was a version bump only for eslint-plugin-conventions to align it with other projects, there were no code changes.
92
+
93
+ ## [3.0.0] - 2026-02-02
94
+
95
+ This was a version bump only for eslint-plugin-conventions to align it with other projects, there were no code changes.
96
+
97
+ ## [1.0.0] - 2026-01-26
98
+
99
+ ### Added
100
+
101
+ - Initial stable release with 9 convention rules
102
+ - LLM-optimized error messages for AI-assisted development
103
+ - 100% test coverage across all rules
104
+ - ESLint 9 flat config support
105
+ - TypeScript type definitions for all rule options
106
+
107
+ ### Rules
108
+
109
+ | Rule | Description | 💼 | ⚠️ |
110
+ | :----------------------------------- | :---------------------------------------------------- | :-: | :-: |
111
+ | `no-commented-code` | Disallow commented-out code blocks | 💼 | ⚠️ |
112
+ | `expiring-todo-comments` | Enforce expiration dates on TODO comments | 💼 | ⚠️ |
113
+ | `prefer-code-point` | Prefer `codePointAt` over `charCodeAt` for Unicode | | |
114
+ | `prefer-dom-node-text-content` | Prefer `textContent` over `innerText` for performance | | |
115
+ | `no-console-spaces` | Disallow leading/trailing spaces in console calls | | |
116
+ | `no-deprecated-api` | Disallow usage of deprecated Node.js APIs | 💼 | ⚠️ |
117
+ | `prefer-dependency-version-strategy` | Enforce consistent version strategies | | |
118
+ | `filename-case` | Enforce consistent file naming conventions | | |
119
+ | `consistent-existence-index-check` | Enforce consistent array index existence checks | | |
120
+
121
+ ### Presets
122
+
123
+ - `recommended` - Balanced conventions for most teams
124
+
125
+ ### Known Limitations
126
+
127
+ Documented in `docs/KNOWN-LIMITATIONS.md`:
128
+
129
+ - `filename-case`: Framework-required names (e.g., `webpack.config.js`) require manual exclude lists
130
+ - `no-deprecated-api`: May not detect usage through wrapper libraries
131
+ - `expiring-todo-comments`: Requires consistent date formats (ISO 8601 recommended)
package/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Ofri Peretz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+
package/README.md CHANGED
@@ -1,23 +1,24 @@
1
1
  <p align="center">
2
- <a href="https://eslint.interlace.tools" target="blank"><img src="https://eslint.interlace.tools/eslint-interlace-logo-light.svg" alt="ESLint Interlace Logo" width="120" /></a>
2
+ <a href="https://eslint.interlace.tools/?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions" target="blank"><img src="https://eslint.interlace.tools/eslint-interlace-logo-light.svg" alt="ESLint Interlace Logo" width="120" /></a>
3
3
  </p>
4
4
 
5
5
  <p align="center">
6
- Security-focused ESLint plugin.
6
+ Project conventions: naming, file structure, and code style consistency.
7
7
  </p>
8
8
 
9
9
  <p align="center">
10
10
  <a href="https://www.npmjs.com/package/eslint-plugin-conventions" target="_blank"><img src="https://img.shields.io/npm/v/eslint-plugin-conventions.svg" alt="NPM Version" /></a>
11
11
  <a href="https://www.npmjs.com/package/eslint-plugin-conventions" target="_blank"><img src="https://img.shields.io/npm/dm/eslint-plugin-conventions.svg" alt="NPM Downloads" /></a>
12
12
  <a href="https://opensource.org/licenses/MIT" target="_blank"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="Package License" /></a>
13
- <a href="https://app.codecov.io/gh/ofri-peretz/eslint/components?components%5B0%5D=conventions" target="_blank"><img src="https://codecov.io/gh/ofri-peretz/eslint/graph/badge.svg?component=eslint-plugin-conventions" alt="Codecov" /></a>
13
+ <a href="https://app.codecov.io/gh/ofri-peretz/eslint/components?components%5B0%5D=conventions" target="_blank"><img src="https://codecov.io/gh/ofri-peretz/eslint/graph/badge.svg?component=conventions" alt="Codecov" /></a>
14
14
  <a href="https://github.com/ofri-peretz/eslint" target="_blank"><img src="https://img.shields.io/badge/Since-Dec_2025-blue?logo=rocket&logoColor=white" alt="Since Dec 2025" /></a>
15
15
  </p>
16
16
 
17
+ > ⭐ If this plugin caught a real bug for you, [**star the repo**](https://github.com/ofri-peretz/eslint) — it's the signal that keeps these rules maintained.
18
+
17
19
  ## Description
18
20
 
19
- This plugin provides Security-focused ESLint plugin.
20
- By using this plugin, you can proactively identify and mitigate security risks across your entire codebase.
21
+ This plugin provides Project conventions: naming, file structure, and code style consistency.
21
22
 
22
23
  ## Philosophy
23
24
 
@@ -25,12 +26,12 @@ By using this plugin, you can proactively identify and mitigate security risks a
25
26
 
26
27
  ## Getting Started
27
28
 
28
- - To check out the [guide](https://eslint.interlace.tools/docs/quality/plugin-conventions), visit [eslint.interlace.tools](https://eslint.interlace.tools). 📚
29
- - 要查看中文 [指南](https://eslint.interlace.tools/docs/quality/plugin-conventions), 请访问 [eslint.interlace.tools](https://eslint.interlace.tools). 📚
30
- - [가이드](https://eslint.interlace.tools/docs/quality/plugin-conventions) 문서는 [eslint.interlace.tools](https://eslint.interlace.tools)에서 확인하실 수 있습니다. 📚
31
- - [ガイド](https://eslint.interlace.tools/docs/quality/plugin-conventions)は [eslint.interlace.tools](https://eslint.interlace.tools)でご確認ください。 📚
32
- - Para ver la [guía](https://eslint.interlace.tools/docs/quality/plugin-conventions), visita [eslint.interlace.tools](https://eslint.interlace.tools). 📚
33
- - للاطلاع على [الدليل](https://eslint.interlace.tools/docs/quality/plugin-conventions)، قم بزيارة [eslint.interlace.tools](https://eslint.interlace.tools). 📚
29
+ - To check out the [guide](https://eslint.interlace.tools/docs/quality/plugin-conventions?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions), visit [eslint.interlace.tools](https://eslint.interlace.tools/?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions). 📚
30
+ - 要查看中文 [指南](https://eslint.interlace.tools/docs/quality/plugin-conventions?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions), 请访问 [eslint.interlace.tools](https://eslint.interlace.tools/?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions). 📚
31
+ - [가이드](https://eslint.interlace.tools/docs/quality/plugin-conventions?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions) 문서는 [eslint.interlace.tools](https://eslint.interlace.tools/?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions)에서 확인하실 수 있습니다. 📚
32
+ - [ガイド](https://eslint.interlace.tools/docs/quality/plugin-conventions?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions)は [eslint.interlace.tools](https://eslint.interlace.tools/?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions)でご確認ください。 📚
33
+ - Para ver la [guía](https://eslint.interlace.tools/docs/quality/plugin-conventions?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions), visita [eslint.interlace.tools](https://eslint.interlace.tools/?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions). 📚
34
+ - للاطلاع على [الدليل](https://eslint.interlace.tools/docs/quality/plugin-conventions?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions)، قم بزيارة [eslint.interlace.tools](https://eslint.interlace.tools/?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions). 📚
34
35
 
35
36
  ```bash
36
37
  npm install eslint-plugin-conventions --save-dev
@@ -53,6 +54,14 @@ export default [conventions.configs.recommended];
53
54
 
54
55
  ---
55
56
 
57
+ ## 📦 Compatibility
58
+ | Package | Version |
59
+ | :--- | :--- |
60
+ | ESLint | `^8.0.0 \|\| ^9.0.0 \|\| ^10.0.0` |
61
+ | Node.js | `>=18.0.0` |
62
+
63
+ See the [ESLint Version Support Policy](../../docs/ESLINT_VERSION_SUPPORT.md) — current ecosystem share data, the 20% gate, and the forward-looking exception that covers v10.
64
+
56
65
  ## Rules
57
66
 
58
67
  **Legend**
@@ -60,17 +69,29 @@ export default [conventions.configs.recommended];
60
69
  | Icon | Description |
61
70
  | :---: | :--- |
62
71
  | 💼 | **Recommended**: Included in the recommended preset. |
63
- | ⚠️ | **Warns**: Set towarn in recommended preset. |
72
+ | ⚠️ | **Warns**: Set to warn in recommended preset. |
64
73
  | 🔧 | **Auto-fixable**: Automatically fixable by the `--fix` CLI option. |
65
74
  | 💡 | **Suggestions**: Providing code suggestions in IDE. |
66
75
  | 🚫 | **Deprecated**: This rule is deprecated. |
67
-
68
- | Rule | CWE | OWASP | CVSS | Description | 💼 | ⚠️ | 🔧 | 💡 | 🚫 |
69
- | :--- | :---: | :---: | :---: | :--- | :---: | :---: | :---: | :---: | :---: |
70
- | [conventions](https://eslint.interlace.tools/docs/quality/plugin-conventions/rules/conventions) | | | | Enforce conventions | | | | | |
71
- | [deprecation](https://eslint.interlace.tools/docs/quality/plugin-conventions/rules/deprecation) | | | | Enforce deprecation | | | | | |
72
- | [development](https://eslint.interlace.tools/docs/quality/plugin-conventions/rules/development) | | | | Enforce development | | | | | |
73
-
76
+ | 🟢 | **Type-unaware**: AST-only, runs in oxlint JS-plugin tier. |
77
+ | 🟡 | **Type-aware (refining)**: pure-AST primary path; types refine precision. |
78
+ | 🟠 | **Type-aware (graceful)**: requires TS program; silent without it. |
79
+
80
+ <!-- AUTO-GENERATED:RULES_TABLE:START - Do not edit manually -->
81
+ | Rule | CWE | OWASP | CVSS | Description | 🧠 | 💼 | ⚠️ | 🔧 | 💡 | 🚫 |
82
+ | :--- | :---: | :---: | :---: | :--- | :---: | :---: | :---: | :---: | :---: | :---: |
83
+ | [consistent-existence-index-check](https://eslint.interlace.tools/docs/quality/plugin-conventions/rules/consistent-existence-index-check?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions) | | | | Enforce consistent style for checking if an element exists in an array | 🟢 | | | | 💡 | |
84
+ | [expiring-todo-comments](https://eslint.interlace.tools/docs/quality/plugin-conventions/rules/expiring-todo-comments?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions) | | | | Add expiration conditions to TODO comments to prevent forgotten tasks. This rule is part of eslint-plugin-c… | 🟢 | | ⚠️ | | 💡 | |
85
+ | [filename-case](https://eslint.interlace.tools/docs/quality/plugin-conventions/rules/filename-case?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions) | | | | Enforce filename case conventions for consistency across your codebase | 🟢 | | | | 💡 | |
86
+ | [no-commented-code](https://eslint.interlace.tools/docs/quality/plugin-conventions/rules/no-commented-code?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions) | | | | ESLint Rule: no-commented-code with LLM-optimized suggestions and auto-fix capabilities. | 🟢 | | ⚠️ | | 💡 | |
87
+ | [no-console-spaces](https://eslint.interlace.tools/docs/quality/plugin-conventions/rules/no-console-spaces?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions) | | | | Disallow leading/trailing whitespace in console arguments. This rule is part of eslint-plugin-conventions. | 🟢 | | | | 💡 | |
88
+ | [no-deprecated-api](https://eslint.interlace.tools/docs/quality/plugin-conventions/rules/no-deprecated-api?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions) | CWE-1078 | | | Prevent usage of deprecated APIs with migration context and timeline. This rule is part of eslint-plugin-co… | 🟢 | | ⚠️ | | 💡 | |
89
+ | [no-json-schema-tags](https://eslint.interlace.tools/docs/quality/plugin-conventions/rules/no-json-schema-tags?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions) | | | | Disallow JSON Schema keywords (e.g. @minimum, @maximum, @pattern, @format) used as JSDoc tags. | 🟢 | | | | 💡 | |
90
+ | [prefer-code-point](https://eslint.interlace.tools/docs/quality/plugin-conventions/rules/prefer-code-point?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions) | | | | Prefer String.codePointAt() over String.charCodeAt(). This rule is part of eslint-plugin-conventions. | 🟢 | | | | 💡 | |
91
+ | [prefer-dependency-version-strategy](https://eslint.interlace.tools/docs/quality/plugin-conventions/rules/prefer-dependency-version-strategy?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions) | | | | Enforce consistent version strategy (caret ^, tilde ~, exact, range, or any) for package.json dependencies.… | 🟢 | | | | 💡 | |
92
+ | [prefer-dom-node-text-content](https://eslint.interlace.tools/docs/quality/plugin-conventions/rules/prefer-dom-node-text-content?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions) | | | | Prefer textContent over innerText. This rule is part of eslint-plugin-conventions. | 🟢 | | | | 💡 | |
93
+ | [require-data-testid](https://eslint.interlace.tools/docs/quality/plugin-conventions/rules/require-data-testid?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions) | | | | Require stable data-testid attributes on interactive elements for end-to-end test reliability | 🟢 | | | | 💡 | |
94
+ <!-- AUTO-GENERATED:RULES_TABLE:END -->
74
95
  ## 🔗 Related ESLint Plugins
75
96
 
76
97
  Part of the **Interlace ESLint Ecosystem** — AI-native security plugins with LLM-optimized error messages:
@@ -79,7 +100,7 @@ Part of the **Interlace ESLint Ecosystem** — AI-native security plugins with L
79
100
  | :--- | :---: | :--- |
80
101
  | [`eslint-plugin-secure-coding`](https://www.npmjs.com/package/eslint-plugin-secure-coding) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-secure-coding.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-secure-coding) | General security rules & OWASP guidelines. |
81
102
  | [`eslint-plugin-pg`](https://www.npmjs.com/package/eslint-plugin-pg) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-pg.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-pg) | PostgreSQL security & best practices. |
82
- | [`eslint-plugin-crypto`](https://www.npmjs.com/package/eslint-plugin-crypto) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-crypto.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-crypto) | NodeJS Cryptography security rules. |
103
+ | [`eslint-plugin-node-security`](https://www.npmjs.com/package/eslint-plugin-node-security) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-node-security.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-node-security) | Node.js core-module security (fs, child_process, vm, crypto, Buffer). |
83
104
  | [`eslint-plugin-jwt`](https://www.npmjs.com/package/eslint-plugin-jwt) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-jwt.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-jwt) | JWT security & best practices. |
84
105
  | [`eslint-plugin-browser-security`](https://www.npmjs.com/package/eslint-plugin-browser-security) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-browser-security.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-browser-security) | Browser-specific security & XSS prevention. |
85
106
  | [`eslint-plugin-express-security`](https://www.npmjs.com/package/eslint-plugin-express-security) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-express-security.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-express-security) | Express.js security hardening rules. |
@@ -89,10 +110,19 @@ Part of the **Interlace ESLint Ecosystem** — AI-native security plugins with L
89
110
  | [`eslint-plugin-vercel-ai-security`](https://www.npmjs.com/package/eslint-plugin-vercel-ai-security) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-vercel-ai-security.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-vercel-ai-security) | Vercel AI SDK security hardening. |
90
111
  | [`eslint-plugin-import-next`](https://www.npmjs.com/package/eslint-plugin-import-next) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-import-next.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-import-next) | Next-gen import sorting & architecture. |
91
112
 
113
+ <!-- INTERLACE:STAR_CTA:START -->
114
+ ## ⭐ Support & follow
115
+
116
+ If this plugin caught a real bug for you, **[star the repo](https://github.com/ofri-peretz/eslint)** — stars are the signal that keeps the Interlace ESLint ecosystem maintained — and **[follow the writeups on Dev.to](https://dev.to/ofri-peretz)** for the benchmarks and security research behind these rules.
117
+
118
+ [![GitHub stars](https://img.shields.io/github/stars/ofri-peretz/eslint?style=social)](https://github.com/ofri-peretz/eslint)
119
+
120
+ <!-- INTERLACE:STAR_CTA:END -->
121
+
92
122
  ## 📄 License
93
123
 
94
124
  MIT © [Ofri Peretz](https://github.com/ofri-peretz)
95
125
 
96
126
  <p align="center">
97
- <a href="https://eslint.interlace.tools/docs/quality/plugin-conventions"><img src="https://eslint.interlace.tools/images/og-conventions.png" alt="ESLint Interlace Plugin" width="100%" /></a>
127
+ <a href="https://eslint.interlace.tools/docs/quality/plugin-conventions?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-conventions"><img src="https://eslint.interlace.tools/images/og-conventions.png" alt="ESLint Interlace Plugin" width="100%" /></a>
98
128
  </p>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-conventions",
3
- "version": "4.0.5",
3
+ "version": "4.1.0",
4
4
  "description": "ESLint rules for team-specific disciplinary patterns and code conventions.",
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -9,6 +9,10 @@
9
9
  ".": {
10
10
  "types": "./src/index.d.ts",
11
11
  "default": "./src/index.js"
12
+ },
13
+ "./oxlint": {
14
+ "types": "./src/oxlint.d.ts",
15
+ "default": "./src/oxlint.js"
12
16
  }
13
17
  },
14
18
  "author": "Ofri Peretz <ofriperetzdev@gmail.com>",
@@ -48,8 +52,21 @@
48
52
  "url": "https://github.com/ofri-peretz/eslint",
49
53
  "directory": "packages/eslint-plugin-conventions"
50
54
  },
51
- "homepage": "https://github.com/ofri-peretz/eslint/tree/main/packages/eslint-plugin-conventions#readme",
55
+ "homepage": "https://eslint.interlace.tools/docs/quality/plugin-conventions?utm_source=npm&utm_medium=referral&utm_campaign=eslint-plugin-conventions",
52
56
  "bugs": {
53
57
  "url": "https://github.com/ofri-peretz/eslint/issues"
58
+ },
59
+ "scripts": {
60
+ "build": "tsx ../../scripts/build-package.ts",
61
+ "test": "vitest run",
62
+ "test:coverage": "vitest run --coverage",
63
+ "typecheck": "tsc -p tsconfig.lib.json --noEmit"
64
+ },
65
+ "peerDependencies": {
66
+ "eslint": "^8.0.0 || ^9.0.0 || ^10.0.0"
67
+ },
68
+ "funding": {
69
+ "type": "github",
70
+ "url": "https://github.com/ofri-peretz/eslint"
54
71
  }
55
- }
72
+ }
package/src/index.d.ts CHANGED
@@ -35,6 +35,21 @@ export declare const rules: {
35
35
  'no-json-schema-tags': TSESLint.RuleModule<"jsonSchemaTag" | "moveToDescription", [(import("./rules/conventions/no-json-schema-tags").Options | undefined)?], unknown, TSESLint.RuleListener> & {
36
36
  name: string;
37
37
  };
38
+ 'require-data-testid': TSESLint.RuleModule<"missingDataTestId" | "dynamicDataTestId", [(import("./rules/conventions/require-data-testid").Options | undefined)?], unknown, TSESLint.RuleListener> & {
39
+ name: string;
40
+ };
41
+ 'utm-taxonomy': TSESLint.RuleModule<"invalidUtmSource" | "invalidUtmMedium", [], unknown, TSESLint.RuleListener> & {
42
+ name: string;
43
+ };
44
+ 'no-raw-cross-property-href': TSESLint.RuleModule<"rawCrossPropertyHref", [], unknown, TSESLint.RuleListener> & {
45
+ name: string;
46
+ };
47
+ 'analytics-event-naming': TSESLint.RuleModule<"invalidEventName" | "interpolatedEventName", [], unknown, TSESLint.RuleListener> & {
48
+ name: string;
49
+ };
50
+ 'no-magic-numbers': TSESLint.RuleModule<"noMagicNumber" | "extractConst", [(import("./rules/conventions/no-magic-numbers").Options | undefined)?], unknown, TSESLint.RuleListener> & {
51
+ name: string;
52
+ };
38
53
  };
39
54
  export declare const plugin: {
40
55
  meta: {
@@ -72,6 +87,21 @@ export declare const plugin: {
72
87
  'no-json-schema-tags': TSESLint.RuleModule<"jsonSchemaTag" | "moveToDescription", [(import("./rules/conventions/no-json-schema-tags").Options | undefined)?], unknown, TSESLint.RuleListener> & {
73
88
  name: string;
74
89
  };
90
+ 'require-data-testid': TSESLint.RuleModule<"missingDataTestId" | "dynamicDataTestId", [(import("./rules/conventions/require-data-testid").Options | undefined)?], unknown, TSESLint.RuleListener> & {
91
+ name: string;
92
+ };
93
+ 'utm-taxonomy': TSESLint.RuleModule<"invalidUtmSource" | "invalidUtmMedium", [], unknown, TSESLint.RuleListener> & {
94
+ name: string;
95
+ };
96
+ 'no-raw-cross-property-href': TSESLint.RuleModule<"rawCrossPropertyHref", [], unknown, TSESLint.RuleListener> & {
97
+ name: string;
98
+ };
99
+ 'analytics-event-naming': TSESLint.RuleModule<"invalidEventName" | "interpolatedEventName", [], unknown, TSESLint.RuleListener> & {
100
+ name: string;
101
+ };
102
+ 'no-magic-numbers': TSESLint.RuleModule<"noMagicNumber" | "extractConst", [(import("./rules/conventions/no-magic-numbers").Options | undefined)?], unknown, TSESLint.RuleListener> & {
103
+ name: string;
104
+ };
75
105
  };
76
106
  };
77
107
  export declare const configs: {
@@ -113,6 +143,21 @@ export declare const configs: {
113
143
  'no-json-schema-tags': TSESLint.RuleModule<"jsonSchemaTag" | "moveToDescription", [(import("./rules/conventions/no-json-schema-tags").Options | undefined)?], unknown, TSESLint.RuleListener> & {
114
144
  name: string;
115
145
  };
146
+ 'require-data-testid': TSESLint.RuleModule<"missingDataTestId" | "dynamicDataTestId", [(import("./rules/conventions/require-data-testid").Options | undefined)?], unknown, TSESLint.RuleListener> & {
147
+ name: string;
148
+ };
149
+ 'utm-taxonomy': TSESLint.RuleModule<"invalidUtmSource" | "invalidUtmMedium", [], unknown, TSESLint.RuleListener> & {
150
+ name: string;
151
+ };
152
+ 'no-raw-cross-property-href': TSESLint.RuleModule<"rawCrossPropertyHref", [], unknown, TSESLint.RuleListener> & {
153
+ name: string;
154
+ };
155
+ 'analytics-event-naming': TSESLint.RuleModule<"invalidEventName" | "interpolatedEventName", [], unknown, TSESLint.RuleListener> & {
156
+ name: string;
157
+ };
158
+ 'no-magic-numbers': TSESLint.RuleModule<"noMagicNumber" | "extractConst", [(import("./rules/conventions/no-magic-numbers").Options | undefined)?], unknown, TSESLint.RuleListener> & {
159
+ name: string;
160
+ };
116
161
  };
117
162
  };
118
163
  };
@@ -120,6 +165,10 @@ export declare const configs: {
120
165
  'conventions/no-commented-code': "warn";
121
166
  'conventions/expiring-todo-comments': "warn";
122
167
  'conventions/no-deprecated-api': "warn";
168
+ 'conventions/utm-taxonomy': "error";
169
+ 'conventions/no-raw-cross-property-href': "error";
170
+ 'conventions/analytics-event-naming': "error";
171
+ 'conventions/no-magic-numbers': "warn";
123
172
  };
124
173
  };
125
174
  };
package/src/index.js CHANGED
@@ -17,6 +17,11 @@ const prefer_dependency_version_strategy_1 = require("./rules/conventions/prefer
17
17
  const filename_case_1 = require("./rules/conventions/filename-case");
18
18
  const consistent_existence_index_check_1 = require("./rules/conventions/consistent-existence-index-check");
19
19
  const no_json_schema_tags_1 = require("./rules/conventions/no-json-schema-tags");
20
+ const require_data_testid_1 = require("./rules/conventions/require-data-testid");
21
+ const utm_taxonomy_1 = require("./rules/conventions/utm-taxonomy");
22
+ const no_raw_cross_property_href_1 = require("./rules/conventions/no-raw-cross-property-href");
23
+ const analytics_event_naming_1 = require("./rules/conventions/analytics-event-naming");
24
+ const no_magic_numbers_1 = require("./rules/conventions/no-magic-numbers");
20
25
  exports.rules = {
21
26
  'no-commented-code': no_commented_code_1.noCommentedCode,
22
27
  'expiring-todo-comments': expiring_todo_comments_1.expiringTodoComments,
@@ -28,11 +33,16 @@ exports.rules = {
28
33
  'filename-case': filename_case_1.filenameCase,
29
34
  'consistent-existence-index-check': consistent_existence_index_check_1.consistentExistenceIndexCheck,
30
35
  'no-json-schema-tags': no_json_schema_tags_1.noJsonSchemaTags,
36
+ 'require-data-testid': require_data_testid_1.requireDataTestId,
37
+ 'utm-taxonomy': utm_taxonomy_1.utmTaxonomy,
38
+ 'no-raw-cross-property-href': no_raw_cross_property_href_1.noRawCrossPropertyHref,
39
+ 'analytics-event-naming': analytics_event_naming_1.analyticsEventNaming,
40
+ 'no-magic-numbers': no_magic_numbers_1.noMagicNumbers,
31
41
  };
32
42
  exports.plugin = {
33
43
  meta: {
34
44
  name: 'eslint-plugin-conventions',
35
- version: '1.0.0',
45
+ version: '4.1.0',
36
46
  },
37
47
  rules: exports.rules,
38
48
  };
@@ -45,6 +55,10 @@ exports.configs = {
45
55
  'conventions/no-commented-code': 'warn',
46
56
  'conventions/expiring-todo-comments': 'warn',
47
57
  'conventions/no-deprecated-api': 'warn',
58
+ 'conventions/utm-taxonomy': 'error',
59
+ 'conventions/no-raw-cross-property-href': 'error',
60
+ 'conventions/analytics-event-naming': 'error',
61
+ 'conventions/no-magic-numbers': 'warn',
48
62
  },
49
63
  },
50
64
  };
package/src/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/eslint-plugin-conventions/src/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAIH,oBAAoB;AACpB,6EAAwE;AACxE,uFAAkF;AAClF,6EAAwE;AACxE,mGAA4F;AAC5F,6EAAwE;AACxE,6EAAwE;AACxE,+GAAyG;AACzG,qEAAiE;AACjE,2GAAqG;AACrG,iFAA2E;AAE9D,QAAA,KAAK,GAAG;IACnB,mBAAmB,EAAE,mCAAe;IACpC,wBAAwB,EAAE,6CAAoB;IAC9C,mBAAmB,EAAE,mCAAe;IACpC,8BAA8B,EAAE,uDAAwB;IACxD,mBAAmB,EAAE,mCAAe;IACpC,mBAAmB,EAAE,mCAAe;IACpC,oCAAoC,EAAE,oEAA+B;IACrE,eAAe,EAAE,4BAAY;IAC7B,kCAAkC,EAAE,gEAA6B;IACjE,qBAAqB,EAAE,sCAAgB;CACkC,CAAC;AAE/D,QAAA,MAAM,GAAG;IACpB,IAAI,EAAE;QACJ,IAAI,EAAE,2BAA2B;QACjC,OAAO,EAAE,OAAO;KACjB;IACD,KAAK,EAAL,aAAK;CAC+B,CAAC;AAE1B,QAAA,OAAO,GAAG;IACrB,WAAW,EAAE;QACX,OAAO,EAAE;YACP,WAAW,EAAE,cAAM;SACpB;QACD,KAAK,EAAE;YACL,+BAA+B,EAAE,MAAM;YACvC,oCAAoC,EAAE,MAAM;YAC5C,+BAA+B,EAAE,MAAM;SACxC;KACmC;CACc,CAAC;AAEvD,kBAAe,cAAM,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAIH,oBAAoB;AACpB,6EAAwE;AACxE,uFAAkF;AAClF,6EAAwE;AACxE,mGAA4F;AAC5F,6EAAwE;AACxE,6EAAwE;AACxE,+GAAyG;AACzG,qEAAiE;AACjE,2GAAqG;AACrG,iFAA2E;AAC3E,iFAA4E;AAC5E,mEAA+D;AAC/D,+FAAwF;AACxF,uFAAkF;AAClF,2EAAsE;AAEzD,QAAA,KAAK,GAAG;IACnB,mBAAmB,EAAE,mCAAe;IACpC,wBAAwB,EAAE,6CAAoB;IAC9C,mBAAmB,EAAE,mCAAe;IACpC,8BAA8B,EAAE,uDAAwB;IACxD,mBAAmB,EAAE,mCAAe;IACpC,mBAAmB,EAAE,mCAAe;IACpC,oCAAoC,EAAE,oEAA+B;IACrE,eAAe,EAAE,4BAAY;IAC7B,kCAAkC,EAAE,gEAA6B;IACjE,qBAAqB,EAAE,sCAAgB;IACvC,qBAAqB,EAAE,uCAAiB;IACxC,cAAc,EAAE,0BAAW;IAC3B,4BAA4B,EAAE,mDAAsB;IACpD,wBAAwB,EAAE,6CAAoB;IAC9C,kBAAkB,EAAE,iCAAc;CACuC,CAAC;AAE/D,QAAA,MAAM,GAAG;IACpB,IAAI,EAAE;QACJ,IAAI,EAAE,2BAA2B;QACjC,OAAO,EAAE,OAAO;KACjB;IACD,KAAK,EAAL,aAAK;CAC+B,CAAC;AAE1B,QAAA,OAAO,GAAG;IACrB,WAAW,EAAE;QACX,OAAO,EAAE;YACP,WAAW,EAAE,cAAM;SACpB;QACD,KAAK,EAAE;YACL,+BAA+B,EAAE,MAAM;YACvC,oCAAoC,EAAE,MAAM;YAC5C,+BAA+B,EAAE,MAAM;YACvC,0BAA0B,EAAE,OAAO;YACnC,wCAAwC,EAAE,OAAO;YACjD,oCAAoC,EAAE,OAAO;YAC7C,8BAA8B,EAAE,MAAM;SACvC;KACmC;CACc,CAAC;AAEvD,kBAAe,cAAM,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"eslint-plugin-conventions.js","sourceRoot":"","sources":["../../../../../packages/eslint-plugin-conventions/src/lib/eslint-plugin-conventions.ts"],"names":[],"mappings":";;AAAA,0DAEC;AAFD,SAAgB,uBAAuB;IACrC,OAAO,2BAA2B,CAAC;AACrC,CAAC"}
1
+ {"version":3,"file":"eslint-plugin-conventions.js","sourceRoot":"","sources":["../../../src/lib/eslint-plugin-conventions.ts"],"names":[],"mappings":";;AAAA,0DAEC;AAFD,SAAgB,uBAAuB;IACrC,OAAO,2BAA2B,CAAC;AACrC,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Copyright (c) 2025 Ofri Peretz
3
+ * Licensed under the MIT License. Use of this source code is governed by the
4
+ * MIT license that can be found in the LICENSE file.
5
+ */
6
+ /**
7
+ * oxlint sub-export.
8
+ *
9
+ * Consumers wire oxlint to this entry via:
10
+ * { "jsPlugins": ["eslint-plugin-conventions/oxlint"] }
11
+ *
12
+ * oxlint's JS plugin loader does `require('eslint-plugin-conventions/oxlint')` and reads
13
+ * `.rules` off the result. The compiled output of `export = plugin` is
14
+ * `module.exports = plugin`, which gives oxlint the plugin object directly
15
+ * (`{ meta, rules }`) — no wrapper, no `.default` indirection.
16
+ *
17
+ * Generated by scripts/generate-oxlint-shims.mjs. Do not edit by hand.
18
+ */
19
+ import { plugin } from './index';
20
+ export = plugin;
package/src/oxlint.js ADDED
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2025 Ofri Peretz
4
+ * Licensed under the MIT License. Use of this source code is governed by the
5
+ * MIT license that can be found in the LICENSE file.
6
+ */
7
+ /**
8
+ * oxlint sub-export.
9
+ *
10
+ * Consumers wire oxlint to this entry via:
11
+ * { "jsPlugins": ["eslint-plugin-conventions/oxlint"] }
12
+ *
13
+ * oxlint's JS plugin loader does `require('eslint-plugin-conventions/oxlint')` and reads
14
+ * `.rules` off the result. The compiled output of `export = plugin` is
15
+ * `module.exports = plugin`, which gives oxlint the plugin object directly
16
+ * (`{ meta, rules }`) — no wrapper, no `.default` indirection.
17
+ *
18
+ * Generated by scripts/generate-oxlint-shims.mjs. Do not edit by hand.
19
+ */
20
+ const index_1 = require("./index");
21
+ module.exports = index_1.plugin;
22
+ //# sourceMappingURL=oxlint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oxlint.js","sourceRoot":"","sources":["../../src/oxlint.ts"],"names":[],"mappings":";AAAA;;;;GAIG;AAEH;;;;;;;;;;;;GAYG;AAEH,mCAAiC;AAEjC,iBAAS,cAAM,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Copyright (c) 2025 Ofri Peretz
3
+ * Licensed under the MIT License. Use of this source code is governed by the
4
+ * MIT license that can be found in the LICENSE file.
5
+ */
6
+ /**
7
+ * ESLint Rule: analytics-event-naming
8
+ *
9
+ * Vendor-neutral. Validates the first argument of analytics event-capture
10
+ * calls against the naming grammar codified in ANALYTICS_PHILOSOPHY.md
11
+ * principle 4:
12
+ *
13
+ * `category:object_action`
14
+ *
15
+ * - `category` and `object` are lowercase snake_case identifiers.
16
+ * - `action` is one of a fixed verb list (present tense): click, submit,
17
+ * view, add, remove, start, end, generate, send, cancel, fail, create,
18
+ * delete, update, invite.
19
+ * - Vendor reserved events starting with `$` (e.g. PostHog `$pageview`,
20
+ * `$set`) are exempt.
21
+ * - Template-literal event names are forbidden — they make the catalog
22
+ * unbounded (principle 3).
23
+ *
24
+ * Matched call shapes (covers PostHog, Segment, Mixpanel, Amplitude
25
+ * conventions plus our own primitives):
26
+ *
27
+ * - `<obj>.capture(name, props)` — PostHog
28
+ * - `<obj>.track(name, props)` — Segment / Mixpanel / Amplitude
29
+ * - `track(name, props)` — bare, our primitive
30
+ *
31
+ * Not matched:
32
+ *
33
+ * - `<obj>.identify(distinctId, props)` — first arg is a person id
34
+ * - `<obj>.page(...)` / `pageview(...)` — event name is implicit
35
+ */
36
+ import type { TSESLint } from '@interlace/eslint-devkit';
37
+ type MessageIds = 'invalidEventName' | 'interpolatedEventName';
38
+ export declare const analyticsEventNaming: TSESLint.RuleModule<MessageIds, [], unknown, TSESLint.RuleListener> & {
39
+ name: string;
40
+ };
41
+ export {};