lint-suite 1.6.2 → 1.6.3

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 (63) hide show
  1. package/README.md +149 -2
  2. package/eslint.cjs +1049 -309
  3. package/eslint.cjs.map +4 -4
  4. package/eslint.js +938 -175
  5. package/eslint.js.map +4 -4
  6. package/lib/angular-template.d.ts +1 -0
  7. package/lib/angular-template.d.ts.map +1 -1
  8. package/lib/angular.d.ts.map +1 -1
  9. package/lib/base-practices.d.ts.map +1 -1
  10. package/lib/line-length.const.d.ts +2 -0
  11. package/lib/line-length.const.d.ts.map +1 -0
  12. package/lib/rules/common/class-usage.type.d.ts +25 -0
  13. package/lib/rules/common/class-usage.type.d.ts.map +1 -0
  14. package/lib/rules/component-metadata.d.ts +5 -0
  15. package/lib/rules/component-metadata.d.ts.map +1 -0
  16. package/lib/rules/no-unstyled-classes/common/no-unstyled-classes.type.d.ts +33 -0
  17. package/lib/rules/no-unstyled-classes/common/no-unstyled-classes.type.d.ts.map +1 -0
  18. package/lib/rules/no-unstyled-classes/no-unstyled-classes.d.ts +8 -0
  19. package/lib/rules/no-unstyled-classes/no-unstyled-classes.d.ts.map +1 -0
  20. package/lib/rules/no-unstyled-classes/styles/component-stylesheets.d.ts +4 -0
  21. package/lib/rules/no-unstyled-classes/styles/component-stylesheets.d.ts.map +1 -0
  22. package/lib/rules/no-unstyled-classes/styles/stylesheet-classes.d.ts +3 -0
  23. package/lib/rules/no-unstyled-classes/styles/stylesheet-classes.d.ts.map +1 -0
  24. package/lib/rules/no-unstyled-classes/styles/stylesheet-collection.d.ts +4 -0
  25. package/lib/rules/no-unstyled-classes/styles/stylesheet-collection.d.ts.map +1 -0
  26. package/lib/rules/no-unstyled-classes/styles/stylesheet-imports.d.ts +2 -0
  27. package/lib/rules/no-unstyled-classes/styles/stylesheet-imports.d.ts.map +1 -0
  28. package/lib/rules/no-unstyled-classes/styles/template-stylesheets.d.ts +3 -0
  29. package/lib/rules/no-unstyled-classes/styles/template-stylesheets.d.ts.map +1 -0
  30. package/lib/rules/no-unused-angular-instance-fields/rule/angular/angular-metadata-literals.d.ts.map +1 -1
  31. package/lib/rules/no-unused-classes/common/no-unused-classes.type.d.ts +24 -0
  32. package/lib/rules/no-unused-classes/common/no-unused-classes.type.d.ts.map +1 -0
  33. package/lib/rules/no-unused-classes/no-unused-classes.d.ts +8 -0
  34. package/lib/rules/no-unused-classes/no-unused-classes.d.ts.map +1 -0
  35. package/lib/rules/no-unused-classes/styles/component-descriptors.d.ts +3 -0
  36. package/lib/rules/no-unused-classes/styles/component-descriptors.d.ts.map +1 -0
  37. package/lib/rules/no-unused-classes/styles/stylesheet-components.d.ts +3 -0
  38. package/lib/rules/no-unused-classes/styles/stylesheet-components.d.ts.map +1 -0
  39. package/lib/rules/no-unused-classes/template/template-usage.d.ts +3 -0
  40. package/lib/rules/no-unused-classes/template/template-usage.d.ts.map +1 -0
  41. package/lib/rules/one-line-guard/one-line-guard.d.ts +10 -0
  42. package/lib/rules/one-line-guard/one-line-guard.d.ts.map +1 -0
  43. package/lib/rules/utils/class-expression-literals.util.d.ts +4 -0
  44. package/lib/rules/utils/class-expression-literals.util.d.ts.map +1 -0
  45. package/lib/rules/utils/resolved-rules.util.d.ts +5 -0
  46. package/lib/rules/utils/resolved-rules.util.d.ts.map +1 -0
  47. package/lib/rules/utils/selector-classes.util.d.ts +7 -0
  48. package/lib/rules/utils/selector-classes.util.d.ts.map +1 -0
  49. package/lib/rules/utils/template-classes.util.d.ts +3 -0
  50. package/lib/rules/utils/template-classes.util.d.ts.map +1 -0
  51. package/lib/typescript-local-plugin.d.ts.map +1 -1
  52. package/lib/typescript-safety.d.ts.map +1 -1
  53. package/package.json +4 -1
  54. package/prettier.cjs +6 -1
  55. package/prettier.cjs.map +3 -3
  56. package/prettier.d.ts.map +1 -1
  57. package/prettier.js +4 -1
  58. package/prettier.js.map +3 -3
  59. package/stylelint.cjs +680 -4
  60. package/stylelint.cjs.map +4 -4
  61. package/stylelint.d.ts.map +1 -1
  62. package/stylelint.js +708 -4
  63. package/stylelint.js.map +4 -4
package/eslint.js CHANGED
@@ -1,11 +1,677 @@
1
1
  // packages/lint-suite/src/lib/angular-template.ts
2
2
  import { configs } from "angular-eslint";
3
3
  import { defineConfig } from "eslint/config";
4
+
5
+ // packages/lint-suite/src/lib/rules/define-plugin.util.ts
6
+ var definePlugin = (name, rules) => {
7
+ const meta7 = { name };
8
+ const plugin = { meta: meta7, rules };
9
+ return plugin;
10
+ };
11
+
12
+ // packages/lint-suite/src/lib/rules/no-unstyled-classes/no-unstyled-classes.ts
13
+ import { ESLintUtils } from "@typescript-eslint/utils";
14
+
15
+ // packages/lint-suite/src/lib/rules/no-unstyled-classes/styles/component-stylesheets.ts
16
+ import { existsSync } from "node:fs";
17
+ import { dirname, resolve } from "node:path";
18
+
19
+ // packages/lint-suite/src/lib/rules/component-metadata.ts
20
+ import { readFileSync } from "node:fs";
21
+ import {
22
+ ScriptTarget,
23
+ canHaveDecorators,
24
+ createSourceFile,
25
+ forEachChild,
26
+ getDecorators,
27
+ isArrayLiteralExpression,
28
+ isCallExpression,
29
+ isIdentifier,
30
+ isObjectLiteralExpression,
31
+ isPropertyAssignment,
32
+ isStringLiteralLike
33
+ } from "typescript";
34
+ var componentArgument = (decorator) => {
35
+ const { expression } = decorator;
36
+ if (!isCallExpression(expression)) return null;
37
+ if (!isIdentifier(expression.expression)) return null;
38
+ const isComponent = expression.expression.text === "Component";
39
+ if (!isComponent) return null;
40
+ const [argument] = expression.arguments;
41
+ if (argument === void 0) return null;
42
+ if (!isObjectLiteralExpression(argument)) return null;
43
+ return argument;
44
+ };
45
+ var decoratedMetadata = (node) => {
46
+ if (!canHaveDecorators(node)) return null;
47
+ const decorators = getDecorators(node) ?? [];
48
+ for (const decorator of decorators) {
49
+ const metadata = componentArgument(decorator);
50
+ if (metadata !== null) return metadata;
51
+ }
52
+ return null;
53
+ };
54
+ var parseComponentMetadata = (text2, path) => {
55
+ const found = [];
56
+ const visit = (node) => {
57
+ const metadata = decoratedMetadata(node);
58
+ if (metadata !== null) found.push(metadata);
59
+ forEachChild(node, visit);
60
+ };
61
+ const source = createSourceFile(path, text2, ScriptTarget.Latest, true);
62
+ forEachChild(source, visit);
63
+ return found;
64
+ };
65
+ var componentMetadata = (path) => {
66
+ try {
67
+ const text2 = readFileSync(path, "utf8");
68
+ return parseComponentMetadata(text2, path);
69
+ } catch {
70
+ return [];
71
+ }
72
+ };
73
+ var literalText = (node) => {
74
+ if (!isStringLiteralLike(node)) return null;
75
+ return node.text;
76
+ };
77
+ var literalTexts = (node) => {
78
+ const single = literalText(node);
79
+ if (single !== null) return [single];
80
+ if (!isArrayLiteralExpression(node)) return [];
81
+ const texts = [];
82
+ for (const element of node.elements) {
83
+ const text2 = literalText(element);
84
+ if (text2 !== null) texts.push(text2);
85
+ }
86
+ return texts;
87
+ };
88
+ var metadataValue = (metadata, name) => {
89
+ for (const property of metadata.properties) {
90
+ if (!isPropertyAssignment(property)) continue;
91
+ if (!isIdentifier(property.name)) continue;
92
+ const isMatch = property.name.text === name;
93
+ if (isMatch) return property.initializer;
94
+ }
95
+ return null;
96
+ };
97
+ var metadataTexts = (metadata, name) => {
98
+ const value = metadataValue(metadata, name);
99
+ if (value === null) return [];
100
+ return literalTexts(value);
101
+ };
102
+
103
+ // packages/lint-suite/src/lib/rules/no-unstyled-classes/styles/component-stylesheets.ts
104
+ var SIBLING_EXTENSIONS = [".scss", ".css"];
105
+ var HTML_EXTENSION = /\.html$/iu;
106
+ var matchesTemplate = (metadata, directory, templateFilename) => {
107
+ const urls = metadataTexts(metadata, "templateUrl");
108
+ const [templateUrl] = urls;
109
+ if (templateUrl === void 0) return false;
110
+ const declared = resolve(directory, templateUrl);
111
+ const linted = resolve(templateFilename);
112
+ return declared === linted;
113
+ };
114
+ var templateMetadata = (componentPath, templateFilename) => {
115
+ const components = componentMetadata(componentPath);
116
+ const directory = dirname(componentPath);
117
+ const matches = (metadata) => {
118
+ return matchesTemplate(metadata, directory, templateFilename);
119
+ };
120
+ const matched = components.find(matches);
121
+ if (matched !== void 0) return matched;
122
+ const isOnly = components.length === 1;
123
+ if (!isOnly) return null;
124
+ const [only] = components;
125
+ return only ?? null;
126
+ };
127
+ var stylesheetFiles = (paths, directory) => {
128
+ const sources = [];
129
+ for (const path of paths) {
130
+ const resolved = resolve(directory, path);
131
+ const isPresent = existsSync(resolved);
132
+ if (!isPresent) continue;
133
+ const source = { kind: "file", path: resolved };
134
+ sources.push(source);
135
+ }
136
+ return sources;
137
+ };
138
+ var inlineSources = (styles, componentPath) => {
139
+ const sourceOf = (style) => {
140
+ const source = {
141
+ kind: "inline",
142
+ source: style,
143
+ path: componentPath
144
+ };
145
+ return source;
146
+ };
147
+ return styles.map(sourceOf);
148
+ };
149
+ var metadataSources = (componentPath, templateFilename) => {
150
+ const metadata = templateMetadata(componentPath, templateFilename);
151
+ if (metadata === null) return [];
152
+ const singleUrl = metadataTexts(metadata, "styleUrl");
153
+ const listedUrls = metadataTexts(metadata, "styleUrls");
154
+ const styles = metadataTexts(metadata, "styles");
155
+ const directory = dirname(componentPath);
156
+ const urls = [...singleUrl, ...listedUrls];
157
+ const files = stylesheetFiles(urls, directory);
158
+ const inline = inlineSources(styles, componentPath);
159
+ return [...files, ...inline];
160
+ };
161
+ var siblingSources = (templateFilename) => {
162
+ const base2 = templateFilename.replace(HTML_EXTENSION, "");
163
+ const candidateOf = (extension) => `${base2}${extension}`;
164
+ const candidates = SIBLING_EXTENSIONS.map(candidateOf);
165
+ return stylesheetFiles(candidates, dirname(templateFilename));
166
+ };
167
+ var componentStylesheets = (templateFilename) => {
168
+ const componentPath = templateFilename.replace(HTML_EXTENSION, ".ts");
169
+ const sources = metadataSources(componentPath, templateFilename);
170
+ if (sources.length > 0) return sources;
171
+ return siblingSources(templateFilename);
172
+ };
173
+
174
+ // packages/lint-suite/src/lib/rules/no-unstyled-classes/styles/stylesheet-classes.ts
175
+ import { readFileSync as readFileSync2, statSync } from "node:fs";
176
+ import { dirname as dirname3 } from "node:path";
177
+ import { parse } from "postcss-scss";
178
+
179
+ // packages/lint-suite/src/lib/rules/no-unstyled-classes/styles/stylesheet-imports.ts
180
+ import { existsSync as existsSync2 } from "node:fs";
181
+ import { basename, dirname as dirname2, join, resolve as resolve2 } from "node:path";
182
+ var QUOTED = /'([^']*)'|"([^"]*)"/u;
183
+ var SKIPPED_PREFIXES = ["sass:", "http", "url("];
184
+ var specifierOf = (params) => {
185
+ const match = QUOTED.exec(params);
186
+ if (!match) return null;
187
+ return match[1] ?? match[2] ?? null;
188
+ };
189
+ var isResolvable = (specifier) => {
190
+ const isEmpty = specifier.length === 0;
191
+ if (isEmpty) return false;
192
+ const isSkipped = SKIPPED_PREFIXES.some(
193
+ (prefix) => specifier.startsWith(prefix)
194
+ );
195
+ if (isSkipped) return false;
196
+ return !specifier.endsWith(".css");
197
+ };
198
+ var candidatesOf = (path) => {
199
+ const isStylesheet = path.endsWith(".scss");
200
+ if (isStylesheet) return [path, join(dirname2(path), `_${basename(path)}`)];
201
+ const partial = join(dirname2(path), `_${basename(path)}.scss`);
202
+ return [
203
+ `${path}.scss`,
204
+ partial,
205
+ join(path, "index.scss"),
206
+ join(path, "_index.scss")
207
+ ];
208
+ };
209
+ var resolveStylesheetImport = (params, directory) => {
210
+ const specifier = specifierOf(params);
211
+ if (specifier === null) return null;
212
+ const isCandidate = isResolvable(specifier);
213
+ if (!isCandidate) return null;
214
+ const path = resolve2(directory, specifier);
215
+ const candidates = candidatesOf(path);
216
+ const existing = candidates.find((candidate) => existsSync2(candidate));
217
+ return existing ?? null;
218
+ };
219
+
220
+ // packages/lint-suite/src/lib/rules/utils/selector-classes.util.ts
221
+ import selectorParser from "postcss-selector-parser";
222
+ var INTERPOLATION_TOKEN = "zzinterpzz";
223
+ var PARENT_TOKEN = "zzparentzz";
224
+ var UNKNOWN_PARENT_SELECTOR = `.${PARENT_TOKEN}`;
225
+ var UNKNOWN_PARTS = new RegExp(
226
+ `${INTERPOLATION_TOKEN}|${PARENT_TOKEN}`,
227
+ "gu"
228
+ );
229
+ var INTERPOLATION = /#\{[^}]*\}/gu;
230
+ var REGEXP_META = /[.*+?^${}()|[\]\\]/gu;
231
+ var escapeRegExp = (part) => {
232
+ return part.replaceAll(REGEXP_META, "\\$&");
233
+ };
234
+ var classNamePattern = (value) => {
235
+ const literals = value.split(UNKNOWN_PARTS).map(escapeRegExp);
236
+ const joined = literals.join(".*");
237
+ return `^${joined}$`;
238
+ };
239
+ var withoutParent = (selector) => {
240
+ return selector.replaceAll("&", UNKNOWN_PARENT_SELECTOR);
241
+ };
242
+ var withParent = (selector, parent) => {
243
+ const hasNesting = selector.includes("&");
244
+ if (hasNesting) return selector.replaceAll("&", parent);
245
+ return `${parent} ${selector}`;
246
+ };
247
+ var resolveSelectors = (selectors, parents) => {
248
+ const hasParents = parents.length > 0;
249
+ if (!hasParents) return selectors.map(withoutParent);
250
+ const resolved = [];
251
+ for (const parent of parents) {
252
+ for (const selector of selectors) {
253
+ resolved.push(withParent(selector, parent));
254
+ }
255
+ }
256
+ return resolved;
257
+ };
258
+ var selectorClasses = (selector) => {
259
+ const exact = [];
260
+ const patterns = [];
261
+ const normalized = selector.replaceAll(INTERPOLATION, INTERPOLATION_TOKEN);
262
+ const collect2 = (node) => {
263
+ const isBareParent = node.value === PARENT_TOKEN;
264
+ if (isBareParent) return;
265
+ const hasInterpolation = node.value.includes(INTERPOLATION_TOKEN);
266
+ const hasUnknownParent = node.value.includes(PARENT_TOKEN);
267
+ const isDynamic = hasInterpolation || hasUnknownParent;
268
+ if (isDynamic) {
269
+ patterns.push(classNamePattern(node.value));
270
+ return;
271
+ }
272
+ exact.push(node.value);
273
+ };
274
+ try {
275
+ const root = selectorParser().astSync(normalized);
276
+ root.walkClasses(collect2);
277
+ } catch {
278
+ const empty = { exact: [], patterns: [] };
279
+ return empty;
280
+ }
281
+ const classes = { exact, patterns };
282
+ return classes;
283
+ };
284
+ var classMatcher = (exact, patterns) => {
285
+ const matches = (name) => {
286
+ const isExact = exact.has(name);
287
+ if (isExact) return true;
288
+ return patterns.some((pattern) => pattern.test(name));
289
+ };
290
+ return matches;
291
+ };
292
+
293
+ // packages/lint-suite/src/lib/rules/utils/resolved-rules.util.ts
294
+ var walkContainer = (container, parents, visit) => {
295
+ for (const node of container.nodes ?? []) {
296
+ if (node.type === "rule") {
297
+ const resolved = resolveSelectors(node.selectors, parents);
298
+ visit(node, resolved, parents);
299
+ walkContainer(node, resolved, visit);
300
+ continue;
301
+ }
302
+ if (node.type !== "atrule") continue;
303
+ walkContainer(node, parents, visit);
304
+ }
305
+ };
306
+ var walkResolvedRules = (root, visit) => {
307
+ walkContainer(root, [], visit);
308
+ };
309
+
310
+ // packages/lint-suite/src/lib/rules/no-unstyled-classes/styles/stylesheet-collection.ts
311
+ var IMPORT_AT_RULES = /* @__PURE__ */ new Set(["use", "import", "forward"]);
312
+ var addSelectors = (selectors, entry) => {
313
+ for (const selector of selectors) {
314
+ const { exact, patterns } = selectorClasses(selector);
315
+ entry.classes.push(...exact);
316
+ entry.patterns.push(...patterns);
317
+ }
318
+ };
319
+ var addImport = (node, entry, directory) => {
320
+ const isImport = IMPORT_AT_RULES.has(node.name);
321
+ if (!isImport) return;
322
+ const imported = resolveStylesheetImport(node.params, directory);
323
+ if (imported !== null) entry.imports.push(imported);
324
+ };
325
+ var collectStylesheet = (root, directory) => {
326
+ const entry = { classes: [], patterns: [], imports: [] };
327
+ const onRule = (_rule, resolved) => {
328
+ addSelectors(resolved, entry);
329
+ };
330
+ const onAtRule = (node) => {
331
+ addImport(node, entry, directory);
332
+ };
333
+ walkResolvedRules(root, onRule);
334
+ root.walkAtRules(onAtRule);
335
+ return entry;
336
+ };
337
+
338
+ // packages/lint-suite/src/lib/rules/no-unstyled-classes/styles/stylesheet-classes.ts
339
+ var stylesheets = /* @__PURE__ */ new Map();
340
+ var emptyEntry = () => {
341
+ const entry = { classes: [], patterns: [], imports: [] };
342
+ return entry;
343
+ };
344
+ var parseStylesheet = (source, path) => {
345
+ try {
346
+ const root = parse(source, { from: path });
347
+ return collectStylesheet(root, dirname3(path));
348
+ } catch {
349
+ return emptyEntry();
350
+ }
351
+ };
352
+ var fileEntry = (path) => {
353
+ try {
354
+ const stats = statSync(path, { bigint: true });
355
+ const version = `${stats.mtimeNs}:${stats.size}`;
356
+ const cached = stylesheets.get(path);
357
+ if (cached?.version === version) return cached.entry;
358
+ const entry = parseStylesheet(readFileSync2(path, "utf8"), path);
359
+ const fresh = { entry, version };
360
+ stylesheets.set(path, fresh);
361
+ return entry;
362
+ } catch {
363
+ return emptyEntry();
364
+ }
365
+ };
366
+ var addEntry = (entry, sink, visited) => {
367
+ for (const name of entry.classes) sink.exact.add(name);
368
+ sink.patterns.push(...entry.patterns);
369
+ for (const imported of entry.imports) {
370
+ const isVisited = visited.has(imported);
371
+ if (isVisited) continue;
372
+ visited.add(imported);
373
+ addEntry(fileEntry(imported), sink, visited);
374
+ }
375
+ };
376
+ var addSource = (source, sink, visited) => {
377
+ if (source.kind === "file") {
378
+ const isVisited = visited.has(source.path);
379
+ if (isVisited) return;
380
+ visited.add(source.path);
381
+ addEntry(fileEntry(source.path), sink, visited);
382
+ return;
383
+ }
384
+ addEntry(parseStylesheet(source.source, source.path), sink, visited);
385
+ };
386
+ var toRegExp = (pattern) => {
387
+ return new RegExp(pattern, "u");
388
+ };
389
+ var stylesheetClasses = (sources) => {
390
+ const exact = /* @__PURE__ */ new Set();
391
+ const patterns = [];
392
+ const sink = { exact, patterns };
393
+ const visited = /* @__PURE__ */ new Set();
394
+ for (const source of sources) addSource(source, sink, visited);
395
+ const compiled = patterns.map(toRegExp);
396
+ const has = classMatcher(exact, compiled);
397
+ const size = exact.size + compiled.length;
398
+ const classes = { has, size };
399
+ return classes;
400
+ };
401
+
402
+ // packages/lint-suite/src/lib/rules/no-unstyled-classes/styles/template-stylesheets.ts
403
+ var templateStylesheets = (templateFilename, cwd, globalStyles) => {
404
+ let known = null;
405
+ const lookup = () => {
406
+ if (known !== null) return known;
407
+ const component = componentStylesheets(templateFilename);
408
+ const global = stylesheetFiles(globalStyles, cwd);
409
+ const sources = [...component, ...global];
410
+ known = stylesheetClasses(sources);
411
+ return known;
412
+ };
413
+ return lookup;
414
+ };
415
+
416
+ // packages/lint-suite/src/lib/rules/utils/template-classes.util.ts
417
+ import { ParseSourceSpan as ParseSourceSpan2 } from "@angular/compiler";
418
+
419
+ // packages/lint-suite/src/lib/rules/utils/class-expression-literals.util.ts
420
+ import {
421
+ Conditional,
422
+ Interpolation,
423
+ Lexer,
424
+ LiteralArray,
425
+ LiteralMap,
426
+ LiteralPrimitive,
427
+ ParseLocation,
428
+ ParseSourceFile,
429
+ ParseSourceSpan,
430
+ Parser
431
+ } from "@angular/compiler";
432
+ var WHITESPACE = /\s+/u;
433
+ var EXPRESSION_FILE = "class-expression";
434
+ var parser = new Parser(new Lexer());
435
+ var spanOf = (source) => {
436
+ const file = new ParseSourceFile(source, EXPRESSION_FILE);
437
+ const start = new ParseLocation(file, 0, 0, 0);
438
+ const span = new ParseSourceSpan(start, start.moveBy(source.length));
439
+ return span;
440
+ };
441
+ var astOf = (parsed) => {
442
+ const hasErrors = parsed.errors.length > 0;
443
+ if (hasErrors) return null;
444
+ return parsed.ast;
445
+ };
446
+ var parseClassExpression = (source) => {
447
+ try {
448
+ const span = spanOf(source);
449
+ const interpolation = parser.parseInterpolation(source, span, 0, null);
450
+ if (interpolation) return astOf(interpolation);
451
+ const binding = parser.parseBinding(source, span, 0);
452
+ return astOf(binding);
453
+ } catch {
454
+ return null;
455
+ }
456
+ };
457
+ var addNames = (value, names) => {
458
+ for (const token of value.split(WHITESPACE)) {
459
+ if (token) names.push(token);
460
+ }
461
+ };
462
+ var addPrimitive = (ast, names) => {
463
+ if (typeof ast.value === "string") addNames(ast.value, names);
464
+ };
465
+ var addMapKeys = (ast, names) => {
466
+ for (const key2 of ast.keys) {
467
+ if (key2.kind !== "spread") addNames(key2.key, names);
468
+ }
469
+ };
470
+ var addInterpolation = (ast, names) => {
471
+ for (const text2 of ast.strings) addNames(text2, names);
472
+ };
473
+ var collect = (ast, names) => {
474
+ if (ast instanceof LiteralPrimitive) {
475
+ addPrimitive(ast, names);
476
+ return;
477
+ }
478
+ if (ast instanceof LiteralMap) {
479
+ addMapKeys(ast, names);
480
+ return;
481
+ }
482
+ if (ast instanceof Interpolation) {
483
+ addInterpolation(ast, names);
484
+ return;
485
+ }
486
+ if (ast instanceof LiteralArray) {
487
+ for (const expression of ast.expressions) collect(expression, names);
488
+ return;
489
+ }
490
+ if (ast instanceof Conditional) {
491
+ collect(ast.trueExp, names);
492
+ collect(ast.falseExp, names);
493
+ }
494
+ };
495
+ var classExpressionLiterals = (source) => {
496
+ const ast = parseClassExpression(source);
497
+ if (ast === null) return [];
498
+ const names = [];
499
+ collect(ast, names);
500
+ return [...new Set(names)];
501
+ };
502
+
503
+ // packages/lint-suite/src/lib/rules/utils/template-classes.util.ts
504
+ var CLASS_ATTRIBUTE = "class";
505
+ var CLASS_BINDING_PREFIX = "class.";
506
+ var TOKEN = /\S+/gu;
507
+ var expressionSource = (value) => {
508
+ if (!("source" in value)) return null;
509
+ const { source } = value;
510
+ if (typeof source !== "string") return null;
511
+ return source;
512
+ };
513
+ var staticClasses = (attribute) => {
514
+ const classes = [];
515
+ const valueSpan = attribute.valueSpan ?? attribute.sourceSpan;
516
+ for (const token of attribute.value.matchAll(TOKEN)) {
517
+ const start = valueSpan.start.moveBy(token.index);
518
+ const end = valueSpan.start.moveBy(token.index + token[0].length);
519
+ const span = new ParseSourceSpan2(start, end);
520
+ const templateClass = { name: token[0], span };
521
+ classes.push(templateClass);
522
+ }
523
+ return classes;
524
+ };
525
+ var boundClassName = (input) => {
526
+ const { details } = input.keySpan;
527
+ if (details === null) return null;
528
+ const isClassBinding = details.startsWith(CLASS_BINDING_PREFIX);
529
+ if (!isClassBinding) return null;
530
+ return input.name;
531
+ };
532
+ var isClassExpression = (input) => {
533
+ const isClassName = input.name === CLASS_ATTRIBUTE;
534
+ if (!isClassName) return false;
535
+ const { details } = input.keySpan;
536
+ if (details === null) return true;
537
+ return details === CLASS_ATTRIBUTE;
538
+ };
539
+ var expressionClasses = (input) => {
540
+ const source = expressionSource(input.value);
541
+ if (source === null) return [];
542
+ const names = classExpressionLiterals(source);
543
+ const templateClassOf = (name) => {
544
+ const templateClass = { name, span: input.sourceSpan };
545
+ return templateClass;
546
+ };
547
+ return names.map(templateClassOf);
548
+ };
549
+ var inputClasses = (input) => {
550
+ const bound = boundClassName(input);
551
+ if (bound !== null) {
552
+ const templateClass = { name: bound, span: input.keySpan };
553
+ return [templateClass];
554
+ }
555
+ const isExpression = isClassExpression(input);
556
+ if (!isExpression) return [];
557
+ return expressionClasses(input);
558
+ };
559
+ var templateClasses = (node) => {
560
+ const classes = [];
561
+ for (const attribute of node.attributes) {
562
+ const isClassName = attribute.name === CLASS_ATTRIBUTE;
563
+ if (isClassName) classes.push(...staticClasses(attribute));
564
+ }
565
+ for (const input of node.inputs) {
566
+ classes.push(...inputClasses(input));
567
+ }
568
+ return classes;
569
+ };
570
+
571
+ // packages/lint-suite/src/lib/rules/no-unstyled-classes/no-unstyled-classes.ts
572
+ var PARSER_REQUIRED = "no-unstyled-classes requires '@angular-eslint/template-parser'.";
573
+ var docs = {
574
+ description: "Disallow template class names that no stylesheet of the component selects"
575
+ };
576
+ var messages = {
577
+ unstyledClass: "Class '{{name}}' is not selected by any stylesheet of this template."
578
+ };
579
+ var stringItems = { type: "string" };
580
+ var ignoreClassPatternsSchema = {
581
+ type: "array",
582
+ items: stringItems,
583
+ description: "Regular expressions for class names that are never reported."
584
+ };
585
+ var globalStylesSchema = {
586
+ type: "array",
587
+ items: stringItems,
588
+ description: "Stylesheets merged into the known classes of every template."
589
+ };
590
+ var properties = {
591
+ ignoreClassPatterns: ignoreClassPatternsSchema,
592
+ globalStyles: globalStylesSchema
593
+ };
594
+ var optionsSchema = {
595
+ type: "object",
596
+ properties,
597
+ additionalProperties: false
598
+ };
599
+ var schema = [optionsSchema];
600
+ var meta = {
601
+ type: "problem",
602
+ docs,
603
+ schema,
604
+ messages
605
+ };
606
+ var ruleDefaults = {
607
+ ignoreClassPatterns: ["^(js|qa|mat|cdk|mdc)-"],
608
+ globalStyles: []
609
+ };
610
+ var defaultOptions = [ruleDefaults];
611
+ var createRule = ESLintUtils.RuleCreator(
612
+ () => "https://github.com/F0rty-Tw0/lint-suite#no-unstyled-classes"
613
+ );
614
+ var isTemplateServices = (services) => {
615
+ if (!("convertNodeSourceSpanToLoc" in services)) return false;
616
+ return typeof services.convertNodeSourceSpanToLoc === "function";
617
+ };
618
+ var toRegExp2 = (pattern) => new RegExp(pattern, "u");
619
+ var no_unstyled_classes_default = createRule({
620
+ name: "no-unstyled-classes",
621
+ meta,
622
+ defaultOptions,
623
+ create(context, [options]) {
624
+ const { parserServices } = context.sourceCode;
625
+ if (parserServices === void 0) throw new Error(PARSER_REQUIRED);
626
+ if (!isTemplateServices(parserServices)) throw new Error(PARSER_REQUIRED);
627
+ const ignored = options.ignoreClassPatterns.map(toRegExp2);
628
+ const stylesheets2 = templateStylesheets(
629
+ context.filename,
630
+ context.cwd,
631
+ options.globalStyles
632
+ );
633
+ const listeners = {
634
+ Element(node) {
635
+ const isCustomElement = node.name.includes("-");
636
+ if (isCustomElement) return;
637
+ const classes = templateClasses(node);
638
+ if (classes.length === 0) return;
639
+ const known = stylesheets2();
640
+ if (known.size === 0) return;
641
+ for (const { name, span } of classes) {
642
+ const isIgnored = ignored.some((pattern) => pattern.test(name));
643
+ if (isIgnored) continue;
644
+ const isStyled = known.has(name);
645
+ if (isStyled) continue;
646
+ const loc = parserServices.convertNodeSourceSpanToLoc(span);
647
+ const data = { name };
648
+ const report = {
649
+ loc,
650
+ messageId: "unstyledClass",
651
+ data
652
+ };
653
+ context.report(report);
654
+ }
655
+ }
656
+ };
657
+ return listeners;
658
+ }
659
+ });
660
+
661
+ // packages/lint-suite/src/lib/angular-template.ts
662
+ var lintSuiteAngularTemplatePlugin = definePlugin(
663
+ "lint-suite-angular-template",
664
+ { "no-unstyled-classes": no_unstyled_classes_default }
665
+ );
4
666
  var angularTemplate = defineConfig([
5
667
  {
6
668
  files: ["**/*.html"],
7
669
  extends: [...configs.templateAccessibility, ...configs.templateRecommended],
670
+ plugins: {
671
+ "lint-suite-angular-template": lintSuiteAngularTemplatePlugin
672
+ },
8
673
  rules: {
674
+ "lint-suite-angular-template/no-unstyled-classes": "error",
9
675
  "@angular-eslint/template/prefer-template-literal": "error",
10
676
  "@angular-eslint/template/no-any": "error",
11
677
  "@angular-eslint/template/no-duplicate-attributes": "error",
@@ -77,15 +743,8 @@ import { configs as configs2, processInlineTemplates } from "angular-eslint";
77
743
  import { defineConfig as defineConfig2 } from "eslint/config";
78
744
  import globals from "globals";
79
745
 
80
- // packages/lint-suite/src/lib/rules/define-plugin.util.ts
81
- var definePlugin = (name, rules) => {
82
- const meta5 = { name };
83
- const plugin = { meta: meta5, rules };
84
- return plugin;
85
- };
86
-
87
746
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/rule/no-unused-angular-instance-fields.ts
88
- import { ESLintUtils } from "@typescript-eslint/utils";
747
+ import { ESLintUtils as ESLintUtils2 } from "@typescript-eslint/utils";
89
748
 
90
749
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/rule/angular/angular-imports.ts
91
750
  import { TSESTree } from "@typescript-eslint/utils";
@@ -127,8 +786,8 @@ var addAngularImport = (node, imports) => {
127
786
  imports.set(specifier.local.name, null);
128
787
  } else if (specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier && specifier.importKind !== "type") {
129
788
  const { imported } = specifier;
130
- const isIdentifier8 = imported.type === TSESTree.AST_NODE_TYPES.Identifier;
131
- const importedName = isIdentifier8 ? imported.name : imported.value;
789
+ const isIdentifier9 = imported.type === TSESTree.AST_NODE_TYPES.Identifier;
790
+ const importedName = isIdentifier9 ? imported.name : imported.value;
132
791
  imports.set(specifier.local.name, importedName);
133
792
  }
134
793
  }
@@ -333,7 +992,7 @@ var methodCandidate = (node, localPrivateOnly, implementedMethods) => {
333
992
  };
334
993
 
335
994
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/rule/angular/angular-metadata-reads.ts
336
- import { dirname, resolve } from "node:path";
995
+ import { dirname as dirname4, resolve as resolve3 } from "node:path";
337
996
  import { TSESTree as TSESTree5 } from "@typescript-eslint/utils";
338
997
 
339
998
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/rule/angular/angular-metadata-literals.ts
@@ -345,7 +1004,9 @@ var text = (node) => {
345
1004
  if (node?.type !== TSESTree4.AST_NODE_TYPES.TemplateLiteral) return null;
346
1005
  const hasExpressions = node.expressions.length > 0;
347
1006
  if (hasExpressions) return null;
348
- return node.quasis[0].value.cooked;
1007
+ const [quasi] = node.quasis;
1008
+ if (quasi === void 0) return null;
1009
+ return quasi.value.cooked;
349
1010
  };
350
1011
  var key = (property) => {
351
1012
  if (property.type !== TSESTree4.AST_NODE_TYPES.Property || property.computed) {
@@ -356,7 +1017,7 @@ var key = (property) => {
356
1017
  }
357
1018
  return text(property.key);
358
1019
  };
359
- var metadataValue = (metadata, name) => {
1020
+ var metadataValue2 = (metadata, name) => {
360
1021
  for (const property of metadata.properties) {
361
1022
  if (property.type !== TSESTree4.AST_NODE_TYPES.Property) continue;
362
1023
  const propertyKey = key(property);
@@ -367,15 +1028,15 @@ var metadataValue = (metadata, name) => {
367
1028
 
368
1029
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/rule/angular/angular-template-parsing.ts
369
1030
  import {
370
- Lexer,
371
- ParseLocation,
372
- ParseSourceFile,
373
- ParseSourceSpan,
374
- Parser,
1031
+ Lexer as Lexer2,
1032
+ ParseLocation as ParseLocation2,
1033
+ ParseSourceFile as ParseSourceFile2,
1034
+ ParseSourceSpan as ParseSourceSpan3,
1035
+ Parser as Parser2,
375
1036
  R3TargetBinder,
376
1037
  parseTemplate
377
1038
  } from "@angular/compiler";
378
- import { readFileSync, statSync } from "node:fs";
1039
+ import { readFileSync as readFileSync3, statSync as statSync2 } from "node:fs";
379
1040
 
380
1041
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/rule/angular/angular-expression-reads.ts
381
1042
  import {
@@ -453,7 +1114,7 @@ var collectAngularExpressionReads = (nodes, boundTarget, action) => {
453
1114
 
454
1115
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/rule/angular/angular-template-parsing.ts
455
1116
  var externalTemplates = /* @__PURE__ */ new Map();
456
- var parser = new Parser(new Lexer());
1117
+ var parser2 = new Parser2(new Lexer2());
457
1118
  var templateBinder = new R3TargetBinder(null);
458
1119
  var templateReads = (template, filename) => {
459
1120
  try {
@@ -470,11 +1131,11 @@ var templateReads = (template, filename) => {
470
1131
  };
471
1132
  var externalTemplateReads = (filename) => {
472
1133
  try {
473
- const stats = statSync(filename, { bigint: true });
1134
+ const stats = statSync2(filename, { bigint: true });
474
1135
  const version = `${stats.mtimeNs}:${stats.size}`;
475
1136
  const cached = externalTemplates.get(filename);
476
1137
  if (cached?.version === version) return cached.reads;
477
- const reads = templateReads(readFileSync(filename, "utf8"), filename);
1138
+ const reads = templateReads(readFileSync3(filename, "utf8"), filename);
478
1139
  externalTemplates.set(filename, { reads, version });
479
1140
  return reads;
480
1141
  } catch {
@@ -482,14 +1143,14 @@ var externalTemplateReads = (filename) => {
482
1143
  }
483
1144
  };
484
1145
  var parseExpression = (expression, span, action) => {
485
- if (action) return parser.parseAction(expression, span, 0);
486
- return parser.parseBinding(expression, span, 0);
1146
+ if (action) return parser2.parseAction(expression, span, 0);
1147
+ return parser2.parseBinding(expression, span, 0);
487
1148
  };
488
1149
  var expressionReads = (expression, filename, action) => {
489
1150
  try {
490
- const file = new ParseSourceFile(expression, filename);
491
- const start = new ParseLocation(file, 0, 0, 0);
492
- const span = new ParseSourceSpan(start, start.moveBy(expression.length));
1151
+ const file = new ParseSourceFile2(expression, filename);
1152
+ const start = new ParseLocation2(file, 0, 0, 0);
1153
+ const span = new ParseSourceSpan3(start, start.moveBy(expression.length));
493
1154
  const result = parseExpression(expression, span, action);
494
1155
  if (result.errors.length > 0) return null;
495
1156
  return collectAngularExpressionReads([result], void 0, action);
@@ -542,11 +1203,11 @@ var inlineTemplateReads = (template, reads, filename) => {
542
1203
  var externalTemplatePropertyReads = (templateUrl, reads, filename) => {
543
1204
  if (!templateUrl) return true;
544
1205
  const url = text(templateUrl);
545
- return url !== null && addReads(reads, externalTemplateReads(resolve(dirname(filename), url)));
1206
+ return url !== null && addReads(reads, externalTemplateReads(resolve3(dirname4(filename), url)));
546
1207
  };
547
1208
  var componentTemplateReads = (metadata, reads, filename) => {
548
- const template = metadataValue(metadata, "template");
549
- const templateUrl = metadataValue(metadata, "templateUrl");
1209
+ const template = metadataValue2(metadata, "template");
1210
+ const templateUrl = metadataValue2(metadata, "templateUrl");
550
1211
  return inlineTemplateReads(template, reads, filename) && externalTemplatePropertyReads(templateUrl, reads, filename);
551
1212
  };
552
1213
  var metadataReads = (options) => {
@@ -557,7 +1218,7 @@ var metadataReads = (options) => {
557
1218
  const hasUnreadableKey = metadata.properties.some(isUnreadableKey);
558
1219
  if (hasUnreadableKey) return null;
559
1220
  const reads = /* @__PURE__ */ new Set();
560
- const hostValue = metadataValue(metadata, "host");
1221
+ const hostValue = metadataValue2(metadata, "host");
561
1222
  const hasHostReads = hostReads(hostValue, reads, filename);
562
1223
  if (!hasHostReads) return null;
563
1224
  if (!options.component) return reads;
@@ -913,7 +1574,7 @@ var classReadVisitor = (classes, stack, dynamicClasses) => {
913
1574
  };
914
1575
 
915
1576
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/project-usage.ts
916
- import { isClassElement, isIdentifier as isIdentifier7, isStringLiteralLike as isStringLiteralLike6 } from "typescript";
1577
+ import { isClassElement, isIdentifier as isIdentifier8, isStringLiteralLike as isStringLiteralLike7 } from "typescript";
917
1578
 
918
1579
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/angular/angular-directive-index.ts
919
1580
  import { CssSelector, SelectorMatcher } from "@angular/compiler";
@@ -974,8 +1635,8 @@ var buildDirectiveIndex = (classes) => {
974
1635
  };
975
1636
 
976
1637
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/angular/angular-template-reads.ts
977
- import { readFileSync as readFileSync2, statSync as statSync2 } from "node:fs";
978
- import { isIdentifier, isStringLiteralLike } from "typescript";
1638
+ import { readFileSync as readFileSync4, statSync as statSync3 } from "node:fs";
1639
+ import { isIdentifier as isIdentifier2, isStringLiteralLike as isStringLiteralLike2 } from "typescript";
979
1640
 
980
1641
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/angular/angular-template-read-resolution.ts
981
1642
  import {
@@ -1329,8 +1990,8 @@ var addTemplateReads = ({
1329
1990
  var memberNameOf = (member) => {
1330
1991
  const name = member.name;
1331
1992
  if (!name) return [];
1332
- const isIdentifierName = isIdentifier(name);
1333
- const isStringName = isStringLiteralLike(name);
1993
+ const isIdentifierName = isIdentifier2(name);
1994
+ const isStringName = isStringLiteralLike2(name);
1334
1995
  const isTextName = isIdentifierName || isStringName;
1335
1996
  if (!isTextName) return [];
1336
1997
  const names = [name.text];
@@ -1346,13 +2007,13 @@ var unknownTemplateNames = ({ declaration, scope }, allNames) => {
1346
2007
  return names;
1347
2008
  };
1348
2009
  var templateFileVersion = (fileName) => {
1349
- const { mtimeNs, size } = statSync2(fileName, { bigint: true });
2010
+ const { mtimeNs, size } = statSync3(fileName, { bigint: true });
1350
2011
  const version = { fileName, mtimeNs, size };
1351
2012
  return version;
1352
2013
  };
1353
2014
  var templateFileIsCurrent = (version) => {
1354
2015
  try {
1355
- const current = statSync2(version.fileName, { bigint: true });
2016
+ const current = statSync3(version.fileName, { bigint: true });
1356
2017
  return current.mtimeNs === version.mtimeNs && current.size === version.size;
1357
2018
  } catch {
1358
2019
  return false;
@@ -1376,7 +2037,7 @@ var templateSourceOf = (angularClass2, allNames, sink, versions) => {
1376
2037
  const templateFileName = template.fileName;
1377
2038
  try {
1378
2039
  versions.push(templateFileVersion(templateFileName));
1379
- const source = readFileSync2(templateFileName, "utf8");
2040
+ const source = readFileSync4(templateFileName, "utf8");
1380
2041
  const externalSource = {
1381
2042
  fileName: templateFileName,
1382
2043
  source
@@ -1425,7 +2086,7 @@ var collectAngularTemplateReads = ({
1425
2086
 
1426
2087
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/typescript/typescript-reads.ts
1427
2088
  import {
1428
- forEachChild,
2089
+ forEachChild as forEachChild2,
1429
2090
  isClassLike,
1430
2091
  isElementAccessExpression,
1431
2092
  isPropertyAccessExpression
@@ -1438,10 +2099,10 @@ import { SyntaxKind, isMethodSignature } from "typescript";
1438
2099
  import {
1439
2100
  SymbolFlags,
1440
2101
  isBigIntLiteral,
1441
- isIdentifier as isIdentifier2,
2102
+ isIdentifier as isIdentifier3,
1442
2103
  isNumericLiteral,
1443
2104
  isPrivateIdentifier,
1444
- isStringLiteralLike as isStringLiteralLike2
2105
+ isStringLiteralLike as isStringLiteralLike3
1445
2106
  } from "typescript";
1446
2107
  var aliasTarget = (checker, symbol) => {
1447
2108
  const isAlias = (symbol.flags & SymbolFlags.Alias) !== 0;
@@ -1496,9 +2157,9 @@ var literalPropertyNames = (type) => {
1496
2157
  return names;
1497
2158
  };
1498
2159
  var propertyName2 = (checker, node) => {
1499
- const isIdentifierName = isIdentifier2(node);
2160
+ const isIdentifierName = isIdentifier3(node);
1500
2161
  const isPrivateName = isPrivateIdentifier(node);
1501
- const isStringName = isStringLiteralLike2(node);
2162
+ const isStringName = isStringLiteralLike3(node);
1502
2163
  const isNumericName = isNumericLiteral(node);
1503
2164
  const isBigIntName = isBigIntLiteral(node);
1504
2165
  const isLiteralName = isIdentifierName || isPrivateName || isStringName || isNumericName || isBigIntName;
@@ -1546,31 +2207,31 @@ var collectAngularInterfaceMethods = (node, checker, sink) => {
1546
2207
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/typescript/typescript-destructuring-reads.ts
1547
2208
  import {
1548
2209
  SyntaxKind as SyntaxKind2,
1549
- isArrayLiteralExpression as isArrayLiteralExpression2,
2210
+ isArrayLiteralExpression as isArrayLiteralExpression3,
1550
2211
  isBinaryExpression,
1551
2212
  isBindingElement,
1552
- isObjectLiteralExpression as isObjectLiteralExpression2,
2213
+ isObjectLiteralExpression as isObjectLiteralExpression3,
1553
2214
  isVariableDeclaration
1554
2215
  } from "typescript";
1555
2216
 
1556
2217
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/typescript/typescript-assignment-pattern-elements.ts
1557
2218
  import {
1558
- isArrayLiteralExpression,
1559
- isObjectLiteralExpression,
2219
+ isArrayLiteralExpression as isArrayLiteralExpression2,
2220
+ isObjectLiteralExpression as isObjectLiteralExpression2,
1560
2221
  isOmittedExpression,
1561
- isPropertyAssignment,
2222
+ isPropertyAssignment as isPropertyAssignment2,
1562
2223
  isSpreadAssignment,
1563
2224
  isSpreadElement
1564
2225
  } from "typescript";
1565
2226
  var nestedPattern = (expression) => {
1566
- const isArrayLiteral = isArrayLiteralExpression(expression);
1567
- const isObjectLiteral = isObjectLiteralExpression(expression);
2227
+ const isArrayLiteral = isArrayLiteralExpression2(expression);
2228
+ const isObjectLiteral = isObjectLiteralExpression2(expression);
1568
2229
  const isNested = isArrayLiteral || isObjectLiteral;
1569
2230
  if (!isNested) return null;
1570
2231
  return expression;
1571
2232
  };
1572
2233
  var nestedPropertyPattern = (property) => {
1573
- const isAssignment = isPropertyAssignment(property);
2234
+ const isAssignment = isPropertyAssignment2(property);
1574
2235
  if (!isAssignment) return null;
1575
2236
  return nestedPattern(property.initializer);
1576
2237
  };
@@ -1609,7 +2270,7 @@ var propertyRead = (property, checker) => {
1609
2270
  return read;
1610
2271
  };
1611
2272
  var assignmentPatternElements = (pattern, checker) => {
1612
- const isArrayPattern = isArrayLiteralExpression(pattern);
2273
+ const isArrayPattern = isArrayLiteralExpression2(pattern);
1613
2274
  if (isArrayPattern) {
1614
2275
  const reads = [];
1615
2276
  for (const [index, element] of pattern.elements.entries()) {
@@ -1626,7 +2287,7 @@ var assignmentPatternElements = (pattern, checker) => {
1626
2287
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/typescript/typescript-binding-pattern-elements.ts
1627
2288
  import {
1628
2289
  isArrayBindingPattern,
1629
- isIdentifier as isIdentifier3,
2290
+ isIdentifier as isIdentifier4,
1630
2291
  isObjectBindingPattern,
1631
2292
  isOmittedExpression as isOmittedExpression2
1632
2293
  } from "typescript";
@@ -1642,7 +2303,7 @@ var nestedPattern2 = (element) => {
1642
2303
  };
1643
2304
  var bindingNames = (checker, element) => {
1644
2305
  if (element.propertyName) return propertyName2(checker, element.propertyName);
1645
- const isIdentifierName = isIdentifier3(element.name);
2306
+ const isIdentifierName = isIdentifier4(element.name);
1646
2307
  if (!isIdentifierName) return null;
1647
2308
  return [element.name.text];
1648
2309
  };
@@ -1763,8 +2424,8 @@ var collectAssignmentReads = (node, context) => {
1763
2424
  if (!isBinary) return;
1764
2425
  const isEqualsAssignment = node.operatorToken.kind === SyntaxKind2.EqualsToken;
1765
2426
  if (!isEqualsAssignment) return;
1766
- const isArrayTarget = isArrayLiteralExpression2(node.left);
1767
- const isObjectTarget = isObjectLiteralExpression2(node.left);
2427
+ const isArrayTarget = isArrayLiteralExpression3(node.left);
2428
+ const isObjectTarget = isObjectLiteralExpression3(node.left);
1768
2429
  const isDestructuringAssignment = isArrayTarget || isObjectTarget;
1769
2430
  if (!isDestructuringAssignment) return;
1770
2431
  const rightTypeOf = () => context.checker.getTypeAtLocation(node.right);
@@ -1780,16 +2441,16 @@ var collectDestructuringReads = (node, checker, sink, candidateNames) => {
1780
2441
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/typescript/typescript-write-targets.ts
1781
2442
  import {
1782
2443
  SyntaxKind as SyntaxKind3,
1783
- isArrayLiteralExpression as isArrayLiteralExpression3,
2444
+ isArrayLiteralExpression as isArrayLiteralExpression4,
1784
2445
  isAsExpression,
1785
2446
  isBinaryExpression as isBinaryExpression2,
1786
2447
  isDeleteExpression,
1787
2448
  isForInStatement,
1788
2449
  isForOfStatement,
1789
2450
  isNonNullExpression,
1790
- isObjectLiteralExpression as isObjectLiteralExpression3,
2451
+ isObjectLiteralExpression as isObjectLiteralExpression4,
1791
2452
  isParenthesizedExpression,
1792
- isPropertyAssignment as isPropertyAssignment2,
2453
+ isPropertyAssignment as isPropertyAssignment3,
1793
2454
  isSatisfiesExpression,
1794
2455
  isSpreadAssignment as isSpreadAssignment2,
1795
2456
  isTypeAssertionExpression
@@ -1806,15 +2467,15 @@ var isExpressionWrapper = (parent, child) => {
1806
2467
  return parent.expression === child;
1807
2468
  };
1808
2469
  var isPatternContainer = (parent, child) => {
1809
- const isArrayLiteral = isArrayLiteralExpression3(parent);
2470
+ const isArrayLiteral = isArrayLiteralExpression4(parent);
1810
2471
  if (isArrayLiteral) {
1811
2472
  return parent.elements.some((element) => element === child);
1812
2473
  }
1813
- const isObjectLiteral = isObjectLiteralExpression3(parent);
2474
+ const isObjectLiteral = isObjectLiteralExpression4(parent);
1814
2475
  if (isObjectLiteral) {
1815
2476
  return parent.properties.some((property) => property === child);
1816
2477
  }
1817
- const isAssignment = isPropertyAssignment2(parent);
2478
+ const isAssignment = isPropertyAssignment3(parent);
1818
2479
  if (isAssignment) return parent.initializer === child;
1819
2480
  const isSpread = isSpreadAssignment2(parent);
1820
2481
  if (!isSpread) return false;
@@ -1879,7 +2540,7 @@ var collectTypeScriptReads = (sourceFile, checker, sink, candidateNames) => {
1879
2540
  collectAngularInterfaceMethods(node, checker, sink);
1880
2541
  }
1881
2542
  collectDestructuringReads(node, checker, sink, candidateNames);
1882
- forEachChild(node, visit);
2543
+ forEachChild2(node, visit);
1883
2544
  };
1884
2545
  visit(sourceFile);
1885
2546
  };
@@ -1987,43 +2648,43 @@ var computeEntry = (index, sourceFile, checker) => {
1987
2648
  };
1988
2649
  const reads = collectFileReads(index, sourceFile, checker, sink);
1989
2650
  dependencies.delete(sourceFile);
1990
- const fileEntry = {
2651
+ const fileEntry2 = {
1991
2652
  ...reads,
1992
2653
  declarations,
1993
2654
  dependencies,
1994
2655
  fallbackNames,
1995
2656
  sourceFile
1996
2657
  };
1997
- return fileEntry;
2658
+ return fileEntry2;
1998
2659
  };
1999
2660
 
2000
2661
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/angular/angular-component-discovery.ts
2001
2662
  import {
2002
- canHaveDecorators as canHaveDecorators2,
2003
- forEachChild as forEachChild2,
2004
- getDecorators as getDecorators2,
2005
- isCallExpression as isCallExpression2,
2663
+ canHaveDecorators as canHaveDecorators3,
2664
+ forEachChild as forEachChild3,
2665
+ getDecorators as getDecorators3,
2666
+ isCallExpression as isCallExpression3,
2006
2667
  isClassLike as isClassLike3,
2007
- isObjectLiteralExpression as isObjectLiteralExpression4
2668
+ isObjectLiteralExpression as isObjectLiteralExpression5
2008
2669
  } from "typescript";
2009
2670
 
2010
2671
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/angular/angular-component-scope.ts
2011
2672
  import {
2012
2673
  SyntaxKind as SyntaxKind4,
2013
- isArrayLiteralExpression as isArrayLiteralExpression4,
2674
+ isArrayLiteralExpression as isArrayLiteralExpression5,
2014
2675
  isClassLike as isClassLike2,
2015
- isIdentifier as isIdentifier5,
2676
+ isIdentifier as isIdentifier6,
2016
2677
  isPropertyAccessExpression as isPropertyAccessExpression3
2017
2678
  } from "typescript";
2018
2679
 
2019
2680
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/angular/angular-decorator-kind.ts
2020
2681
  import {
2021
2682
  SymbolFlags as SymbolFlags2,
2022
- canHaveDecorators,
2023
- getDecorators,
2024
- isCallExpression,
2683
+ canHaveDecorators as canHaveDecorators2,
2684
+ getDecorators as getDecorators2,
2685
+ isCallExpression as isCallExpression2,
2025
2686
  isImportDeclaration,
2026
- isStringLiteralLike as isStringLiteralLike3
2687
+ isStringLiteralLike as isStringLiteralLike4
2027
2688
  } from "typescript";
2028
2689
  var decoratorKinds = [
2029
2690
  "Component",
@@ -2045,7 +2706,7 @@ var importedFromAngularCore = (declaration) => {
2045
2706
  let current = parentOf2(declaration);
2046
2707
  while (current) {
2047
2708
  if (isImportDeclaration(current)) {
2048
- return isStringLiteralLike3(current.moduleSpecifier) && current.moduleSpecifier.text === "@angular/core";
2709
+ return isStringLiteralLike4(current.moduleSpecifier) && current.moduleSpecifier.text === "@angular/core";
2049
2710
  }
2050
2711
  current = parentOf2(current);
2051
2712
  }
@@ -2080,10 +2741,10 @@ var angularDecoratorKind = (expression, discovery) => {
2080
2741
  return name;
2081
2742
  };
2082
2743
  var classDecoratorKind = (declaration, discovery) => {
2083
- const hasDecorators = canHaveDecorators(declaration);
2744
+ const hasDecorators = canHaveDecorators2(declaration);
2084
2745
  if (!hasDecorators) return null;
2085
- for (const decorator of getDecorators(declaration) ?? []) {
2086
- const isDecoratorCall = isCallExpression(decorator.expression);
2746
+ for (const decorator of getDecorators2(declaration) ?? []) {
2747
+ const isDecoratorCall = isCallExpression2(decorator.expression);
2087
2748
  if (!isDecoratorCall) continue;
2088
2749
  const kind = angularDecoratorKind(
2089
2750
  decorator.expression.expression,
@@ -2095,23 +2756,23 @@ var classDecoratorKind = (declaration, discovery) => {
2095
2756
  };
2096
2757
 
2097
2758
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/angular/angular-metadata-values.ts
2098
- import { dirname as dirname2, resolve as resolve2 } from "node:path";
2759
+ import { dirname as dirname5, resolve as resolve4 } from "node:path";
2099
2760
  import {
2100
- isIdentifier as isIdentifier4,
2761
+ isIdentifier as isIdentifier5,
2101
2762
  isNumericLiteral as isNumericLiteral2,
2102
2763
  isPropertyAccessExpression as isPropertyAccessExpression2,
2103
- isPropertyAssignment as isPropertyAssignment3,
2104
- isStringLiteralLike as isStringLiteralLike4
2764
+ isPropertyAssignment as isPropertyAssignment4,
2765
+ isStringLiteralLike as isStringLiteralLike5
2105
2766
  } from "typescript";
2106
2767
  var stringValue = (node, discovery) => {
2107
2768
  if (!node) return null;
2108
- const isStringLiteral = isStringLiteralLike4(node);
2769
+ const isStringLiteral = isStringLiteralLike5(node);
2109
2770
  if (isStringLiteral) return node.text;
2110
- const isIdentifierNode = isIdentifier4(node);
2771
+ const isIdentifierNode = isIdentifier5(node);
2111
2772
  const isPropertyAccessNode = isPropertyAccessExpression2(node);
2112
2773
  if (isIdentifierNode || isPropertyAccessNode) {
2113
2774
  const symbol = discovery.checker.getSymbolAtLocation(
2114
- isIdentifier4(node) ? node : node.name
2775
+ isIdentifier5(node) ? node : node.name
2115
2776
  );
2116
2777
  if (symbol) {
2117
2778
  resolveAlias(symbol, discovery);
@@ -2122,10 +2783,10 @@ var stringValue = (node, discovery) => {
2122
2783
  };
2123
2784
  var metadataProperty = (metadata, name) => {
2124
2785
  for (const property of metadata.properties) {
2125
- const isAssignment = isPropertyAssignment3(property);
2786
+ const isAssignment = isPropertyAssignment4(property);
2126
2787
  if (!isAssignment) continue;
2127
- const isIdentifierName = isIdentifier4(property.name);
2128
- const isStringName = isStringLiteralLike4(property.name);
2788
+ const isIdentifierName = isIdentifier5(property.name);
2789
+ const isStringName = isStringLiteralLike5(property.name);
2129
2790
  const isNumericName = isNumericLiteral2(property.name);
2130
2791
  const isLiteralName = isIdentifierName || isStringName || isNumericName;
2131
2792
  const isPropertyNamed = isLiteralName && property.name.text === name;
@@ -2145,7 +2806,7 @@ var templateOf = (metadata, fileName, discovery) => {
2145
2806
  if (url) {
2146
2807
  const text2 = stringValue(url, discovery);
2147
2808
  if (text2 === null) return void 0;
2148
- const externalFileName = resolve2(dirname2(fileName), text2);
2809
+ const externalFileName = resolve4(dirname5(fileName), text2);
2149
2810
  const externalTemplate = {
2150
2811
  fileName: externalFileName,
2151
2812
  kind: "external"
@@ -2185,7 +2846,7 @@ var scopedClasses = (classes, discovery) => {
2185
2846
  return scoped;
2186
2847
  };
2187
2848
  var importedClasses = (element, discovery) => {
2188
- const isIdentifierElement = isIdentifier5(element);
2849
+ const isIdentifierElement = isIdentifier6(element);
2189
2850
  const isPropertyAccessElement = isPropertyAccessExpression3(element);
2190
2851
  if (!isIdentifierElement && !isPropertyAccessElement) return null;
2191
2852
  const target = isIdentifierElement ? element : element.name;
@@ -2201,7 +2862,7 @@ var scopeOf = (metadata, discovery) => {
2201
2862
  const isModuleDeclared = standalone === void 0 && !imports;
2202
2863
  if (standalone === false || isModuleDeclared) return null;
2203
2864
  if (!imports) return [];
2204
- const isImportsArray = isArrayLiteralExpression4(imports);
2865
+ const isImportsArray = isArrayLiteralExpression5(imports);
2205
2866
  if (!isImportsArray) return null;
2206
2867
  const scope = [];
2207
2868
  for (const element of imports.elements) {
@@ -2254,7 +2915,7 @@ var decoratedClass = (declaration, call, discovery) => {
2254
2915
  const bareDiscovery = { ...base2, valid: !component };
2255
2916
  return bareDiscovery;
2256
2917
  }
2257
- const isMetadataObject = isObjectLiteralExpression4(metadata);
2918
+ const isMetadataObject = isObjectLiteralExpression5(metadata);
2258
2919
  if (!isMetadataObject) {
2259
2920
  const invalidDiscovery = { ...base2, valid: false };
2260
2921
  return invalidDiscovery;
@@ -2262,10 +2923,10 @@ var decoratedClass = (declaration, call, discovery) => {
2262
2923
  return describedClass(base2, metadata, discovery);
2263
2924
  };
2264
2925
  var angularClass = (declaration, discovery) => {
2265
- const hasDecorators = canHaveDecorators2(declaration);
2926
+ const hasDecorators = canHaveDecorators3(declaration);
2266
2927
  if (!hasDecorators) return null;
2267
- for (const decorator of getDecorators2(declaration) ?? []) {
2268
- const isDecoratorCall = isCallExpression2(decorator.expression);
2928
+ for (const decorator of getDecorators3(declaration) ?? []) {
2929
+ const isDecoratorCall = isCallExpression3(decorator.expression);
2269
2930
  if (!isDecoratorCall) continue;
2270
2931
  const found = decoratedClass(declaration, decorator.expression, discovery);
2271
2932
  if (found) return found;
@@ -2283,7 +2944,7 @@ var angularClasses = (sourceFile, checker) => {
2283
2944
  classes.push(found);
2284
2945
  }
2285
2946
  }
2286
- forEachChild2(node, visit);
2947
+ forEachChild3(node, visit);
2287
2948
  };
2288
2949
  visit(sourceFile);
2289
2950
  discovery.dependencies.delete(sourceFile);
@@ -2385,17 +3046,17 @@ var dropStaleTemplateEntries = (index, force) => {
2385
3046
 
2386
3047
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/typescript/typescript-candidate-names.ts
2387
3048
  import {
2388
- canHaveDecorators as canHaveDecorators3,
2389
- forEachChild as forEachChild3,
2390
- getDecorators as getDecorators3,
3049
+ canHaveDecorators as canHaveDecorators4,
3050
+ forEachChild as forEachChild4,
3051
+ getDecorators as getDecorators4,
2391
3052
  isClassLike as isClassLike4,
2392
- isIdentifier as isIdentifier6,
2393
- isStringLiteralLike as isStringLiteralLike5
3053
+ isIdentifier as isIdentifier7,
3054
+ isStringLiteralLike as isStringLiteralLike6
2394
3055
  } from "typescript";
2395
3056
  var isDecoratedClass = (node) => {
2396
- const isDecoratable = canHaveDecorators3(node);
3057
+ const isDecoratable = canHaveDecorators4(node);
2397
3058
  if (!isDecoratable) return false;
2398
- const decorators = getDecorators3(node);
3059
+ const decorators = getDecorators4(node);
2399
3060
  const decoratorCount = decorators?.length ?? 0;
2400
3061
  return decoratorCount > 0;
2401
3062
  };
@@ -2406,8 +3067,8 @@ var addMemberNames = (node, names) => {
2406
3067
  if (!isDecorated) return;
2407
3068
  for (const member of node.members) {
2408
3069
  if (!member.name) continue;
2409
- const isIdentifierName = isIdentifier6(member.name);
2410
- const isStringName = isStringLiteralLike5(member.name);
3070
+ const isIdentifierName = isIdentifier7(member.name);
3071
+ const isStringName = isStringLiteralLike6(member.name);
2411
3072
  const isNamedMember = isIdentifierName || isStringName;
2412
3073
  if (isNamedMember) {
2413
3074
  names.add(member.name.text);
@@ -2418,7 +3079,7 @@ var collectCandidateNames = (sourceFile) => {
2418
3079
  const names = /* @__PURE__ */ new Set();
2419
3080
  const visit = (node) => {
2420
3081
  addMemberNames(node, names);
2421
- forEachChild3(node, visit);
3082
+ forEachChild4(node, visit);
2422
3083
  };
2423
3084
  visit(sourceFile);
2424
3085
  return names;
@@ -2537,8 +3198,8 @@ var memberName = (node) => {
2537
3198
  const isMember = isClassElement(node);
2538
3199
  if (!isMember) return null;
2539
3200
  if (!node.name) return null;
2540
- const isIdentifierName = isIdentifier7(node.name);
2541
- const isStringName = isStringLiteralLike6(node.name);
3201
+ const isIdentifierName = isIdentifier8(node.name);
3202
+ const isStringName = isStringLiteralLike7(node.name);
2542
3203
  const isNamedMember = isIdentifierName || isStringName;
2543
3204
  if (!isNamedMember) return null;
2544
3205
  return node.name.text;
@@ -2602,10 +3263,10 @@ var projectUsage = (program) => {
2602
3263
  };
2603
3264
 
2604
3265
  // packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/rule/no-unused-angular-instance-fields.ts
2605
- var docs = {
3266
+ var docs2 = {
2606
3267
  description: "Disallow unread instance fields and methods in Angular components and directives"
2607
3268
  };
2608
- var messages = {
3269
+ var messages2 = {
2609
3270
  unusedField: "Angular instance field '{{name}}' is never read.",
2610
3271
  unusedMethod: "Angular instance method '{{name}}' is never read."
2611
3272
  };
@@ -2618,34 +3279,34 @@ var analysisSchema = {
2618
3279
  enum: ["local", "project"],
2619
3280
  description: "Choose local-file or typed whole-project analysis."
2620
3281
  };
2621
- var properties = {
3282
+ var properties2 = {
2622
3283
  allowEffectFields: allowEffectFieldsSchema,
2623
3284
  analysis: analysisSchema
2624
3285
  };
2625
- var optionsSchema = {
3286
+ var optionsSchema2 = {
2626
3287
  type: "object",
2627
- properties,
3288
+ properties: properties2,
2628
3289
  additionalProperties: false
2629
3290
  };
2630
- var schema = [optionsSchema];
2631
- var meta = {
3291
+ var schema2 = [optionsSchema2];
3292
+ var meta2 = {
2632
3293
  type: "problem",
2633
- docs,
2634
- schema,
2635
- messages
3294
+ docs: docs2,
3295
+ schema: schema2,
3296
+ messages: messages2
2636
3297
  };
2637
- var ruleDefaults = {
3298
+ var ruleDefaults2 = {
2638
3299
  allowEffectFields: false,
2639
3300
  analysis: "local"
2640
3301
  };
2641
- var defaultOptions = [ruleDefaults];
2642
- var createRule = ESLintUtils.RuleCreator(
3302
+ var defaultOptions2 = [ruleDefaults2];
3303
+ var createRule2 = ESLintUtils2.RuleCreator(
2643
3304
  () => "https://eslint.org/docs/latest/rules/no-unused-private-class-members"
2644
3305
  );
2645
3306
  var projectParserServices = (context, analysis) => {
2646
3307
  if (analysis !== "project") return void 0;
2647
3308
  try {
2648
- return ESLintUtils.getParserServices(context);
3309
+ return ESLintUtils2.getParserServices(context);
2649
3310
  } catch {
2650
3311
  throw new Error(
2651
3312
  "Project analysis requires parser services with type information."
@@ -2663,10 +3324,10 @@ var projectMemberUsedFor = (parserServices) => {
2663
3324
  };
2664
3325
  return memberUsed;
2665
3326
  };
2666
- var no_unused_angular_instance_fields_default = createRule({
3327
+ var no_unused_angular_instance_fields_default = createRule2({
2667
3328
  name: "no-unused-instance-fields",
2668
- meta,
2669
- defaultOptions,
3329
+ meta: meta2,
3330
+ defaultOptions: defaultOptions2,
2670
3331
  create(context, [options]) {
2671
3332
  const analysis = options.analysis ?? "local";
2672
3333
  const isSpec = isSpecFile(context.filename);
@@ -2706,6 +3367,9 @@ var no_unused_angular_instance_fields_default = createRule({
2706
3367
  var lintSuiteAngularPlugin = definePlugin("lint-suite-angular", {
2707
3368
  "no-unused-instance-fields": no_unused_angular_instance_fields_default
2708
3369
  });
3370
+ var inlineTemplates = processInlineTemplates && {
3371
+ processor: processInlineTemplates
3372
+ };
2709
3373
  var angular = defineConfig2([
2710
3374
  {
2711
3375
  files: ["**/*.ts"],
@@ -2723,7 +3387,7 @@ var angular = defineConfig2([
2723
3387
  projectService: true
2724
3388
  }
2725
3389
  },
2726
- processor: processInlineTemplates,
3390
+ ...inlineTemplates,
2727
3391
  rules: {
2728
3392
  "lint-suite-angular/no-unused-instance-fields": [
2729
3393
  "error",
@@ -2833,6 +3497,11 @@ var baseLimits = defineConfig3([
2833
3497
 
2834
3498
  // packages/lint-suite/src/lib/base-practices.ts
2835
3499
  import { defineConfig as defineConfig4 } from "eslint/config";
3500
+
3501
+ // packages/lint-suite/src/lib/line-length.const.ts
3502
+ var MAX_LINE_LENGTH = 135;
3503
+
3504
+ // packages/lint-suite/src/lib/base-practices.ts
2836
3505
  var basePractices = defineConfig4([
2837
3506
  {
2838
3507
  files: [
@@ -2891,7 +3560,7 @@ var basePractices = defineConfig4([
2891
3560
  "max-len": [
2892
3561
  "error",
2893
3562
  {
2894
- code: 135,
3563
+ code: MAX_LINE_LENGTH,
2895
3564
  ignoreComments: true
2896
3565
  }
2897
3566
  ],
@@ -3446,7 +4115,7 @@ var typescriptRecommended = defineConfig17([
3446
4115
  import { defineConfig as defineConfig18 } from "eslint/config";
3447
4116
 
3448
4117
  // packages/lint-suite/src/lib/rules/explicit-accessibility/explicit-accessibility.ts
3449
- import { ESLintUtils as ESLintUtils2, TSESTree as TSESTree10 } from "@typescript-eslint/utils";
4118
+ import { ESLintUtils as ESLintUtils3, TSESTree as TSESTree10 } from "@typescript-eslint/utils";
3450
4119
 
3451
4120
  // packages/lint-suite/src/lib/rules/explicit-accessibility/common/explicit-accessibility.const.ts
3452
4121
  var accessibilities = [
@@ -3454,10 +4123,10 @@ var accessibilities = [
3454
4123
  "private",
3455
4124
  "protected"
3456
4125
  ];
3457
- var docs2 = {
4126
+ var docs3 = {
3458
4127
  description: "Require explicit accessibility modifiers on class members"
3459
4128
  };
3460
- var messages2 = {
4129
+ var messages3 = {
3461
4130
  missingAccessibility: "Class member '{{ name }}' is missing an explicit accessibility modifier (public/private/protected).",
3462
4131
  setAccessibility: "Add the '{{ accessibility }}' modifier."
3463
4132
  };
@@ -3466,27 +4135,27 @@ var defaultAccessibilitySchema = {
3466
4135
  enum: ["public", "private", "protected", "none"],
3467
4136
  description: "The accessibility modifier inserted by the auto-fix; constructors always get public. 'none' reports without an auto-fix and offers all three levels as suggestions."
3468
4137
  };
3469
- var properties2 = {
4138
+ var properties3 = {
3470
4139
  defaultAccessibility: defaultAccessibilitySchema
3471
4140
  };
3472
- var optionsSchema2 = {
4141
+ var optionsSchema3 = {
3473
4142
  type: "object",
3474
- properties: properties2,
4143
+ properties: properties3,
3475
4144
  additionalProperties: false
3476
4145
  };
3477
- var schema2 = [optionsSchema2];
3478
- var meta2 = {
4146
+ var schema3 = [optionsSchema3];
4147
+ var meta3 = {
3479
4148
  type: "suggestion",
3480
- docs: docs2,
4149
+ docs: docs3,
3481
4150
  fixable: "code",
3482
4151
  hasSuggestions: true,
3483
- schema: schema2,
3484
- messages: messages2
4152
+ schema: schema3,
4153
+ messages: messages3
3485
4154
  };
3486
- var defaultOptions2 = [{ defaultAccessibility: "public" }];
4155
+ var defaultOptions3 = [{ defaultAccessibility: "public" }];
3487
4156
 
3488
4157
  // packages/lint-suite/src/lib/rules/explicit-accessibility/explicit-accessibility.ts
3489
- var createRule2 = ESLintUtils2.RuleCreator(
4158
+ var createRule3 = ESLintUtils3.RuleCreator(
3490
4159
  () => "https://github.com/F0rty-Tw0/lint-suite#explicit-accessibility"
3491
4160
  );
3492
4161
  var isPrivateMember = (node) => {
@@ -3552,10 +4221,10 @@ var suggestionsOf = (node, fixAccessibility, sourceCode) => {
3552
4221
  };
3553
4222
  return accessibilities.filter(isOtherAccessibility).map(suggestionFor);
3554
4223
  };
3555
- var explicit_accessibility_default = createRule2({
4224
+ var explicit_accessibility_default = createRule3({
3556
4225
  name: "explicit-accessibility",
3557
- meta: meta2,
3558
- defaultOptions: defaultOptions2,
4226
+ meta: meta3,
4227
+ defaultOptions: defaultOptions3,
3559
4228
  create(context, [{ defaultAccessibility = "public" }]) {
3560
4229
  const { sourceCode } = context;
3561
4230
  const check = (node) => {
@@ -3592,20 +4261,20 @@ var explicit_accessibility_default = createRule2({
3592
4261
  });
3593
4262
 
3594
4263
  // packages/lint-suite/src/lib/rules/no-inline-object-types/no-inline-object-types.ts
3595
- import { ESLintUtils as ESLintUtils3, TSESTree as TSESTree11 } from "@typescript-eslint/utils";
3596
- var docs3 = {
4264
+ import { ESLintUtils as ESLintUtils4, TSESTree as TSESTree11 } from "@typescript-eslint/utils";
4265
+ var docs4 = {
3597
4266
  description: "Require nested object types inside a type alias to be extracted to a named type alias"
3598
4267
  };
3599
- var messages3 = {
4268
+ var messages4 = {
3600
4269
  inlineObjectType: "Inline object type must be extracted to a named type alias."
3601
4270
  };
3602
- var meta3 = {
4271
+ var meta4 = {
3603
4272
  type: "suggestion",
3604
- docs: docs3,
4273
+ docs: docs4,
3605
4274
  schema: [],
3606
- messages: messages3
4275
+ messages: messages4
3607
4276
  };
3608
- var createRule3 = ESLintUtils3.RuleCreator(
4277
+ var createRule4 = ESLintUtils4.RuleCreator(
3609
4278
  () => "https://github.com/F0rty-Tw0/lint-suite#no-inline-object-types"
3610
4279
  );
3611
4280
  var enclosingTypeAlias = (node) => {
@@ -3618,9 +4287,9 @@ var enclosingTypeAlias = (node) => {
3618
4287
  }
3619
4288
  return void 0;
3620
4289
  };
3621
- var no_inline_object_types_default = createRule3({
4290
+ var no_inline_object_types_default = createRule4({
3622
4291
  name: "no-inline-object-types",
3623
- meta: meta3,
4292
+ meta: meta4,
3624
4293
  defaultOptions: [],
3625
4294
  create(context) {
3626
4295
  const listeners = {
@@ -3640,46 +4309,138 @@ var no_inline_object_types_default = createRule3({
3640
4309
  }
3641
4310
  });
3642
4311
 
4312
+ // packages/lint-suite/src/lib/rules/one-line-guard/one-line-guard.ts
4313
+ import { ESLintUtils as ESLintUtils5, TSESTree as TSESTree12 } from "@typescript-eslint/utils";
4314
+ var docs5 = {
4315
+ description: "Require a lone return/throw/continue/break guard to drop its braces when the whole if statement fits on one line"
4316
+ };
4317
+ var messages5 = {
4318
+ oneLineGuard: "Lone {{ keyword }} guard fits within {{ max }} columns; write it on one line without braces."
4319
+ };
4320
+ var schema4 = [
4321
+ {
4322
+ type: "object",
4323
+ properties: {
4324
+ maxLineLength: { type: "integer", minimum: 1 }
4325
+ },
4326
+ additionalProperties: false
4327
+ }
4328
+ ];
4329
+ var meta5 = {
4330
+ type: "suggestion",
4331
+ docs: docs5,
4332
+ fixable: "code",
4333
+ schema: schema4,
4334
+ messages: messages5
4335
+ };
4336
+ var createRule5 = ESLintUtils5.RuleCreator(
4337
+ () => "https://github.com/F0rty-Tw0/lint-suite#one-line-guard"
4338
+ );
4339
+ var GUARD_KEYWORDS = /* @__PURE__ */ new Set([
4340
+ TSESTree12.AST_NODE_TYPES.ReturnStatement,
4341
+ TSESTree12.AST_NODE_TYPES.ThrowStatement,
4342
+ TSESTree12.AST_NODE_TYPES.ContinueStatement,
4343
+ TSESTree12.AST_NODE_TYPES.BreakStatement
4344
+ ]);
4345
+ var soleStatement = (body) => {
4346
+ if (body.type !== TSESTree12.AST_NODE_TYPES.BlockStatement) return void 0;
4347
+ if (body.body.length !== 1) return void 0;
4348
+ return body.body[0];
4349
+ };
4350
+ var guardStatement = (node) => {
4351
+ if (node.alternate) return void 0;
4352
+ const statement = soleStatement(node.consequent);
4353
+ if (!statement) return void 0;
4354
+ const isGuardKeyword = GUARD_KEYWORDS.has(statement.type);
4355
+ if (!isGuardKeyword) return void 0;
4356
+ return statement;
4357
+ };
4358
+ var headText = (node, sourceCode) => {
4359
+ return sourceCode.text.slice(node.range[0], node.consequent.range[0]).trimEnd();
4360
+ };
4361
+ var collapsedLine = (node, head, bodyText, sourceCode) => {
4362
+ const line = sourceCode.lines[node.loc.start.line - 1] ?? "";
4363
+ const prefix = line.slice(0, node.loc.start.column);
4364
+ return `${prefix}${head} ${bodyText}`;
4365
+ };
4366
+ var one_line_guard_default = createRule5({
4367
+ name: "one-line-guard",
4368
+ meta: meta5,
4369
+ defaultOptions: [{ maxLineLength: 80 }],
4370
+ create(context, [{ maxLineLength }]) {
4371
+ const { sourceCode } = context;
4372
+ const listeners = {
4373
+ IfStatement(node) {
4374
+ const statement = guardStatement(node);
4375
+ if (!statement) return;
4376
+ const hasComments = sourceCode.getCommentsInside(node.consequent).length > 0;
4377
+ if (hasComments) return;
4378
+ const head = headText(node, sourceCode);
4379
+ const isMultiLineHead = head.includes("\n");
4380
+ if (isMultiLineHead) return;
4381
+ const bodyText = sourceCode.getText(statement);
4382
+ const isMultiLineBody = bodyText.includes("\n");
4383
+ if (isMultiLineBody) return;
4384
+ const collapsed = collapsedLine(node, head, bodyText, sourceCode);
4385
+ if (collapsed.length > maxLineLength) return;
4386
+ const [keywordToken] = sourceCode.getTokens(statement);
4387
+ if (keywordToken === void 0) return;
4388
+ const keyword = keywordToken.value;
4389
+ const data = { keyword, max: maxLineLength };
4390
+ const fix = (fixer) => fixer.replaceText(node.consequent, bodyText);
4391
+ const report = {
4392
+ node,
4393
+ messageId: "oneLineGuard",
4394
+ data,
4395
+ fix
4396
+ };
4397
+ context.report(report);
4398
+ }
4399
+ };
4400
+ return listeners;
4401
+ }
4402
+ });
4403
+
3643
4404
  // packages/lint-suite/src/lib/rules/readonly-type-properties/readonly-type-properties.ts
3644
- import { ESLintUtils as ESLintUtils4, TSESTree as TSESTree12 } from "@typescript-eslint/utils";
3645
- var docs4 = {
4405
+ import { ESLintUtils as ESLintUtils6, TSESTree as TSESTree13 } from "@typescript-eslint/utils";
4406
+ var docs6 = {
3646
4407
  description: "Require readonly on primitive-typed type and interface properties"
3647
4408
  };
3648
- var messages4 = {
4409
+ var messages6 = {
3649
4410
  missingReadonly: "Type property '{{ name }}' should be readonly. Disable this rule on the line if mutation is required."
3650
4411
  };
3651
- var meta4 = {
4412
+ var meta6 = {
3652
4413
  type: "suggestion",
3653
- docs: docs4,
4414
+ docs: docs6,
3654
4415
  fixable: "code",
3655
4416
  schema: [],
3656
- messages: messages4
4417
+ messages: messages6
3657
4418
  };
3658
- var createRule4 = ESLintUtils4.RuleCreator(
4419
+ var createRule6 = ESLintUtils6.RuleCreator(
3659
4420
  () => "https://github.com/F0rty-Tw0/lint-suite#readonly-type-properties"
3660
4421
  );
3661
4422
  var propertyName3 = (node, sourceCode) => {
3662
- if (node.key.type === TSESTree12.AST_NODE_TYPES.Identifier) {
4423
+ if (node.key.type === TSESTree13.AST_NODE_TYPES.Identifier) {
3663
4424
  return node.key.name;
3664
4425
  }
3665
4426
  return sourceCode.getText(node.key);
3666
4427
  };
3667
4428
  var PRIMITIVE_KEYWORDS = /* @__PURE__ */ new Set([
3668
- TSESTree12.AST_NODE_TYPES.TSStringKeyword,
3669
- TSESTree12.AST_NODE_TYPES.TSNumberKeyword,
3670
- TSESTree12.AST_NODE_TYPES.TSBooleanKeyword,
3671
- TSESTree12.AST_NODE_TYPES.TSBigIntKeyword,
3672
- TSESTree12.AST_NODE_TYPES.TSSymbolKeyword,
3673
- TSESTree12.AST_NODE_TYPES.TSNullKeyword,
3674
- TSESTree12.AST_NODE_TYPES.TSUndefinedKeyword
4429
+ TSESTree13.AST_NODE_TYPES.TSStringKeyword,
4430
+ TSESTree13.AST_NODE_TYPES.TSNumberKeyword,
4431
+ TSESTree13.AST_NODE_TYPES.TSBooleanKeyword,
4432
+ TSESTree13.AST_NODE_TYPES.TSBigIntKeyword,
4433
+ TSESTree13.AST_NODE_TYPES.TSSymbolKeyword,
4434
+ TSESTree13.AST_NODE_TYPES.TSNullKeyword,
4435
+ TSESTree13.AST_NODE_TYPES.TSUndefinedKeyword
3675
4436
  ]);
3676
4437
  var isPrimitive = (type) => {
3677
4438
  const isPrimitiveKeyword = PRIMITIVE_KEYWORDS.has(type.type);
3678
4439
  if (isPrimitiveKeyword) return true;
3679
- if (type.type === TSESTree12.AST_NODE_TYPES.TSLiteralType || type.type === TSESTree12.AST_NODE_TYPES.TSTemplateLiteralType) {
4440
+ if (type.type === TSESTree13.AST_NODE_TYPES.TSLiteralType || type.type === TSESTree13.AST_NODE_TYPES.TSTemplateLiteralType) {
3680
4441
  return true;
3681
4442
  }
3682
- if (type.type === TSESTree12.AST_NODE_TYPES.TSUnionType || type.type === TSESTree12.AST_NODE_TYPES.TSIntersectionType) {
4443
+ if (type.type === TSESTree13.AST_NODE_TYPES.TSUnionType || type.type === TSESTree13.AST_NODE_TYPES.TSIntersectionType) {
3683
4444
  return type.types.every(isPrimitive);
3684
4445
  }
3685
4446
  return false;
@@ -3691,9 +4452,9 @@ var readonlyFix = (node, sourceCode) => {
3691
4452
  return fixer.insertTextBefore(firstToken, "readonly ");
3692
4453
  };
3693
4454
  };
3694
- var readonly_type_properties_default = createRule4({
4455
+ var readonly_type_properties_default = createRule6({
3695
4456
  name: "readonly-type-properties",
3696
- meta: meta4,
4457
+ meta: meta6,
3697
4458
  defaultOptions: [],
3698
4459
  create(context) {
3699
4460
  const { sourceCode } = context;
@@ -3722,7 +4483,8 @@ var readonly_type_properties_default = createRule4({
3722
4483
  var localPlugin = definePlugin("local", {
3723
4484
  "explicit-accessibility": explicit_accessibility_default,
3724
4485
  "readonly-type-properties": readonly_type_properties_default,
3725
- "no-inline-object-types": no_inline_object_types_default
4486
+ "no-inline-object-types": no_inline_object_types_default,
4487
+ "one-line-guard": one_line_guard_default
3726
4488
  });
3727
4489
 
3728
4490
  // packages/lint-suite/src/lib/typescript-safety.ts
@@ -3734,6 +4496,7 @@ var typescriptSafety = defineConfig18([
3734
4496
  "local/explicit-accessibility": "error",
3735
4497
  "local/readonly-type-properties": "error",
3736
4498
  "local/no-inline-object-types": "error",
4499
+ "local/one-line-guard": ["error", { maxLineLength: MAX_LINE_LENGTH }],
3737
4500
  "@typescript-eslint/explicit-function-return-type": "error",
3738
4501
  "@typescript-eslint/no-empty-function": "error",
3739
4502
  "@typescript-eslint/no-unused-vars": "error",