eslint-plugin-flawless 0.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.
package/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ MIT License
2
+
3
+ Copyright for portions of eslint-plugin-arrow-return-style-x are held by u3u,
4
+ 2023 as part of eslint-plugin-arrow-return-style. All other copyright for
5
+ eslint-plugin-arrow-return-style-x are held by Christopher Buss
6
+ <christopher.buss@pm.me>, 2025.
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
9
+ this software and associated documentation files (the "Software"), to deal in
10
+ the Software without restriction, including without limitation the rights to
11
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12
+ the Software, and to permit persons to whom the Software is furnished to do so,
13
+ subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included in all
16
+ copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,200 @@
1
+ # eslint-plugin-template
2
+
3
+ > A modern, TypeScript-first template for building ESLint plugins (Flat Config
4
+ > ready)
5
+
6
+ [![npm version][npm-version-src]][npm-version-href]
7
+ [![npm downloads][npm-downloads-src]][npm-downloads-href]
8
+ [![License][license-src]][license-href]
9
+
10
+ This repository is a starter template for creating your own ESLint plugin with:
11
+
12
+ - ESLint 9 Flat Config support out of the box
13
+ - TypeScript with strong typing for rules and options
14
+ - Vitest-based rule tests via eslint-vitest-rule-tester
15
+ - Rule scaffolding script to generate rule code, tests, and docs
16
+ - Auto-generated README rules section via eslint-doc-generator
17
+
18
+ Use it as a “Use this template” on GitHub or fork and rename.
19
+
20
+ ## Quick start
21
+
22
+ 1. Create your repo from this template
23
+
24
+ - Click “Use this template” on GitHub, or
25
+ - Degit locally: `degit christopher-buss/eslint-plugin-template my-plugin`
26
+
27
+ 2. Install dependencies
28
+
29
+ ```pwsh
30
+ pnpm i
31
+ ```
32
+
33
+ 3. Rename the package and plugin
34
+
35
+ Update these fields to your plugin name (e.g., `eslint-plugin-awesome`):
36
+
37
+ - `package.json` → `name`, `description`, `repository`, `author`, `license`
38
+ - README title and badges
39
+
40
+ The runtime plugin name (used in config) is derived from the package name by
41
+ removing the `eslint-plugin-` prefix. For `eslint-plugin-awesome` the plugin key
42
+ becomes `awesome`.
43
+
44
+ 4. Scaffold your first rule
45
+
46
+ ```pwsh
47
+ pnpm create-rule my-new-rule
48
+ ```
49
+
50
+ This generates:
51
+
52
+ - `src/rules/my-new-rule/rule.ts` – rule implementation
53
+ - `src/rules/my-new-rule/rule.spec.ts` – tests
54
+ - `src/rules/my-new-rule/documentation.md` – rule docs
55
+
56
+ 5. Run tests and docs
57
+
58
+ ```pwsh
59
+ pnpm test
60
+ pnpm eslint-docs
61
+ ```
62
+
63
+ The docs command updates the auto-generated rules list in this README.
64
+
65
+ ## Using your plugin
66
+
67
+ Once published to npm as `eslint-plugin-awesome`, you can enable it in a
68
+ project.
69
+
70
+ ### Flat Config (ESLint 9+)
71
+
72
+ ```js
73
+ // eslint.config.js / eslint.config.mjs / eslint.config.ts
74
+ import yourPlugin from "eslint-plugin-awesome";
75
+
76
+ export default [
77
+ // Enable all recommended rules from your plugin
78
+ yourPlugin.configs.recommended,
79
+
80
+ // Or wire it manually
81
+ {
82
+ plugins: {
83
+ awesome: yourPlugin,
84
+ },
85
+ rules: {
86
+ "awesome/my-new-rule": "error",
87
+ },
88
+ },
89
+ ];
90
+ ```
91
+
92
+ ### Legacy Config (.eslintrc)
93
+
94
+ ```json
95
+ {
96
+ "extends": ["plugin:yourname/recommended"]
97
+ }
98
+ ```
99
+
100
+ ## Development
101
+
102
+ Scripts you’ll use during development:
103
+
104
+ - `pnpm dev` – fast stub build for local iteration
105
+ - `pnpm build` – type-safe build with d.ts via tsdown
106
+ - `pnpm test` – run Vitest tests
107
+ - `pnpm lint` – run ESLint on this repo
108
+ - `pnpm typecheck` – run `tsc --noEmit`
109
+ - `pnpm eslint-docs` – regenerate README rules list
110
+ - `pnpm release` – bump version via bumpp
111
+
112
+ Requirements:
113
+
114
+ - Node.js >= 20
115
+ - pnpm >= 10
116
+ - ESLint >= 9.15.0 (peer dep for consumers)
117
+
118
+ ## Project structure
119
+
120
+ ```text
121
+ src/
122
+ configs/ # Flat config presets (e.g., recommended)
123
+ rules/ # Your rules (each in its own folder)
124
+ plugin.ts # Plugin host (name, version, rules)
125
+ util.ts # Rule creator with docs links
126
+ index.ts # Entry combining plugin + configs (default export)
127
+ scripts/
128
+ create-rule.ts # Scaffolds a new rule (code, tests, docs)
129
+ template/ # Rule templates used by the script
130
+ ```
131
+
132
+ { "extends": ["plugin:awesome/recommended"] }
133
+
134
+ - The plugin key is computed from your package name (see `src/plugin.ts`).
135
+ - `src/configs/recommended` is provided for convenience; add your rules there
136
+ when ready.
137
+
138
+ ## Scaffolding a rule
139
+
140
+ ```pwsh
141
+ pnpm create-rule my-new-rule
142
+ ```
143
+
144
+ What happens:
145
+
146
+ 1. Creates `src/rules/my-new-rule/` with `rule.ts`, `rule.spec.ts`,
147
+ `documentation.md`.
148
+ 2. Attempts to register the rule. If automatic edit cannot be applied, the
149
+ script prints the exact import and entry you can paste into your plugin/index
150
+ file.
151
+ 3. Run `pnpm test` to validate, then `pnpm eslint-docs` to refresh this README.
152
+
153
+ ## Publishing
154
+
155
+ Typical flow:
156
+
157
+ ```pwsh
158
+ pnpm test
159
+ pnpm build
160
+ pnpm release # chooses the next semver and commits tags
161
+ # CI publishes to npm
162
+ ```
163
+
164
+ ## Rules reference
165
+
166
+ Generate this section with:
167
+
168
+ ```pwsh
169
+ pnpm eslint-docs
170
+ ```
171
+
172
+ <!-- begin auto-generated rules list -->
173
+
174
+ 💭 Requires
175
+ [type information](https://typescript-eslint.io/linting/typed-linting).
176
+
177
+ | Name | Description | 💭 |
178
+ | :---------------------------------------------------------------- | :---------------------------------------------------------- | :-- |
179
+ | [naming-convention](src/rules/naming-convention/documentation.md) | Enforce naming conventions for everything across a codebase | 💭 |
180
+
181
+ <!-- end auto-generated rules list -->
182
+
183
+ ## Contributing
184
+
185
+ PRs and issues welcome. If you’re using this as a template, adapt the sections
186
+ to your needs and replace the badges and links.
187
+
188
+ ## License
189
+
190
+ [MIT](./LICENSE) © 2025 [Christopher Buss](https://github.com/christopher-buss)
191
+
192
+ <!-- Badges -->
193
+
194
+ [npm-version-src]: https://img.shields.io/npm/v/eslint-plugin-flawless
195
+ [npm-version-href]: https://npmjs.com/package/eslint-plugin-flawless
196
+ [npm-downloads-src]: https://img.shields.io/npm/dm/eslint-plugin-flawless
197
+ [npm-downloads-href]: https://npmjs.com/package/eslint-plugin-flawless
198
+ [license-src]:
199
+ https://img.shields.io/github/license/christopher-buss/eslint-plugin-template.svg
200
+ [license-href]: ./LICENSE
@@ -0,0 +1,164 @@
1
+ import { TSESLint } from "@typescript-eslint/utils";
2
+ import "@typescript-eslint/utils/eslint-utils";
3
+ import * as _typescript_eslint_utils_ts_eslint0 from "@typescript-eslint/utils/ts-eslint";
4
+ import { Linter } from "eslint";
5
+
6
+ //#region src/util.d.ts
7
+ interface PluginDocumentation {
8
+ description: string;
9
+ recommended?: boolean;
10
+ requiresTypeChecking: boolean;
11
+ }
12
+ //#endregion
13
+ //#region src/rules/naming-convention/utils/enums.d.ts
14
+ declare const Selector: {
15
+ readonly variable: 1;
16
+ readonly function: 2;
17
+ readonly parameter: 4;
18
+ readonly objectStyleEnum: 8;
19
+ readonly parameterProperty: 16;
20
+ readonly classicAccessor: 32;
21
+ readonly enumMember: 64;
22
+ readonly classMethod: 128;
23
+ readonly objectLiteralMethod: 256;
24
+ readonly typeMethod: 512;
25
+ readonly classProperty: 1024;
26
+ readonly objectLiteralProperty: 2048;
27
+ readonly typeProperty: 4096;
28
+ readonly autoAccessor: 8192;
29
+ readonly class: 16384;
30
+ readonly interface: 32768;
31
+ readonly typeAlias: 65536;
32
+ readonly enum: 131072;
33
+ readonly typeParameter: 262144;
34
+ readonly import: 524288;
35
+ };
36
+ type SelectorString = keyof typeof Selector;
37
+ declare const MetaSelector: {
38
+ readonly default: -1;
39
+ readonly variableLike: 15;
40
+ readonly memberLike: 16368;
41
+ readonly typeLike: 507904;
42
+ readonly method: 896;
43
+ readonly property: 7168;
44
+ readonly accessor: 8224;
45
+ };
46
+ type MetaSelectorString = keyof typeof MetaSelector;
47
+ declare const Modifier: {
48
+ readonly const: 1;
49
+ readonly readonly: 2;
50
+ readonly static: 4;
51
+ readonly public: 8;
52
+ readonly protected: 16;
53
+ readonly private: 32;
54
+ readonly "#private": 64;
55
+ readonly abstract: 128;
56
+ readonly destructured: 256;
57
+ readonly global: 512;
58
+ readonly exported: 1024;
59
+ readonly unused: 2048;
60
+ readonly requiresQuotes: 4096;
61
+ readonly override: 8192;
62
+ readonly async: 16384;
63
+ readonly default: 32768;
64
+ readonly namespace: 65536;
65
+ };
66
+ type ModifierString = keyof typeof Modifier;
67
+ declare const PredefinedFormat: {
68
+ readonly camelCase: 1;
69
+ readonly strictCamelCase: 2;
70
+ readonly PascalCase: 3;
71
+ readonly StrictPascalCase: 4;
72
+ readonly snake_case: 5;
73
+ readonly UPPER_CASE: 6;
74
+ };
75
+ type PredefinedFormatString = keyof typeof PredefinedFormat;
76
+ declare const TypeModifier: {
77
+ readonly boolean: 131072;
78
+ readonly string: 262144;
79
+ readonly number: 524288;
80
+ readonly function: 1048576;
81
+ readonly array: 2097152;
82
+ };
83
+ type TypeModifierString = keyof typeof TypeModifier;
84
+ declare const UnderscoreOption: {
85
+ readonly forbid: 1;
86
+ readonly allow: 2;
87
+ readonly require: 3;
88
+ readonly requireDouble: 4;
89
+ readonly allowDouble: 5;
90
+ readonly allowSingleOrDouble: 6;
91
+ };
92
+ type IndividualAndMetaSelectorsString = MetaSelectorString | SelectorString;
93
+ type UnderscoreOptionString = keyof typeof UnderscoreOption;
94
+ //#endregion
95
+ //#region src/rules/naming-convention/utils/types.d.ts
96
+ interface MatchRegex {
97
+ match: boolean;
98
+ regex: string;
99
+ }
100
+ interface NamingSelector {
101
+ custom?: MatchRegex;
102
+ filter?: MatchRegex | string;
103
+ /**
104
+ * Format options.
105
+ */
106
+ format: Array<PredefinedFormatString> | null;
107
+ leadingUnderscore?: UnderscoreOptionString;
108
+ modifiers?: Array<ModifierString>;
109
+ prefix?: Array<string>;
110
+ /**
111
+ * Selector options.
112
+ */
113
+ selector: Array<IndividualAndMetaSelectorsString> | IndividualAndMetaSelectorsString;
114
+ suffix?: Array<string>;
115
+ trailingUnderscore?: UnderscoreOptionString;
116
+ types?: Array<TypeModifierString>;
117
+ }
118
+ //#endregion
119
+ //#region src/rules/naming-convention/rule.d.ts
120
+ type MessageIds$1 = "doesNotMatchFormat" | "doesNotMatchFormatTrimmed" | "missingAffix" | "missingUnderscore" | "satisfyCustom" | "unexpectedUnderscore";
121
+ type Options$1 = Array<NamingSelector>;
122
+ //#endregion
123
+ //#region src/plugin.d.ts
124
+ declare const plugin: {
125
+ meta: {
126
+ name: string;
127
+ version: string;
128
+ };
129
+ rules: {
130
+ "naming-convention": TSESLint.RuleModule<MessageIds$1, Options$1, PluginDocumentation, TSESLint.RuleListener>;
131
+ };
132
+ };
133
+ //#endregion
134
+ //#region src/index.d.ts
135
+ declare const _default: {
136
+ configs: {
137
+ recommended: {
138
+ plugins: {
139
+ [x: string]: {
140
+ meta: {
141
+ name: string;
142
+ version: string;
143
+ };
144
+ rules: {
145
+ "naming-convention": _typescript_eslint_utils_ts_eslint0.RuleModule<MessageIds$1, Options$1, PluginDocumentation, _typescript_eslint_utils_ts_eslint0.RuleListener>;
146
+ };
147
+ };
148
+ };
149
+ rules: {};
150
+ };
151
+ };
152
+ meta: {
153
+ name: string;
154
+ version: string;
155
+ };
156
+ rules: {
157
+ "naming-convention": _typescript_eslint_utils_ts_eslint0.RuleModule<MessageIds$1, Options$1, PluginDocumentation, _typescript_eslint_utils_ts_eslint0.RuleListener>;
158
+ };
159
+ };
160
+ type RuleOptions = { [K in keyof RuleDefinitions]: RuleDefinitions[K]["defaultOptions"] };
161
+ type Rules = { [K in keyof RuleOptions]: Linter.RuleEntry<RuleOptions[K]> };
162
+ type RuleDefinitions = typeof plugin.rules;
163
+ //#endregion
164
+ export { RuleOptions, Rules, _default as default };