lint-suite 2.0.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +18 -4
  2. package/eslint.js +204 -81
  3. package/eslint.js.map +4 -4
  4. package/lib/rules/file-cache.d.ts +1 -1
  5. package/lib/rules/file-cache.d.ts.map +1 -1
  6. package/lib/rules/no-unstyled-classes/styles/stylesheet-classes.d.ts.map +1 -1
  7. package/lib/rules/no-unstyled-classes/styles/stylesheet-collection.d.ts +1 -1
  8. package/lib/rules/no-unstyled-classes/styles/stylesheet-collection.d.ts.map +1 -1
  9. package/lib/rules/no-unstyled-classes/styles/stylesheet-imports.d.ts +8 -1
  10. package/lib/rules/no-unstyled-classes/styles/stylesheet-imports.d.ts.map +1 -1
  11. package/lib/rules/no-unused-angular-instance-fields/project-usage/angular/angular-template-reads.d.ts.map +1 -1
  12. package/lib/rules/no-unused-angular-instance-fields/project-usage/common/project-index.type.d.ts +1 -0
  13. package/lib/rules/no-unused-angular-instance-fields/project-usage/common/project-index.type.d.ts.map +1 -1
  14. package/lib/rules/no-unused-angular-instance-fields/project-usage/project-file-entry.d.ts.map +1 -1
  15. package/lib/rules/no-unused-angular-instance-fields/project-usage/project-index-reconciliation.d.ts.map +1 -1
  16. package/lib/rules/no-unused-angular-instance-fields/project-usage/typescript/typescript-dangling-imports.d.ts +8 -0
  17. package/lib/rules/no-unused-angular-instance-fields/project-usage/typescript/typescript-dangling-imports.d.ts.map +1 -0
  18. package/lib/rules/no-unused-exports/common/no-unused-exports.type.d.ts +9 -1
  19. package/lib/rules/no-unused-exports/common/no-unused-exports.type.d.ts.map +1 -1
  20. package/lib/rules/no-unused-exports/disk-resolver.d.ts +9 -0
  21. package/lib/rules/no-unused-exports/disk-resolver.d.ts.map +1 -0
  22. package/lib/rules/no-unused-exports/export-index.d.ts.map +1 -1
  23. package/lib/rules/no-unused-exports/utils/module-edges.util.d.ts +3 -3
  24. package/lib/rules/no-unused-exports/utils/module-edges.util.d.ts.map +1 -1
  25. package/lib/rules/no-unused-exports/utils/module-resolver.util.d.ts +8 -0
  26. package/lib/rules/no-unused-exports/utils/module-resolver.util.d.ts.map +1 -0
  27. package/lib/rules/package-version.d.ts +2 -0
  28. package/lib/rules/package-version.d.ts.map +1 -0
  29. package/package.json +4 -7
  30. package/stylelint.js +65 -18
  31. package/stylelint.js.map +4 -4
  32. package/eslint.cjs +0 -7376
  33. package/eslint.cjs.map +0 -7
  34. package/lib/rules/no-unused-exports/utils/module-target.util.d.ts +0 -4
  35. package/lib/rules/no-unused-exports/utils/module-target.util.d.ts.map +0 -1
  36. package/prettier.cjs +0 -50
  37. package/prettier.cjs.map +0 -7
  38. package/stylelint.cjs +0 -968
  39. package/stylelint.cjs.map +0 -7
package/stylelint.cjs DELETED
@@ -1,968 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // packages/lint-suite/src/stylelint.ts
31
- var stylelint_exports = {};
32
- __export(stylelint_exports, {
33
- stylelint: () => stylelint2
34
- });
35
- module.exports = __toCommonJS(stylelint_exports);
36
- var import_stylelint_scss = __toESM(require("stylelint-scss"), 1);
37
- var import_stylelint_selector_bem_pattern = __toESM(require("stylelint-selector-bem-pattern"), 1);
38
-
39
- // packages/lint-suite/src/lib/rules/no-unused-classes/no-unused-classes.ts
40
- var import_stylelint = __toESM(require("stylelint"), 1);
41
-
42
- // packages/lint-suite/src/lib/rules/no-unused-classes/styles/stylesheet-components.ts
43
- var import_node_fs3 = require("node:fs");
44
- var import_node_path3 = require("node:path");
45
-
46
- // packages/lint-suite/src/lib/rules/no-unused-classes/styles/linked-templates.ts
47
- var import_node_fs2 = require("node:fs");
48
- var import_node_path2 = require("node:path");
49
-
50
- // packages/lint-suite/src/lib/rules/file-cache.ts
51
- var import_node_fs = require("node:fs");
52
- var import_node_path = require("node:path");
53
- var CACHE_FORMAT_VERSION = 1;
54
- var caches = /* @__PURE__ */ new Set();
55
- var isFlushRegistered = false;
56
- var cacheDirectory = () => {
57
- const { LINT_SUITE_CACHE, LINT_SUITE_CACHE_DIR } = process.env;
58
- const isDisabled = LINT_SUITE_CACHE === "0";
59
- if (isDisabled) return null;
60
- if (LINT_SUITE_CACHE_DIR) return LINT_SUITE_CACHE_DIR;
61
- return (0, import_node_path.join)(process.cwd(), "node_modules", ".cache", "lint-suite");
62
- };
63
- var cacheFile = (name) => {
64
- const directory = cacheDirectory();
65
- if (directory === null) return null;
66
- return (0, import_node_path.join)(directory, `${name}.v${CACHE_FORMAT_VERSION}.json`);
67
- };
68
- var isCachedFile = (value) => {
69
- const isObject = typeof value === "object" && value !== null;
70
- if (!isObject) return false;
71
- const hasVersion = "version" in value && typeof value.version === "string";
72
- return hasVersion && "value" in value;
73
- };
74
- var storedEntries = (text) => {
75
- const entries = /* @__PURE__ */ new Map();
76
- const parsed = JSON.parse(text);
77
- const isRecord = typeof parsed === "object" && parsed !== null;
78
- if (!isRecord) return entries;
79
- for (const [path, entry] of Object.entries(parsed)) {
80
- if (isCachedFile(entry)) entries.set(path, entry);
81
- }
82
- return entries;
83
- };
84
- var load = (cache2) => {
85
- cache2.loaded = true;
86
- const file = cacheFile(cache2.name);
87
- if (file === null) return;
88
- try {
89
- const stored = storedEntries((0, import_node_fs.readFileSync)(file, "utf8"));
90
- for (const [path, entry] of stored) cache2.entries.set(path, entry);
91
- } catch {
92
- return;
93
- }
94
- };
95
- var write = (cache2) => {
96
- const file = cacheFile(cache2.name);
97
- if (file === null) return;
98
- try {
99
- (0, import_node_fs.mkdirSync)((0, import_node_path.dirname)(file), { recursive: true });
100
- const temporary = `${file}.${process.pid}.tmp`;
101
- const stored = Object.fromEntries(cache2.entries);
102
- (0, import_node_fs.writeFileSync)(temporary, JSON.stringify(stored));
103
- (0, import_node_fs.renameSync)(temporary, file);
104
- } catch {
105
- return;
106
- }
107
- };
108
- var flushFileCaches = () => {
109
- for (const cache2 of caches) {
110
- if (!cache2.dirty) continue;
111
- write(cache2);
112
- cache2.dirty = false;
113
- }
114
- };
115
- var registerFlush = () => {
116
- if (isFlushRegistered) return;
117
- isFlushRegistered = true;
118
- process.once("exit", flushFileCaches);
119
- };
120
- var createFileCache = (name) => {
121
- const cache2 = {
122
- name,
123
- entries: /* @__PURE__ */ new Map(),
124
- loaded: false,
125
- dirty: false
126
- };
127
- caches.add(cache2);
128
- registerFlush();
129
- return cache2;
130
- };
131
- var readCached = (cache2, path, parse) => {
132
- if (!cache2.loaded) load(cache2);
133
- try {
134
- const stats = (0, import_node_fs.statSync)(path, { bigint: true });
135
- const version = `${stats.mtimeNs}:${stats.size}`;
136
- const cached = cache2.entries.get(path);
137
- if (cached?.version === version) return cached.value;
138
- const value = parse((0, import_node_fs.readFileSync)(path, "utf8"), path);
139
- const fresh = { value, version };
140
- cache2.entries.set(path, fresh);
141
- cache2.dirty = true;
142
- return value;
143
- } catch {
144
- return null;
145
- }
146
- };
147
-
148
- // packages/lint-suite/src/lib/rules/utils/template-links.util.ts
149
- var LINK_TAG = /<link\b[^>]*>/giu;
150
- var STYLESHEET_REL = /\brel\s*=\s*["']stylesheet["']/iu;
151
- var HREF = /\bhref\s*=\s*["']([^"']*)["']/iu;
152
- var UNRESOLVABLE = /^(?:\/|[^:/?#]+:)/u;
153
- var hrefOf = (tag) => {
154
- const isStylesheet = STYLESHEET_REL.test(tag);
155
- if (!isStylesheet) return null;
156
- const href = HREF.exec(tag)?.[1] ?? "";
157
- const isUnresolvable = UNRESOLVABLE.test(href);
158
- const isLocal = href.length > 0 && !isUnresolvable;
159
- return isLocal ? href : null;
160
- };
161
- var linkedStylesheetHrefs = (template) => {
162
- const tags = template.match(LINK_TAG) ?? [];
163
- return tags.map(hrefOf).filter((href) => href !== null);
164
- };
165
-
166
- // packages/lint-suite/src/lib/rules/no-unused-classes/styles/linked-templates.ts
167
- var TEMPLATE_EXTENSION = /\.html$/iu;
168
- var SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set(["node_modules", "dist", "coverage"]);
169
- var links = createFileCache("template-links");
170
- var linkIndex = null;
171
- var templateLinks = (templatePath) => {
172
- return readCached(links, templatePath, linkedStylesheetHrefs) ?? [];
173
- };
174
- var isWalkable = (name) => {
175
- const isDotfile = name.startsWith(".");
176
- if (isDotfile) return false;
177
- return !SKIPPED_DIRECTORIES.has(name);
178
- };
179
- var walkTemplates = (root) => {
180
- const found = [];
181
- const pending = [root];
182
- while (pending.length > 0) {
183
- const directory = pending.pop();
184
- if (directory === void 0) break;
185
- for (const entry of (0, import_node_fs2.readdirSync)(directory, { withFileTypes: true })) {
186
- const path = (0, import_node_path2.join)(directory, entry.name);
187
- const isDirectory = entry.isDirectory();
188
- if (isDirectory) {
189
- const canWalk = isWalkable(entry.name);
190
- if (canWalk) pending.push(path);
191
- continue;
192
- }
193
- const isTemplate = TEMPLATE_EXTENSION.test(entry.name);
194
- if (isTemplate) found.push(path);
195
- }
196
- }
197
- return found;
198
- };
199
- var templatesUnder = (root) => {
200
- try {
201
- return walkTemplates(root);
202
- } catch {
203
- return [];
204
- }
205
- };
206
- var templatesByStylesheet = (root) => {
207
- const byStylesheet = /* @__PURE__ */ new Map();
208
- for (const template of templatesUnder(root)) {
209
- const directory = (0, import_node_path2.dirname)(template);
210
- for (const href of templateLinks(template)) {
211
- const stylesheet = (0, import_node_path2.resolve)(directory, href);
212
- const linked = byStylesheet.get(stylesheet) ?? [];
213
- linked.push(template);
214
- byStylesheet.set(stylesheet, linked);
215
- }
216
- }
217
- return byStylesheet;
218
- };
219
- var currentLinkIndex = () => {
220
- const now = performance.now();
221
- const cached = linkIndex;
222
- const isFresh = cached !== null && now - cached.builtAt < cached.buildDuration * 100;
223
- if (isFresh) return cached;
224
- const templates2 = templatesByStylesheet(process.cwd());
225
- const fresh = {
226
- builtAt: now,
227
- buildDuration: performance.now() - now,
228
- templates: templates2
229
- };
230
- linkIndex = fresh;
231
- return fresh;
232
- };
233
- var linkedTemplates = (stylesheetPath) => {
234
- return currentLinkIndex().templates.get(stylesheetPath) ?? [];
235
- };
236
-
237
- // packages/lint-suite/src/lib/rules/component-metadata.ts
238
- var import_typescript = require("typescript");
239
- var COMPONENT_MARKER = "@Component";
240
- var cache = createFileCache("component-metadata");
241
- var componentArgument = (decorator) => {
242
- const { expression } = decorator;
243
- if (!(0, import_typescript.isCallExpression)(expression)) return null;
244
- if (!(0, import_typescript.isIdentifier)(expression.expression)) return null;
245
- const isComponent = expression.expression.text === "Component";
246
- if (!isComponent) return null;
247
- const [argument] = expression.arguments;
248
- if (argument === void 0) return null;
249
- if (!(0, import_typescript.isObjectLiteralExpression)(argument)) return null;
250
- return argument;
251
- };
252
- var decoratedMetadata = (node) => {
253
- if (!(0, import_typescript.canHaveDecorators)(node)) return null;
254
- const decorators = (0, import_typescript.getDecorators)(node) ?? [];
255
- for (const decorator of decorators) {
256
- const metadata = componentArgument(decorator);
257
- if (metadata !== null) return metadata;
258
- }
259
- return null;
260
- };
261
- var literalText = (node) => {
262
- if (!(0, import_typescript.isStringLiteralLike)(node)) return null;
263
- return node.text;
264
- };
265
- var literalTexts = (node) => {
266
- const single = literalText(node);
267
- if (single !== null) return [single];
268
- if (!(0, import_typescript.isArrayLiteralExpression)(node)) return [];
269
- const texts = [];
270
- for (const element of node.elements) {
271
- const text = literalText(element);
272
- if (text !== null) texts.push(text);
273
- }
274
- return texts;
275
- };
276
- var metadataValue = (metadata, name) => {
277
- for (const property of metadata.properties) {
278
- if (!(0, import_typescript.isPropertyAssignment)(property)) continue;
279
- if (!(0, import_typescript.isIdentifier)(property.name)) continue;
280
- const isMatch = property.name.text === name;
281
- if (isMatch) return property.initializer;
282
- }
283
- return null;
284
- };
285
- var metadataTexts = (metadata, name) => {
286
- const value = metadataValue(metadata, name);
287
- if (value === null) return [];
288
- return literalTexts(value);
289
- };
290
- var toDescriptor = (metadata) => {
291
- const [templateUrl] = metadataTexts(metadata, "templateUrl");
292
- const [template] = metadataTexts(metadata, "template");
293
- const styleUrl = metadataTexts(metadata, "styleUrl");
294
- const listedStyleUrls = metadataTexts(metadata, "styleUrls");
295
- const styleUrls = [...styleUrl, ...listedStyleUrls];
296
- const styles = metadataTexts(metadata, "styles");
297
- const descriptor = {
298
- templateUrl: templateUrl ?? null,
299
- template: template ?? null,
300
- styleUrls,
301
- styles
302
- };
303
- return descriptor;
304
- };
305
- var parseComponentMetadata = (text, path) => {
306
- const found = [];
307
- const hasComponent = text.includes(COMPONENT_MARKER);
308
- if (!hasComponent) return found;
309
- const visit = (node) => {
310
- const metadata = decoratedMetadata(node);
311
- if (metadata !== null) found.push(toDescriptor(metadata));
312
- (0, import_typescript.forEachChild)(node, visit);
313
- };
314
- const source = (0, import_typescript.createSourceFile)(path, text, import_typescript.ScriptTarget.Latest, true);
315
- (0, import_typescript.forEachChild)(source, visit);
316
- return found;
317
- };
318
- var componentMetadata = (path) => {
319
- return readCached(cache, path, parseComponentMetadata) ?? [];
320
- };
321
-
322
- // packages/lint-suite/src/lib/rules/no-unused-classes/styles/stylesheet-components.ts
323
- var MODULE_EXTENSION = /\.ts$/iu;
324
- var STYLE_EXTENSION = /\.(?:scss|sass|css)$/iu;
325
- var UNKNOWN_TEMPLATE = { kind: "unknown" };
326
- var listings = /* @__PURE__ */ new Map();
327
- var directoryListing = (directory) => {
328
- const stats = (0, import_node_fs3.statSync)(directory, { bigint: true });
329
- const version = `${stats.mtimeNs}`;
330
- const cached = listings.get(directory);
331
- if (cached?.version === version) return cached.files;
332
- const files = (0, import_node_fs3.readdirSync)(directory);
333
- const fresh = { files, version };
334
- listings.set(directory, fresh);
335
- return files;
336
- };
337
- var declaredStylesheets = (descriptor, directory) => {
338
- const resolveUrl = (url) => (0, import_node_path3.resolve)(directory, url);
339
- return descriptor.styleUrls.map(resolveUrl);
340
- };
341
- var fileTemplate = (descriptor, directory) => {
342
- if (descriptor.templateUrl === null) return null;
343
- const path = (0, import_node_path3.resolve)(directory, descriptor.templateUrl);
344
- const isPresent = (0, import_node_fs3.existsSync)(path);
345
- if (!isPresent) return null;
346
- const source = { kind: "file", path };
347
- return source;
348
- };
349
- var inlineTemplate = (descriptor, componentPath) => {
350
- if (descriptor.template === null) return null;
351
- const source = {
352
- kind: "inline",
353
- source: descriptor.template,
354
- path: componentPath
355
- };
356
- return source;
357
- };
358
- var componentTemplate = (descriptor, componentPath) => {
359
- const directory = (0, import_node_path3.dirname)(componentPath);
360
- const file = fileTemplate(descriptor, directory);
361
- if (file !== null) return file;
362
- const inline = inlineTemplate(descriptor, componentPath);
363
- return inline ?? UNKNOWN_TEMPLATE;
364
- };
365
- var matchedTemplates = (componentPath, stylesheetPath) => {
366
- const directory = (0, import_node_path3.dirname)(componentPath);
367
- const sources = [];
368
- for (const descriptor of componentMetadata(componentPath)) {
369
- const declared = declaredStylesheets(descriptor, directory);
370
- const isMatch = declared.includes(stylesheetPath);
371
- if (!isMatch) continue;
372
- sources.push(componentTemplate(descriptor, componentPath));
373
- }
374
- return sources;
375
- };
376
- var directoryFiles = (directory, extension) => {
377
- try {
378
- return directoryListing(directory).filter((file) => extension.test(file));
379
- } catch {
380
- return [];
381
- }
382
- };
383
- var fallbackTemplates = (stylesheetPath) => {
384
- const sibling = stylesheetPath.replace(STYLE_EXTENSION, ".html");
385
- const paths = /* @__PURE__ */ new Set();
386
- const hasSibling = (0, import_node_fs3.existsSync)(sibling);
387
- if (hasSibling) paths.add(sibling);
388
- for (const path of linkedTemplates(stylesheetPath)) paths.add(path);
389
- const toSource = (path) => {
390
- const source = { kind: "file", path };
391
- return source;
392
- };
393
- const pathList = [...paths];
394
- return pathList.map(toSource);
395
- };
396
- var stylesheetTemplates = (stylesheetPath) => {
397
- const resolved = (0, import_node_path3.resolve)(stylesheetPath);
398
- const directory = (0, import_node_path3.dirname)(resolved);
399
- const sources = [];
400
- for (const file of directoryFiles(directory, MODULE_EXTENSION)) {
401
- const componentPath = (0, import_node_path3.join)(directory, file);
402
- const matched = matchedTemplates(componentPath, resolved);
403
- sources.push(...matched);
404
- }
405
- if (sources.length > 0) return sources;
406
- return fallbackTemplates(resolved);
407
- };
408
-
409
- // packages/lint-suite/src/lib/rules/no-unused-classes/template/template-usage.ts
410
- var import_compiler3 = require("@angular/compiler");
411
-
412
- // packages/lint-suite/src/lib/rules/selector-classes.ts
413
- var import_postcss_selector_parser = __toESM(require("postcss-selector-parser"), 1);
414
- var INTERPOLATION_TOKEN = "zzinterpzz";
415
- var PARENT_TOKEN = "zzparentzz";
416
- var UNKNOWN_PARENT_SELECTOR = `.${PARENT_TOKEN}`;
417
- var UNKNOWN_PARTS = new RegExp(
418
- `${INTERPOLATION_TOKEN}|${PARENT_TOKEN}`,
419
- "gu"
420
- );
421
- var INTERPOLATION = /#\{[^}]*\}/gu;
422
- var DEEP_COMBINATORS = /* @__PURE__ */ new Set(["/deep/", ">>>"]);
423
- var HOST_PSEUDOS = /* @__PURE__ */ new Set([":host", ":host-context"]);
424
- var NG_DEEP_PSEUDO = "::ng-deep";
425
- var REGEXP_META = /[.*+?^${}()|[\]\\]/gu;
426
- var escapeRegExp = (part) => {
427
- return part.replaceAll(REGEXP_META, "\\$&");
428
- };
429
- var classNamePattern = (value) => {
430
- const literals = value.split(UNKNOWN_PARTS).map(escapeRegExp);
431
- const joined = literals.join(".*");
432
- return `^${joined}$`;
433
- };
434
- var withoutParent = (selector) => {
435
- return selector.replaceAll("&", UNKNOWN_PARENT_SELECTOR);
436
- };
437
- var withParent = (selector, parent) => {
438
- const hasNesting = selector.includes("&");
439
- if (hasNesting) return selector.replaceAll("&", parent);
440
- return `${parent} ${selector}`;
441
- };
442
- var resolveSelectors = (selectors, parents) => {
443
- const hasParents = parents.length > 0;
444
- if (!hasParents) return selectors.map(withoutParent);
445
- const resolved = [];
446
- for (const parent of parents) {
447
- for (const selector of selectors) {
448
- resolved.push(withParent(selector, parent));
449
- }
450
- }
451
- return resolved;
452
- };
453
- var isBoundaryNode = (node) => {
454
- if (node.type === "combinator") return DEEP_COMBINATORS.has(node.value);
455
- if (node.type !== "pseudo") return false;
456
- return node.value === NG_DEEP_PSEUDO;
457
- };
458
- var addTemplateClass = (value, names) => {
459
- const hasInterpolation = value.includes(INTERPOLATION_TOKEN);
460
- const hasUnknownParent = value.includes(PARENT_TOKEN);
461
- const isDynamic = hasInterpolation || hasUnknownParent;
462
- if (isDynamic) return;
463
- names.push(value);
464
- };
465
- var collectTemplateClasses = (nodes, names) => {
466
- for (const node of nodes) {
467
- const isBoundary = isBoundaryNode(node);
468
- if (isBoundary) return true;
469
- if (node.type === "class") {
470
- addTemplateClass(node.value, names);
471
- continue;
472
- }
473
- if (node.type !== "pseudo") continue;
474
- const isHost = HOST_PSEUDOS.has(node.value);
475
- if (isHost) continue;
476
- for (const argument of node.nodes) {
477
- const isStopped = collectTemplateClasses(argument.nodes, names);
478
- if (isStopped) return true;
479
- }
480
- }
481
- return false;
482
- };
483
- var selectorTemplateClasses = (selector) => {
484
- const names = [];
485
- const normalized = selector.replaceAll(INTERPOLATION, INTERPOLATION_TOKEN);
486
- try {
487
- const root = (0, import_postcss_selector_parser.default)().astSync(normalized);
488
- for (const each of root.nodes) collectTemplateClasses(each.nodes, names);
489
- } catch {
490
- return [];
491
- }
492
- const uniqueNames = new Set(names);
493
- return [...uniqueNames];
494
- };
495
- var classMatcher = (exact, patterns) => {
496
- const matches = (name) => {
497
- const isExact = exact.has(name);
498
- if (isExact) return true;
499
- return patterns.some((pattern) => pattern.test(name));
500
- };
501
- return matches;
502
- };
503
-
504
- // packages/lint-suite/src/lib/rules/utils/class-expression-literals.util.ts
505
- var import_compiler = require("@angular/compiler");
506
- var WHITESPACE = /\s+/u;
507
- var EXPRESSION_FILE = "class-expression";
508
- var INTERPOLATION_TOKEN2 = "zzinterpzz";
509
- var parser = new import_compiler.Parser(new import_compiler.Lexer());
510
- var spanOf = (source) => {
511
- const file = new import_compiler.ParseSourceFile(source, EXPRESSION_FILE);
512
- const start = new import_compiler.ParseLocation(file, 0, 0, 0);
513
- const span = new import_compiler.ParseSourceSpan(start, start.moveBy(source.length));
514
- return span;
515
- };
516
- var astOf = (parsed) => {
517
- const hasErrors = parsed.errors.length > 0;
518
- if (hasErrors) return null;
519
- return parsed.ast;
520
- };
521
- var parseClassExpression = (source) => {
522
- try {
523
- const span = spanOf(source);
524
- const interpolation = parser.parseInterpolation(source, span, 0, null);
525
- if (interpolation) return astOf(interpolation);
526
- const binding = parser.parseBinding(source, span, 0);
527
- return astOf(binding);
528
- } catch {
529
- return null;
530
- }
531
- };
532
- var addNames = (value, names) => {
533
- for (const token of value.split(WHITESPACE)) {
534
- if (token) names.push(token);
535
- }
536
- };
537
- var addPrimitive = (ast, names) => {
538
- if (typeof ast.value === "string") addNames(ast.value, names);
539
- };
540
- var addMapKeys = (ast, names) => {
541
- for (const key of ast.keys) {
542
- if (key.kind !== "spread") addNames(key.key, names);
543
- }
544
- };
545
- var addInterpolation = (ast, names) => {
546
- for (const text of ast.strings) addNames(text, names);
547
- };
548
- var collect = (ast, names) => {
549
- if (ast instanceof import_compiler.LiteralPrimitive) {
550
- addPrimitive(ast, names);
551
- return;
552
- }
553
- if (ast instanceof import_compiler.LiteralMap) {
554
- addMapKeys(ast, names);
555
- return;
556
- }
557
- if (ast instanceof import_compiler.Interpolation) {
558
- addInterpolation(ast, names);
559
- return;
560
- }
561
- if (ast instanceof import_compiler.LiteralArray) {
562
- for (const expression of ast.expressions) collect(expression, names);
563
- return;
564
- }
565
- if (ast instanceof import_compiler.Conditional) {
566
- collect(ast.trueExp, names);
567
- collect(ast.falseExp, names);
568
- }
569
- };
570
- var classExpressionLiterals = (source) => {
571
- const ast = parseClassExpression(source);
572
- if (ast === null) return [];
573
- const names = [];
574
- collect(ast, names);
575
- const uniqueNames = new Set(names);
576
- return [...uniqueNames];
577
- };
578
- var isSpreadKey = (key) => key.kind === "spread";
579
- var isDynamicAst = (ast) => {
580
- if (ast instanceof import_compiler.LiteralPrimitive) return false;
581
- if (ast instanceof import_compiler.LiteralMap) return ast.keys.some(isSpreadKey);
582
- if (ast instanceof import_compiler.LiteralArray) return ast.expressions.some(isDynamicAst);
583
- if (ast instanceof import_compiler.Conditional) {
584
- const isTrueDynamic = isDynamicAst(ast.trueExp);
585
- const isFalseDynamic = isDynamicAst(ast.falseExp);
586
- return isTrueDynamic || isFalseDynamic;
587
- }
588
- return true;
589
- };
590
- var isNamedToken = (token) => token !== INTERPOLATION_TOKEN2;
591
- var isPatternToken = (token) => {
592
- return token.includes(INTERPOLATION_TOKEN2);
593
- };
594
- var isPlainToken = (token) => !isPatternToken(token);
595
- var interpolationUsage = (ast) => {
596
- const joined = ast.strings.join(INTERPOLATION_TOKEN2);
597
- const tokens = joined.split(WHITESPACE).filter(Boolean);
598
- const named = tokens.filter(isNamedToken);
599
- const patterns = named.filter(isPatternToken).map(classNamePattern);
600
- const names = named.filter(isPlainToken);
601
- const uniqueNames = new Set(names);
602
- const uniquePatterns = new Set(patterns);
603
- const usage = {
604
- names: [...uniqueNames],
605
- patterns: [...uniquePatterns],
606
- isDynamic: named.length < tokens.length
607
- };
608
- return usage;
609
- };
610
- var UNKNOWN_USAGE = {
611
- names: [],
612
- patterns: [],
613
- isDynamic: true
614
- };
615
- var classExpressionUsage = (source) => {
616
- const ast = parseClassExpression(source);
617
- if (ast === null) return UNKNOWN_USAGE;
618
- if (ast instanceof import_compiler.Interpolation) return interpolationUsage(ast);
619
- const names = [];
620
- collect(ast, names);
621
- const isDynamic = isDynamicAst(ast);
622
- const uniqueNames = new Set(names);
623
- const usage = {
624
- names: [...uniqueNames],
625
- patterns: [],
626
- isDynamic
627
- };
628
- return usage;
629
- };
630
-
631
- // packages/lint-suite/src/lib/rules/utils/template-classes.util.ts
632
- var import_compiler2 = require("@angular/compiler");
633
- var CLASS_ATTRIBUTES = [
634
- "class",
635
- "routerLinkActive",
636
- "animate.enter",
637
- "animate.leave"
638
- ];
639
- var CLASS_BINDING_PREFIX = "class.";
640
- var TOKEN = /\S+/gu;
641
- var expressionSource = (value) => {
642
- if (!("source" in value)) return null;
643
- const { source } = value;
644
- if (typeof source !== "string") return null;
645
- return source;
646
- };
647
- var staticClasses = (attribute) => {
648
- const classes = [];
649
- const valueSpan = attribute.valueSpan ?? attribute.sourceSpan;
650
- for (const token of attribute.value.matchAll(TOKEN)) {
651
- const start = valueSpan.start.moveBy(token.index);
652
- const end = valueSpan.start.moveBy(token.index + token[0].length);
653
- const span = new import_compiler2.ParseSourceSpan(start, end);
654
- const templateClass = { name: token[0], span };
655
- classes.push(templateClass);
656
- }
657
- return classes;
658
- };
659
- var boundClassName = (input) => {
660
- const { details } = input.keySpan;
661
- if (details === null) return null;
662
- const isClassBinding = details.startsWith(CLASS_BINDING_PREFIX);
663
- if (!isClassBinding) return null;
664
- return input.name;
665
- };
666
- var isClassExpression = (input) => {
667
- const isClassName = CLASS_ATTRIBUTES.includes(input.name);
668
- if (!isClassName) return false;
669
- const { details } = input.keySpan;
670
- if (details === null) return true;
671
- return details === input.name;
672
- };
673
- var expressionClasses = (input) => {
674
- const source = expressionSource(input.value);
675
- if (source === null) return [];
676
- const names = classExpressionLiterals(source);
677
- const templateClassOf = (name) => {
678
- const templateClass = { name, span: input.sourceSpan };
679
- return templateClass;
680
- };
681
- return names.map(templateClassOf);
682
- };
683
- var inputClasses = (input) => {
684
- const bound = boundClassName(input);
685
- if (bound !== null) {
686
- const templateClass = { name: bound, span: input.keySpan };
687
- return [templateClass];
688
- }
689
- const isExpression = isClassExpression(input);
690
- if (!isExpression) return [];
691
- return expressionClasses(input);
692
- };
693
- var templateClasses = (node) => {
694
- const classes = [];
695
- for (const attribute of node.attributes) {
696
- const isClassName = CLASS_ATTRIBUTES.includes(attribute.name);
697
- if (isClassName) {
698
- const found = staticClasses(attribute);
699
- classes.push(...found);
700
- }
701
- }
702
- for (const input of node.inputs) {
703
- const found = inputClasses(input);
704
- classes.push(...found);
705
- }
706
- return classes;
707
- };
708
-
709
- // packages/lint-suite/src/lib/rules/utils/to-regexp.util.ts
710
- var toRegExp = (pattern) => new RegExp(pattern, "u");
711
-
712
- // packages/lint-suite/src/lib/rules/no-unused-classes/template/template-usage.ts
713
- var NG_CLASS_ATTRIBUTE = "ngClass";
714
- var matchesNone = () => false;
715
- var UNKNOWN_USAGE2 = {
716
- has: matchesNone,
717
- isDynamic: true,
718
- size: 0
719
- };
720
- var templates = createFileCache("template-usage");
721
- var expressionSource2 = (value) => {
722
- const isWithSource = value instanceof import_compiler3.ASTWithSource;
723
- if (!isWithSource) return null;
724
- return value.source;
725
- };
726
- var isClassInput = (input) => {
727
- const isNgClass = input.name === NG_CLASS_ATTRIBUTE;
728
- if (isNgClass) return true;
729
- return isClassExpression(input);
730
- };
731
- var ClassUsageVisitor = class extends import_compiler3.TmplAstRecursiveVisitor {
732
- names = /* @__PURE__ */ new Set();
733
- patterns = /* @__PURE__ */ new Set();
734
- isDynamic = false;
735
- visitElement(element) {
736
- this.collect(element);
737
- super.visitElement(element);
738
- }
739
- visitTemplate(template) {
740
- this.collect(template);
741
- super.visitTemplate(template);
742
- }
743
- visitComponent(component) {
744
- this.collect(component);
745
- super.visitComponent(component);
746
- }
747
- collect(node) {
748
- for (const { name } of templateClasses(node)) this.names.add(name);
749
- for (const input of node.inputs) this.collectInput(input);
750
- }
751
- collectInput(input) {
752
- const isClass = isClassInput(input);
753
- if (!isClass) return;
754
- const source = expressionSource2(input.value);
755
- if (source === null) {
756
- this.isDynamic = true;
757
- return;
758
- }
759
- const usage = classExpressionUsage(source);
760
- for (const name of usage.names) this.names.add(name);
761
- for (const pattern of usage.patterns) this.patterns.add(pattern);
762
- if (usage.isDynamic) this.isDynamic = true;
763
- }
764
- };
765
- var parseUsage = (text, path) => {
766
- const parsed = (0, import_compiler3.parseTemplate)(text, path);
767
- if (parsed.errors !== null) return null;
768
- const visitor = new ClassUsageVisitor();
769
- (0, import_compiler3.tmplAstVisitAll)(visitor, parsed.nodes);
770
- const names = [...visitor.names];
771
- const patterns = [...visitor.patterns];
772
- const entry = { names, patterns, isDynamic: visitor.isDynamic };
773
- return entry;
774
- };
775
- var sourceUsage = (source) => {
776
- if (source.kind === "unknown") return null;
777
- if (source.kind === "inline") return parseUsage(source.source, source.path);
778
- return readCached(templates, source.path, parseUsage) ?? null;
779
- };
780
- var templateUsage = (sources) => {
781
- const names = /* @__PURE__ */ new Set();
782
- const patterns = /* @__PURE__ */ new Set();
783
- for (const source of sources) {
784
- const entry = sourceUsage(source);
785
- if (entry === null) return UNKNOWN_USAGE2;
786
- if (entry.isDynamic) return UNKNOWN_USAGE2;
787
- for (const name of entry.names) names.add(name);
788
- for (const pattern of entry.patterns) patterns.add(pattern);
789
- }
790
- const patternList = [...patterns];
791
- const compiled = patternList.map(toRegExp);
792
- const has = classMatcher(names, compiled);
793
- const size = names.size;
794
- const usage = { has, isDynamic: false, size };
795
- return usage;
796
- };
797
-
798
- // packages/lint-suite/src/lib/rules/utils/resolved-rules.util.ts
799
- var walkContainer = (container, parents, visit) => {
800
- for (const node of container.nodes ?? []) {
801
- if (node.type === "rule") {
802
- const resolved = resolveSelectors(node.selectors, parents);
803
- visit(node, resolved, parents);
804
- walkContainer(node, resolved, visit);
805
- continue;
806
- }
807
- if (node.type !== "atrule") continue;
808
- walkContainer(node, parents, visit);
809
- }
810
- };
811
- var walkResolvedRules = (root, visit) => {
812
- walkContainer(root, [], visit);
813
- };
814
-
815
- // packages/lint-suite/src/lib/rules/no-unused-classes/no-unused-classes.ts
816
- var { createPlugin, utils } = import_stylelint.default;
817
- var DEFAULT_IGNORE_PATTERNS = ["^(js|qa|mat|cdk|mdc)-"];
818
- var ruleName = "lint-suite/no-unused-classes";
819
- var rejected = (name) => {
820
- return `Unexpected class ".${name}" not used by any template of this stylesheet`;
821
- };
822
- var messages = utils.ruleMessages(ruleName, { rejected });
823
- var meta = {
824
- url: "https://github.com/F0rty-Tw0/lint-suite#no-unused-classes"
825
- };
826
- var isString = (value) => typeof value === "string";
827
- var validate = (result, primary, secondary) => {
828
- const primaryOptions = { actual: primary, possible: [true] };
829
- const possible = { ignoreClassPatterns: [isString] };
830
- const secondaryOptions = { actual: secondary, possible, optional: true };
831
- return utils.validateOptions(
832
- result,
833
- ruleName,
834
- primaryOptions,
835
- secondaryOptions
836
- );
837
- };
838
- var addNames2 = (selector, names) => {
839
- for (const name of selectorTemplateClasses(selector)) names.add(name);
840
- };
841
- var extendedClasses = (root) => {
842
- const names = /* @__PURE__ */ new Set();
843
- const collect2 = (atRule) => addNames2(atRule.params, names);
844
- root.walkAtRules("extend", collect2);
845
- return names;
846
- };
847
- var isEmittingRule = (rule) => {
848
- const isEmittingNode = (node) => {
849
- return node.type === "decl" || node.type === "atrule";
850
- };
851
- const children = rule.nodes;
852
- return children.some(isEmittingNode);
853
- };
854
- var emittedClasses = (root) => {
855
- const names = /* @__PURE__ */ new Set();
856
- const visit = (rule, resolved) => {
857
- const isEmitting = isEmittingRule(rule);
858
- if (!isEmitting) return;
859
- for (const selector of resolved) addNames2(selector, names);
860
- };
861
- walkResolvedRules(root, visit);
862
- return names;
863
- };
864
- var ruleClasses = (resolved, parents) => {
865
- const inherited = /* @__PURE__ */ new Set();
866
- for (const parent of parents) addNames2(parent, inherited);
867
- const own = /* @__PURE__ */ new Set();
868
- for (const selector of resolved) {
869
- for (const name of selectorTemplateClasses(selector)) {
870
- const isInherited = inherited.has(name);
871
- if (isInherited) continue;
872
- own.add(name);
873
- }
874
- }
875
- return [...own];
876
- };
877
- var reportUnused = (context, rule, name) => {
878
- const isEmitted = context.emitted.has(name);
879
- if (!isEmitted) return;
880
- const matchesIgnored = (pattern) => pattern.test(name);
881
- const isIgnored = context.ignored.some(matchesIgnored);
882
- if (isIgnored) return;
883
- const isUsed = context.isUsed(name);
884
- if (isUsed) return;
885
- const isExtended = context.extended.has(name);
886
- if (isExtended) return;
887
- const message = messages.rejected(name);
888
- const word = `.${name}`;
889
- const problem = {
890
- ruleName,
891
- result: context.result,
892
- node: rule,
893
- message,
894
- word
895
- };
896
- utils.report(problem);
897
- };
898
- var noUnusedClasses = (primary, secondary) => {
899
- const walk = (root, result) => {
900
- const isValid = validate(result, primary, secondary);
901
- if (!isValid) return;
902
- const file = root.source?.input.file;
903
- if (file === void 0) return;
904
- const templates2 = stylesheetTemplates(file);
905
- if (templates2.length === 0) return;
906
- const usage = templateUsage(templates2);
907
- if (usage.isDynamic) return;
908
- const patterns = secondary?.ignoreClassPatterns ?? DEFAULT_IGNORE_PATTERNS;
909
- const ignored = patterns.map(toRegExp);
910
- const extended = extendedClasses(root);
911
- const emitted = emittedClasses(root);
912
- const context = {
913
- result,
914
- ignored,
915
- extended,
916
- emitted,
917
- isUsed: usage.has
918
- };
919
- const visit = (rule, resolved, parents) => {
920
- for (const name of ruleClasses(resolved, parents)) {
921
- reportUnused(context, rule, name);
922
- }
923
- };
924
- walkResolvedRules(root, visit);
925
- };
926
- return walk;
927
- };
928
- noUnusedClasses.ruleName = ruleName;
929
- noUnusedClasses.messages = messages;
930
- noUnusedClasses.meta = meta;
931
- var plugin = createPlugin(ruleName, noUnusedClasses);
932
- var no_unused_classes_default = plugin;
933
-
934
- // packages/lint-suite/src/stylelint.ts
935
- var stylelint2 = {
936
- // Stylelint resolves config for cwd when picking a formatter; without a
937
- // top-level `rules` an overrides-only config fails with "No rules found".
938
- rules: {},
939
- overrides: [
940
- {
941
- files: ["**/*.scss", "**/*.css"],
942
- extends: [
943
- "stylelint-config-standard",
944
- "stylelint-config-standard-scss",
945
- "stylelint-config-recess-order"
946
- ],
947
- plugins: [...import_stylelint_scss.default, import_stylelint_selector_bem_pattern.default, no_unused_classes_default],
948
- rules: {
949
- "selector-class-pattern": "^(?:(?:o|c|u|t|s|is|has|_|js|qa)-)?[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*(?:__[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*)?(?:--[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*)?(?:\\[.+\\])?$",
950
- "plugin/selector-bem-pattern": {
951
- preset: "bem",
952
- implicitComponents: ["**/*.component.scss", "**/*.component.css"],
953
- ignoreCustomProperties: ["^--mdc", "^--sys"]
954
- },
955
- "no-descending-specificity": null,
956
- // A stylesheet class no linked template uses is reported.
957
- // Bad: .ghost {} used by no template
958
- // Good: delete it, or use it in a template
959
- "lint-suite/no-unused-classes": true
960
- }
961
- }
962
- ]
963
- };
964
- // Annotate the CommonJS export names for ESM import in node:
965
- 0 && (module.exports = {
966
- stylelint
967
- });
968
- //# sourceMappingURL=stylelint.cjs.map