lint-suite 2.0.0 → 2.0.2

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/README.md CHANGED
@@ -207,7 +207,9 @@ literal class names inside `[class]="..."` expressions and `class="a {{ b }}"`
207
207
  interpolations. String literals, object-literal keys, array elements, and both
208
208
  branches of a ternary contribute names; identifiers, calls, pipes, and `+`
209
209
  concatenations contribute nothing, so a class the rule cannot see is never
210
- reported. `[ngClass]` is deliberately not analysed.
210
+ reported. `[ngClass]` is deliberately not analysed. `routerLinkActive`,
211
+ `animate.enter`, and `animate.leave` are also read as class lists, static or
212
+ bound.
211
213
 
212
214
  Stylesheets come from the component beside the template: `styleUrl`,
213
215
  `styleUrls`, and inline `styles` read as string or template literals from the
@@ -278,13 +280,17 @@ Selectors resolve through the same parser as the ESLint rule, so `&__element`,
278
280
  `&--modifier`, `&.other`, `& > .child`, `.wrapper &`, `@media` blocks, and
279
281
  selector lists all report the resolved name on the rule that declares it: in
280
282
  `.panel { .inner {} }` only `inner` is checked on the inner rule, never `panel`
281
- twice. Arguments of `:host(.dark)` and `:host-context(.rtl)` are skipped, and
283
+ twice. A rule that only wraps nested rules, like `.dialog` in
284
+ `.dialog { &__name {} }`, emits no selector of its own and is never reported;
285
+ `.shell` in `.shell { .inner {} }` still is, because `.shell .inner` reaches
286
+ the output. Arguments of `:host(.dark)` and `:host-context(.rtl)` are skipped, and
282
287
  everything after `::ng-deep`, `/deep/`, or `>>>` is skipped too, because those
283
288
  classes live in other templates. A selector built with interpolation
284
289
  (`.icon-#{$size}`) is never reported, and `@extend .base` counts `base` as
285
290
  used.
286
291
 
287
- The template side reads the same sources as `no-unstyled-classes` plus
292
+ The template side reads the same sources as `no-unstyled-classes` (including
293
+ `routerLinkActive`, `animate.enter`, and `animate.leave`, static or bound) plus
288
294
  `[ngClass]`, and it does not skip custom elements: a class on
289
295
  `<app-child class="foo">` is written by this template, so `.foo` counts as
290
296
  used. When any template of the stylesheet holds a class source the rule cannot
@@ -457,7 +463,7 @@ per file.
457
463
 
458
464
  | Rule | Reports | Options |
459
465
  |---|---|---|
460
- | `local/type-placement` | An exported `type` outside a `common/*.type.ts` or `test/common/*.type.ts` file; a value exported from a `*.type.ts` file; a non-`const` export from a `*.const.ts` file; an `import type` from a relative or internal path that is neither a `*.type.ts` file nor a `common` barrel (`../common`, `./common/index.ts`, `@shared/common`). `.spec.ts`, `.stub.ts`, `.d.ts`, `state.type.ts` (any prefix), and fixtures are exempt; a `.spec.util.ts` file is not, so an exported type in one is reported. Never resolves imports. | `internalPatterns`: regex sources for alias prefixes that must resolve to a `*.type.ts` file. Default empty: a workspace alias (`@shared/common`) resolves to a library entry point, and module boundaries forbid deep imports, so alias type imports pass. |
466
+ | `local/type-placement` | An exported `type` outside a `common/*.type.ts` or `test/common/*.type.ts` file; a value exported from a `*.type.ts` file; a non-`const` export from a `*.const.ts` file; an `import type` from a relative or internal path that is neither a `*.type.ts` / `*.schema.ts` file nor a `common` barrel (`../common`, `./common/index.ts`, `@shared/common`). `.spec.ts`, `.stub.ts`, `.schema.ts` (an inferred type lives beside its schema), `.d.ts`, `state.type.ts` (any prefix), and fixtures are exempt; a `.spec.util.ts` file is not, so an exported type in one is reported. Never resolves imports. | `internalPatterns`: regex sources for alias prefixes that must resolve to a `*.type.ts` file. Default empty: a workspace alias (`@shared/common`) resolves to a library entry point, and module boundaries forbid deep imports, so alias type imports pass. |
461
467
  | `local/util-purity` | Inside `utils/*.util.ts` (excluding paths under `test/` or `testing/`): imports of `node:fs`, `child_process`, `os`, `process`, `http`, `net`, `worker_threads`; a module-level `let`; a module-level `new Map/Set/WeakMap/WeakSet`; `process.*`, `globalThis`, `window`, `document`, `localStorage`, `console`; `Date.now`, `Math.random`, `performance.now`, `crypto.randomUUID`; `setTimeout`, `setInterval`, `fetch`, `inject`, `require`. | `bannedModules` |
462
468
  | `local/test-file-shape` | A file named `*.spec-support.ts`, `*.spec-helper.ts`, `*.test-utils.ts`, `*-fixture.ts`, or under `__mocks__/` / `helpers/` / `common/stubs/`; a `.stub.ts` outside `test/stubs/`, a `.mock.ts` outside `test/mocks/`, a `.spec.util.ts` outside `test/utils/`, or any `fixtures/` directory outside `test/fixtures/` (a dedicated `testing/` library is exempt from all of these); a `test/stubs/*.stub.ts` export not named `UPPER_SNAKE_STUB` or without a type annotation; a `test/mocks/*.mock.ts` export that is not a camelCase `...Mock` function with an explicit return type. | none |
463
469
 
package/eslint.cjs CHANGED
@@ -687,7 +687,12 @@ var classExpressionLiterals = (source) => {
687
687
  };
688
688
 
689
689
  // packages/lint-suite/src/lib/rules/utils/template-classes.util.ts
690
- var CLASS_ATTRIBUTE = "class";
690
+ var CLASS_ATTRIBUTES = [
691
+ "class",
692
+ "routerLinkActive",
693
+ "animate.enter",
694
+ "animate.leave"
695
+ ];
691
696
  var CLASS_BINDING_PREFIX = "class.";
692
697
  var TOKEN = /\S+/gu;
693
698
  var expressionSource = (value) => {
@@ -716,11 +721,11 @@ var boundClassName = (input) => {
716
721
  return input.name;
717
722
  };
718
723
  var isClassExpression = (input) => {
719
- const isClassName = input.name === CLASS_ATTRIBUTE;
724
+ const isClassName = CLASS_ATTRIBUTES.includes(input.name);
720
725
  if (!isClassName) return false;
721
726
  const { details } = input.keySpan;
722
727
  if (details === null) return true;
723
- return details === CLASS_ATTRIBUTE;
728
+ return details === input.name;
724
729
  };
725
730
  var expressionClasses = (input) => {
726
731
  const source = expressionSource(input.value);
@@ -745,7 +750,7 @@ var inputClasses = (input) => {
745
750
  var templateClasses = (node) => {
746
751
  const classes = [];
747
752
  for (const attribute of node.attributes) {
748
- const isClassName = attribute.name === CLASS_ATTRIBUTE;
753
+ const isClassName = CLASS_ATTRIBUTES.includes(attribute.name);
749
754
  if (isClassName) {
750
755
  const found = staticClasses(attribute);
751
756
  classes.push(...found);
@@ -6811,13 +6816,13 @@ var import_utils35 = require("@typescript-eslint/utils");
6811
6816
  // packages/lint-suite/src/lib/rules/type-placement/common/type-placement.const.ts
6812
6817
  var DEFAULT_INTERNAL_PATTERNS = [];
6813
6818
  var docs19 = {
6814
- description: "Require types to live in common/*.type.ts files, *.const.ts files to export only consts, and type-only imports to come from *.type.ts files or a common barrel"
6819
+ description: "Require types to live in common/*.type.ts files, *.const.ts files to export only consts, and type-only imports to come from *.type.ts or *.schema.ts files or a common barrel"
6815
6820
  };
6816
6821
  var messages19 = {
6817
6822
  typeOutsideTypeFile: "Exported type '{{ name }}' belongs in a common/*.type.ts or test/common/*.type.ts file, not here.",
6818
6823
  valueInTypeFile: "A *.type.ts file may only export type aliases and interfaces.",
6819
6824
  nonConstInConstFile: "A *.const.ts file may only export const variable declarations.",
6820
- typeImportNotFromTypeFile: "Type-only import from '{{ source }}' must come from a *.type.ts file or a common barrel."
6825
+ typeImportNotFromTypeFile: "Type-only import from '{{ source }}' must come from a *.type.ts or *.schema.ts file, or a common barrel."
6821
6826
  };
6822
6827
  var stringItems2 = { type: "string" };
6823
6828
  var internalPatternsSchema = {
@@ -6848,10 +6853,10 @@ var defaultOptions10 = [
6848
6853
  var TYPE_FILE_SUFFIX = ".type.ts";
6849
6854
  var CONST_FILE_SUFFIX = ".const.ts";
6850
6855
  var COMMON_SEGMENT = "/common/";
6851
- var EXEMPT_FILE = /\.(spec|stub|d)\.ts$/;
6856
+ var EXEMPT_FILE = /\.(spec|stub|schema|d)\.ts$/;
6852
6857
  var STATE_TYPE_FILE = /(^|[./])state\.type\.ts$/;
6853
6858
  var FIXTURES_SEGMENT2 = "/fixtures/";
6854
- var TYPE_FILE_SEGMENT = /\.type(\.ts)?$/;
6859
+ var TYPE_SOURCE_SEGMENT = /\.(type|schema)(\.ts)?$/;
6855
6860
  var COMMON_BARREL = /(^|\/)common(\/index(\.ts)?)?$/;
6856
6861
  var createRule19 = import_utils35.ESLintUtils.RuleCreator(
6857
6862
  () => "https://github.com/F0rty-Tw0/lint-suite#type-placement"
@@ -6870,7 +6875,7 @@ var lastSegment = (source) => {
6870
6875
  var isTypeOnlySource = (source) => {
6871
6876
  const isCommonBarrel = COMMON_BARREL.test(source);
6872
6877
  if (isCommonBarrel) return true;
6873
- return TYPE_FILE_SEGMENT.test(lastSegment(source));
6878
+ return TYPE_SOURCE_SEGMENT.test(lastSegment(source));
6874
6879
  };
6875
6880
  var isInternalSource = (source, patterns) => {
6876
6881
  const isRelative = source.startsWith(".");
@@ -7292,6 +7297,14 @@ var typescriptSafety = (0, import_config18.defineConfig)([
7292
7297
  // Class actions carry their payload as constructor parameter properties.
7293
7298
  "@typescript-eslint/parameter-properties": "off"
7294
7299
  }
7300
+ },
7301
+ {
7302
+ files: ["**/*.stub.ts"],
7303
+ rules: {
7304
+ // local/test-file-shape requires STUB: Type; a literal stub would trip
7305
+ // no-inferrable-types.
7306
+ "@typescript-eslint/no-inferrable-types": "off"
7307
+ }
7295
7308
  }
7296
7309
  ]);
7297
7310