@rnzeus/eslint-plugin 0.1.2 → 0.1.4

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.
@@ -0,0 +1,595 @@
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 __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+
25
+ // src/rules/styles-usage.ts
26
+ var import_node_fs = __toESM(require("fs"));
27
+ var import_node_path = __toESM(require("path"));
28
+ var DEFAULTS = {
29
+ stylesSuffix: ".styles",
30
+ stylesExtensions: ["ts", "tsx"],
31
+ directiveTag: "rnzeus-styles-used",
32
+ stylesObjectName: "styles",
33
+ styleProps: ["style", "contentContainerStyle"]
34
+ };
35
+ var stylesKeysCache = /* @__PURE__ */ new Map();
36
+ var MAX_CACHE = 200;
37
+ function cacheSet(file, value) {
38
+ if (stylesKeysCache.size >= MAX_CACHE) {
39
+ const firstKey = stylesKeysCache.keys().next().value;
40
+ if (firstKey) stylesKeysCache.delete(firstKey);
41
+ }
42
+ stylesKeysCache.set(file, value);
43
+ }
44
+ function fileProbablyUsesStyles(sourceCode, stylesSuffix, stylesObjectName) {
45
+ const ast = sourceCode.ast;
46
+ const body = ast?.body ?? [];
47
+ for (const n of body) {
48
+ if (n.type !== "ImportDeclaration") continue;
49
+ const v = n.source?.value;
50
+ if (typeof v === "string" && v.includes(stylesSuffix)) return true;
51
+ }
52
+ const text = sourceCode.getText();
53
+ return text.includes(`${stylesObjectName}.`);
54
+ }
55
+ function extractStyleKeysFromText(text) {
56
+ const keys = /* @__PURE__ */ new Set();
57
+ const idx = text.indexOf("StyleSheet.create");
58
+ if (idx === -1) return keys;
59
+ const braceStart = text.indexOf("{", idx);
60
+ if (braceStart === -1) return keys;
61
+ let depth = 0;
62
+ let readingKey = false;
63
+ let currentKey = "";
64
+ for (let i = braceStart; i < text.length; i++) {
65
+ const ch = text[i];
66
+ if (ch === "{") {
67
+ depth++;
68
+ continue;
69
+ }
70
+ if (ch === "}") {
71
+ depth--;
72
+ if (depth === 0) break;
73
+ continue;
74
+ }
75
+ if (depth !== 1) continue;
76
+ if (!readingKey && /[A-Za-z_$]/.test(ch)) {
77
+ readingKey = true;
78
+ currentKey = ch;
79
+ continue;
80
+ }
81
+ if (readingKey) {
82
+ if (/[\w$]/.test(ch)) {
83
+ currentKey += ch;
84
+ continue;
85
+ }
86
+ if (ch === ":") {
87
+ keys.add(currentKey);
88
+ readingKey = false;
89
+ currentKey = "";
90
+ continue;
91
+ }
92
+ readingKey = false;
93
+ currentKey = "";
94
+ }
95
+ }
96
+ return keys;
97
+ }
98
+ function resolveSiblingStylesFile(filename, stylesSuffix, stylesExtensions) {
99
+ const dir = import_node_path.default.dirname(filename);
100
+ const ext = import_node_path.default.extname(filename);
101
+ const base = import_node_path.default.basename(filename, ext);
102
+ for (const e of stylesExtensions) {
103
+ const candidate = import_node_path.default.join(dir, `${base}${stylesSuffix}.${e}`);
104
+ if (import_node_fs.default.existsSync(candidate)) return candidate;
105
+ }
106
+ return null;
107
+ }
108
+ function parseDirectiveKeys(sourceCode, directiveTag) {
109
+ const used = /* @__PURE__ */ new Set();
110
+ const tag = directiveTag.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
111
+ const re = new RegExp(`${tag}\\s*:\\s*([^\\n\\r*]+)`, "i");
112
+ for (const c of sourceCode.getAllComments()) {
113
+ const match = c.value.match(re);
114
+ if (!match) continue;
115
+ match[1].split("|").map((s) => s.trim()).filter(Boolean).forEach((k) => used.add(k));
116
+ }
117
+ return used;
118
+ }
119
+ function isIdentifier(node, name) {
120
+ return node?.type === "Identifier" && node.name === name;
121
+ }
122
+ function isStylesMemberExpression(node, stylesObjectName) {
123
+ if (node?.type !== "MemberExpression") return null;
124
+ if (!isIdentifier(node.object, stylesObjectName)) return null;
125
+ if (node.computed) {
126
+ if (node.property?.type === "Literal" && typeof node.property.value === "string") {
127
+ return { key: node.property.value, computed: true };
128
+ }
129
+ return { key: "", computed: true };
130
+ }
131
+ if (node.property?.type === "Identifier") {
132
+ return { key: node.property.name, computed: false };
133
+ }
134
+ return null;
135
+ }
136
+ function findBestReportNode(sourceCode) {
137
+ const ast = sourceCode.ast;
138
+ const body = ast?.body ?? [];
139
+ for (const n of body) {
140
+ if (n.type !== "ImportDeclaration") continue;
141
+ const v = n.source?.value;
142
+ if (typeof v === "string" && v.includes(".styles")) return n;
143
+ }
144
+ return ast;
145
+ }
146
+ function uniqueStrings(items) {
147
+ const out = [];
148
+ const seen = /* @__PURE__ */ new Set();
149
+ for (const s of items) {
150
+ if (!s || typeof s !== "string") continue;
151
+ if (seen.has(s)) continue;
152
+ seen.add(s);
153
+ out.push(s);
154
+ }
155
+ return out;
156
+ }
157
+ function buildStyleProps(defaults, incoming, mode) {
158
+ if (!incoming || incoming.length === 0) return new Set(defaults);
159
+ if (mode === "override") {
160
+ return new Set(uniqueStrings(incoming));
161
+ }
162
+ return new Set(uniqueStrings([...defaults, ...incoming]));
163
+ }
164
+ var rule = {
165
+ meta: {
166
+ type: "problem",
167
+ docs: {
168
+ description: "Ensures styles declared in sibling <File>.styles.ts(x) are used in <File>.ts(x)."
169
+ },
170
+ schema: [
171
+ {
172
+ type: "object",
173
+ properties: {
174
+ stylesSuffix: { type: "string" },
175
+ stylesExtensions: { type: "array", items: { type: "string" } },
176
+ directiveTag: { type: "string" },
177
+ stylesObjectName: { type: "string" },
178
+ styleProps: { type: "array", items: { type: "string" } },
179
+ type: { type: "string", enum: ["merge", "override"] }
180
+ },
181
+ additionalProperties: false
182
+ }
183
+ ],
184
+ messages: {
185
+ unusedStyles: "Unused styles in {{stylesFile}}: {{keys}}",
186
+ noWholeStylesObject: "Do not pass the whole styles object. Use style={styles.foo}.",
187
+ dynamicNeedsDirective: "Dynamic styles access ({{stylesName}}[...]) requires directive: {{tag}}"
188
+ }
189
+ },
190
+ create(context) {
191
+ const opt = context.options?.[0] ?? {};
192
+ const stylesSuffix = opt.stylesSuffix ?? DEFAULTS.stylesSuffix;
193
+ const stylesExtensions = opt.stylesExtensions ?? DEFAULTS.stylesExtensions;
194
+ const directiveTag = opt.directiveTag ?? DEFAULTS.directiveTag;
195
+ const stylesObjectName = opt.stylesObjectName ?? DEFAULTS.stylesObjectName;
196
+ const mode = opt.type ?? "merge";
197
+ const STYLE_PROPS = buildStyleProps(
198
+ DEFAULTS.styleProps,
199
+ opt.styleProps,
200
+ mode
201
+ );
202
+ const filename = context.filename;
203
+ const sourceCode = context.sourceCode;
204
+ if (!fileProbablyUsesStyles(sourceCode, stylesSuffix, stylesObjectName))
205
+ return {};
206
+ const ext = import_node_path.default.extname(filename);
207
+ if (ext !== ".ts" && ext !== ".tsx") return {};
208
+ const stylesPath = resolveSiblingStylesFile(
209
+ filename,
210
+ stylesSuffix,
211
+ stylesExtensions
212
+ );
213
+ if (!stylesPath) return {};
214
+ let declaredKeys = /* @__PURE__ */ new Set();
215
+ try {
216
+ const stat = import_node_fs.default.statSync(stylesPath);
217
+ const cached = stylesKeysCache.get(stylesPath);
218
+ if (!cached || cached.mtimeMs !== stat.mtimeMs) {
219
+ const text = import_node_fs.default.readFileSync(stylesPath, "utf8");
220
+ const keys = extractStyleKeysFromText(text);
221
+ cacheSet(stylesPath, { mtimeMs: stat.mtimeMs, keys });
222
+ declaredKeys = keys;
223
+ } else {
224
+ declaredKeys = cached.keys;
225
+ }
226
+ } catch {
227
+ declaredKeys = /* @__PURE__ */ new Set();
228
+ }
229
+ const usedKeys = /* @__PURE__ */ new Set();
230
+ const directiveKeys = parseDirectiveKeys(sourceCode, directiveTag);
231
+ directiveKeys.forEach((k) => usedKeys.add(k));
232
+ let sawDynamic = false;
233
+ let firstDynamicNode = null;
234
+ function recordFromNode(node) {
235
+ const info = isStylesMemberExpression(node, stylesObjectName);
236
+ if (!info) return;
237
+ if (info.key) {
238
+ usedKeys.add(info.key);
239
+ } else {
240
+ sawDynamic = true;
241
+ if (!firstDynamicNode) firstDynamicNode = node;
242
+ }
243
+ }
244
+ function checkNoWholeStylesObject(node) {
245
+ if (node.name?.type !== "JSXIdentifier") return;
246
+ if (node.name.name !== "styles") return;
247
+ const expr = node.value?.expression;
248
+ if (isIdentifier(expr, stylesObjectName)) {
249
+ context.report({ node, messageId: "noWholeStylesObject" });
250
+ }
251
+ }
252
+ function visitExpression(expr) {
253
+ if (!expr) return;
254
+ recordFromNode(expr);
255
+ if (expr.type === "ArrayExpression") {
256
+ expr.elements?.forEach(visitExpression);
257
+ } else if (expr.type === "ObjectExpression") {
258
+ expr.properties?.forEach((p) => visitExpression(p.value));
259
+ } else if (expr.type === "ConditionalExpression") {
260
+ visitExpression(expr.consequent);
261
+ visitExpression(expr.alternate);
262
+ } else if (expr.type === "LogicalExpression") {
263
+ visitExpression(expr.left);
264
+ visitExpression(expr.right);
265
+ }
266
+ }
267
+ function onJSXAttribute(node) {
268
+ if (node.name?.type === "JSXIdentifier" && STYLE_PROPS.has(node.name.name)) {
269
+ const expr = node.value?.expression;
270
+ if (expr) visitExpression(expr);
271
+ }
272
+ checkNoWholeStylesObject(node);
273
+ }
274
+ function finish() {
275
+ if (sawDynamic && directiveKeys.size === 0 && firstDynamicNode) {
276
+ context.report({
277
+ node: firstDynamicNode,
278
+ messageId: "dynamicNeedsDirective",
279
+ data: { tag: directiveTag, stylesName: stylesObjectName }
280
+ });
281
+ }
282
+ const unused = [...declaredKeys].filter((k) => !usedKeys.has(k));
283
+ if (unused.length) {
284
+ context.report({
285
+ node: findBestReportNode(sourceCode),
286
+ messageId: "unusedStyles",
287
+ data: {
288
+ stylesFile: import_node_path.default.basename(stylesPath),
289
+ keys: unused.sort().join(", ")
290
+ }
291
+ });
292
+ }
293
+ }
294
+ return {
295
+ JSXAttribute: onJSXAttribute,
296
+ "Program:exit": finish
297
+ };
298
+ }
299
+ };
300
+ var styles_usage_default = rule;
301
+
302
+ // src/rules/styles-naming.ts
303
+ var import_node_path2 = __toESM(require("path"));
304
+ var DEFAULTS2 = {
305
+ stylesSuffix: ".styles",
306
+ stylesExtensions: ["ts", "tsx"]
307
+ };
308
+ var SNAKE_CASE_RE = /^[a-z][a-z0-9_]*$/;
309
+ function extractTopLevelStyleKeys(text) {
310
+ const result = [];
311
+ const idx = text.indexOf("StyleSheet.create");
312
+ if (idx === -1) return result;
313
+ const braceStart = text.indexOf("{", idx);
314
+ if (braceStart === -1) return result;
315
+ let depth = 0;
316
+ let readingKey = false;
317
+ let currentKey = "";
318
+ let keyStartIndex = -1;
319
+ for (let i = braceStart; i < text.length; i++) {
320
+ const ch = text[i];
321
+ if (ch === "{") {
322
+ depth++;
323
+ continue;
324
+ }
325
+ if (ch === "}") {
326
+ depth--;
327
+ if (depth === 0) break;
328
+ continue;
329
+ }
330
+ if (depth !== 1) continue;
331
+ if (!readingKey && /[A-Za-z_$]/.test(ch)) {
332
+ readingKey = true;
333
+ currentKey = ch;
334
+ keyStartIndex = i;
335
+ continue;
336
+ }
337
+ if (readingKey) {
338
+ if (/[\w$]/.test(ch)) {
339
+ currentKey += ch;
340
+ continue;
341
+ }
342
+ if (ch === ":") {
343
+ result.push({ key: currentKey, index: keyStartIndex });
344
+ readingKey = false;
345
+ currentKey = "";
346
+ keyStartIndex = -1;
347
+ continue;
348
+ }
349
+ readingKey = false;
350
+ currentKey = "";
351
+ keyStartIndex = -1;
352
+ }
353
+ }
354
+ return result;
355
+ }
356
+ function isStylesFile(filename, stylesSuffix, stylesExtensions) {
357
+ const ext = import_node_path2.default.extname(filename);
358
+ if (!stylesExtensions.includes(ext.replace(".", ""))) return false;
359
+ return import_node_path2.default.basename(filename).includes(stylesSuffix);
360
+ }
361
+ var rule2 = {
362
+ meta: {
363
+ type: "problem",
364
+ docs: {
365
+ description: "Enforce snake_case naming for style keys in *.styles.ts(x) files."
366
+ },
367
+ schema: [
368
+ {
369
+ type: "object",
370
+ properties: {
371
+ stylesSuffix: { type: "string" },
372
+ stylesExtensions: { type: "array", items: { type: "string" } }
373
+ },
374
+ additionalProperties: false
375
+ }
376
+ ],
377
+ messages: {
378
+ invalidName: 'Style name "{{name}}" must be snake_case (e.g. "{{suggestion}}").'
379
+ }
380
+ },
381
+ create(context) {
382
+ const opt = context.options?.[0] ?? {};
383
+ const stylesSuffix = opt.stylesSuffix ?? DEFAULTS2.stylesSuffix;
384
+ const stylesExtensions = opt.stylesExtensions ?? DEFAULTS2.stylesExtensions;
385
+ const filename = context.getFilename();
386
+ if (!isStylesFile(filename, stylesSuffix, stylesExtensions)) {
387
+ return {};
388
+ }
389
+ const sourceCode = context.getSourceCode();
390
+ const text = sourceCode.getText();
391
+ const keys = extractTopLevelStyleKeys(text);
392
+ function toSnakeCase(input) {
393
+ return input.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[-\s]+/g, "_").toLowerCase();
394
+ }
395
+ for (const { key, index } of keys) {
396
+ if (!SNAKE_CASE_RE.test(key)) {
397
+ const loc = sourceCode.getLocFromIndex(index);
398
+ context.report({
399
+ loc: {
400
+ start: loc,
401
+ end: { line: loc.line, column: loc.column + key.length }
402
+ },
403
+ messageId: "invalidName",
404
+ data: {
405
+ name: key,
406
+ suggestion: toSnakeCase(key)
407
+ }
408
+ });
409
+ }
410
+ }
411
+ return {};
412
+ }
413
+ };
414
+ var styles_naming_default = rule2;
415
+
416
+ // src/rules/slice-imports.ts
417
+ var import_node_path3 = __toESM(require("path"));
418
+ var DEFAULTS3 = {
419
+ layers: ["shared", "entities", "features", "widgets", "pages", "app"],
420
+ srcRoot: "src"
421
+ };
422
+ function normalizePath(filepath) {
423
+ return filepath.split(import_node_path3.default.sep).join("/");
424
+ }
425
+ function getFileContext(filename, srcRoot, layers) {
426
+ const normalized = normalizePath(filename);
427
+ const parts = normalized.split("/");
428
+ const srcIndex = parts.lastIndexOf(srcRoot);
429
+ if (srcIndex === -1) return null;
430
+ const layer = parts[srcIndex + 1];
431
+ if (!layer || !layers.includes(layer)) return null;
432
+ if (layer === "shared") {
433
+ return { layer, slice: null };
434
+ }
435
+ const slice = parts[srcIndex + 2];
436
+ if (!slice) return null;
437
+ return { layer, slice };
438
+ }
439
+ function parseAliasImport(importPath, layers) {
440
+ if (!importPath.startsWith("@")) return null;
441
+ const normalized = importPath.replace(/^@/, "");
442
+ const parts = normalized.split("/").filter(Boolean);
443
+ const layer = parts[0];
444
+ if (!layer || !layers.includes(layer)) return null;
445
+ if (layer === "shared") {
446
+ return {
447
+ layer,
448
+ slice: null,
449
+ rest: parts.slice(1)
450
+ };
451
+ }
452
+ const slice = parts[1];
453
+ if (!slice) {
454
+ return {
455
+ layer,
456
+ slice: null,
457
+ rest: []
458
+ };
459
+ }
460
+ return {
461
+ layer,
462
+ slice,
463
+ rest: parts.slice(2)
464
+ };
465
+ }
466
+ function getLayerIndex(layer, layers) {
467
+ return layers.indexOf(layer);
468
+ }
469
+ function isRelativeImport(importPath) {
470
+ return importPath.startsWith("./") || importPath.startsWith("../");
471
+ }
472
+ function isCrossSliceXImport(imported, currentSlice) {
473
+ return imported.rest[0] === "@x" && imported.rest[1] === currentSlice;
474
+ }
475
+ var rule3 = {
476
+ meta: {
477
+ type: "problem",
478
+ docs: {
479
+ description: "Enforces FSD import boundaries: layer order, same-slice relative imports only, and cross-slice access only through @x/<currentSlice>."
480
+ },
481
+ schema: [
482
+ {
483
+ type: "object",
484
+ properties: {
485
+ layers: {
486
+ type: "array",
487
+ items: { type: "string" }
488
+ },
489
+ srcRoot: { type: "string" }
490
+ },
491
+ additionalProperties: false
492
+ }
493
+ ],
494
+ messages: {
495
+ forbiddenHigherLayer: 'Layer "{{currentLayer}}" cannot import from higher layer "{{importedLayer}}".',
496
+ sameSliceMustBeRelative: 'Same-slice imports must be relative. Replace "{{importPath}}" with a relative path.',
497
+ crossSliceMustUseX: 'Cross-slice imports inside layer "{{layer}}" are allowed only through "@{{layer}}/{{targetSlice}}/@x/{{currentSlice}}".'
498
+ }
499
+ },
500
+ create(context) {
501
+ const opt = context.options?.[0] ?? {};
502
+ const layers = opt.layers ?? DEFAULTS3.layers;
503
+ const srcRoot = opt.srcRoot ?? DEFAULTS3.srcRoot;
504
+ const filename = context.getFilename();
505
+ const fileCtx = getFileContext(filename, srcRoot, layers);
506
+ if (!fileCtx) return {};
507
+ return {
508
+ ImportDeclaration(node) {
509
+ const importPath = node.source?.value;
510
+ if (typeof importPath !== "string") return;
511
+ if (isRelativeImport(importPath)) return;
512
+ const imported = parseAliasImport(importPath, layers);
513
+ if (!imported) return;
514
+ const currentLayer = fileCtx.layer;
515
+ const currentSlice = fileCtx.slice;
516
+ const importedLayer = imported.layer;
517
+ const importedSlice = imported.slice;
518
+ const currentLayerIndex = getLayerIndex(currentLayer, layers);
519
+ const importedLayerIndex = getLayerIndex(importedLayer, layers);
520
+ if (currentLayerIndex === -1 || importedLayerIndex === -1) return;
521
+ if (importedLayerIndex > currentLayerIndex) {
522
+ context.report({
523
+ node: node.source,
524
+ messageId: "forbiddenHigherLayer",
525
+ data: {
526
+ currentLayer,
527
+ importedLayer
528
+ }
529
+ });
530
+ return;
531
+ }
532
+ if (currentLayer === "shared") {
533
+ return;
534
+ }
535
+ if (!currentSlice) return;
536
+ if (importedLayer !== currentLayer) return;
537
+ if (!importedSlice) {
538
+ context.report({
539
+ node: node.source,
540
+ messageId: "crossSliceMustUseX",
541
+ data: {
542
+ layer: currentLayer,
543
+ targetSlice: "<targetSlice>",
544
+ currentSlice
545
+ }
546
+ });
547
+ return;
548
+ }
549
+ if (importedSlice === currentSlice) {
550
+ context.report({
551
+ node: node.source,
552
+ messageId: "sameSliceMustBeRelative",
553
+ data: {
554
+ importPath
555
+ }
556
+ });
557
+ return;
558
+ }
559
+ if (!isCrossSliceXImport(imported, currentSlice)) {
560
+ context.report({
561
+ node: node.source,
562
+ messageId: "crossSliceMustUseX",
563
+ data: {
564
+ layer: currentLayer,
565
+ targetSlice: importedSlice,
566
+ currentSlice
567
+ }
568
+ });
569
+ }
570
+ }
571
+ };
572
+ }
573
+ };
574
+ var slice_imports_default = rule3;
575
+
576
+ // src/plugin.ts
577
+ var plugin = {
578
+ rules: {
579
+ "slice-imports": slice_imports_default,
580
+ "styles-usage": styles_usage_default,
581
+ "styles-naming": styles_naming_default
582
+ }
583
+ };
584
+ var plugin_default = plugin;
585
+
586
+ // src/configs/imports.ts
587
+ module.exports = [
588
+ {
589
+ plugins: { rnzeus: plugin_default },
590
+ rules: {
591
+ "rnzeus/slice-imports": "error"
592
+ }
593
+ }
594
+ ];
595
+ //# sourceMappingURL=imports.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/rules/styles-usage.ts","../../src/rules/styles-naming.ts","../../src/rules/slice-imports.ts","../../src/plugin.ts","../../src/configs/imports.ts"],"sourcesContent":["import type { Rule, SourceCode } from \"eslint\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\ntype Options = [\n {\n stylesSuffix?: string;\n stylesExtensions?: string[];\n directiveTag?: string;\n stylesObjectName?: string;\n\n /**\n * JSX props that should be treated as “style-like props”.\n * Example: [\"style\", \"contentContainerStyle\", \"columnWrapperStyle\"]\n */\n styleProps?: string[];\n\n /**\n * How to apply styleProps relative to defaults.\n * - \"merge\" (default): DEFAULTS.styleProps + styleProps (unique)\n * - \"override\": only styleProps\n */\n type?: \"merge\" | \"override\";\n }\n];\n\nconst DEFAULTS = {\n stylesSuffix: \".styles\",\n stylesExtensions: [\"ts\", \"tsx\"],\n directiveTag: \"rnzeus-styles-used\",\n stylesObjectName: \"styles\",\n\n styleProps: [\"style\", \"contentContainerStyle\"],\n} as const;\n\nconst stylesKeysCache = new Map<\n string,\n { mtimeMs: number; keys: Set<string> }\n>();\nconst MAX_CACHE = 200;\n\nfunction cacheSet(file: string, value: { mtimeMs: number; keys: Set<string> }) {\n if (stylesKeysCache.size >= MAX_CACHE) {\n const firstKey = stylesKeysCache.keys().next().value;\n if (firstKey) stylesKeysCache.delete(firstKey);\n }\n stylesKeysCache.set(file, value);\n}\n\nfunction fileProbablyUsesStyles(\n sourceCode: SourceCode,\n stylesSuffix: string,\n stylesObjectName: string\n): boolean {\n const ast: any = sourceCode.ast;\n const body: any[] = ast?.body ?? [];\n\n for (const n of body) {\n if (n.type !== \"ImportDeclaration\") continue;\n const v = n.source?.value;\n if (typeof v === \"string\" && v.includes(stylesSuffix)) return true;\n }\n\n const text = sourceCode.getText();\n return text.includes(`${stylesObjectName}.`);\n}\n\nfunction extractStyleKeysFromText(text: string): Set<string> {\n const keys = new Set<string>();\n\n const idx = text.indexOf(\"StyleSheet.create\");\n if (idx === -1) return keys;\n\n const braceStart = text.indexOf(\"{\", idx);\n if (braceStart === -1) return keys;\n\n let depth = 0;\n let readingKey = false;\n let currentKey = \"\";\n\n for (let i = braceStart; i < text.length; i++) {\n const ch = text[i];\n\n if (ch === \"{\") {\n depth++;\n continue;\n }\n\n if (ch === \"}\") {\n depth--;\n if (depth === 0) break;\n continue;\n }\n\n if (depth !== 1) continue;\n\n if (!readingKey && /[A-Za-z_$]/.test(ch)) {\n readingKey = true;\n currentKey = ch;\n continue;\n }\n\n if (readingKey) {\n if (/[\\w$]/.test(ch)) {\n currentKey += ch;\n continue;\n }\n\n if (ch === \":\") {\n keys.add(currentKey);\n readingKey = false;\n currentKey = \"\";\n continue;\n }\n\n readingKey = false;\n currentKey = \"\";\n }\n }\n\n return keys;\n}\n\nfunction resolveSiblingStylesFile(\n filename: string,\n stylesSuffix: string,\n stylesExtensions: readonly string[]\n): string | null {\n const dir = path.dirname(filename);\n const ext = path.extname(filename);\n const base = path.basename(filename, ext);\n\n for (const e of stylesExtensions) {\n const candidate = path.join(dir, `${base}${stylesSuffix}.${e}`);\n if (fs.existsSync(candidate)) return candidate;\n }\n\n return null;\n}\n\nfunction parseDirectiveKeys(\n sourceCode: SourceCode,\n directiveTag: string\n): Set<string> {\n const used = new Set<string>();\n const tag = directiveTag.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const re = new RegExp(`${tag}\\\\s*:\\\\s*([^\\\\n\\\\r*]+)`, \"i\");\n\n for (const c of sourceCode.getAllComments()) {\n const match = c.value.match(re);\n if (!match) continue;\n\n match[1]\n .split(\"|\")\n .map((s) => s.trim())\n .filter(Boolean)\n .forEach((k) => used.add(k));\n }\n\n return used;\n}\n\nfunction isIdentifier(node: any, name: string): boolean {\n return node?.type === \"Identifier\" && node.name === name;\n}\n\nfunction isStylesMemberExpression(\n node: any,\n stylesObjectName: string\n): { key: string; computed: boolean } | null {\n if (node?.type !== \"MemberExpression\") return null;\n if (!isIdentifier(node.object, stylesObjectName)) return null;\n\n if (node.computed) {\n if (\n node.property?.type === \"Literal\" &&\n typeof node.property.value === \"string\"\n ) {\n return { key: node.property.value, computed: true };\n }\n return { key: \"\", computed: true };\n }\n\n if (node.property?.type === \"Identifier\") {\n return { key: node.property.name, computed: false };\n }\n\n return null;\n}\n\nfunction findBestReportNode(sourceCode: SourceCode): any {\n const ast: any = sourceCode.ast;\n const body: any[] = ast?.body ?? [];\n\n for (const n of body) {\n if (n.type !== \"ImportDeclaration\") continue;\n const v = n.source?.value;\n if (typeof v === \"string\" && v.includes(\".styles\")) return n;\n }\n\n return ast;\n}\n\nfunction uniqueStrings(items: readonly string[]): string[] {\n const out: string[] = [];\n const seen = new Set<string>();\n for (const s of items) {\n if (!s || typeof s !== \"string\") continue;\n if (seen.has(s)) continue;\n seen.add(s);\n out.push(s);\n }\n return out;\n}\n\nfunction buildStyleProps(\n defaults: readonly string[],\n incoming: string[] | undefined,\n mode: \"merge\" | \"override\"\n): Set<string> {\n if (!incoming || incoming.length === 0) return new Set(defaults);\n\n if (mode === \"override\") {\n return new Set(uniqueStrings(incoming));\n }\n\n // merge (default): defaults + incoming (unique)\n return new Set(uniqueStrings([...defaults, ...incoming]));\n}\n\nconst rule: Rule.RuleModule = {\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Ensures styles declared in sibling <File>.styles.ts(x) are used in <File>.ts(x).\",\n },\n schema: [\n {\n type: \"object\",\n properties: {\n stylesSuffix: { type: \"string\" },\n stylesExtensions: { type: \"array\", items: { type: \"string\" } },\n directiveTag: { type: \"string\" },\n stylesObjectName: { type: \"string\" },\n\n styleProps: { type: \"array\", items: { type: \"string\" } },\n type: { type: \"string\", enum: [\"merge\", \"override\"] },\n },\n additionalProperties: false,\n },\n ],\n messages: {\n unusedStyles: \"Unused styles in {{stylesFile}}: {{keys}}\",\n noWholeStylesObject:\n \"Do not pass the whole styles object. Use style={styles.foo}.\",\n dynamicNeedsDirective:\n \"Dynamic styles access ({{stylesName}}[...]) requires directive: {{tag}}\",\n },\n },\n\n create(context) {\n const opt = (context.options?.[0] ?? {}) as Options[0];\n\n const stylesSuffix = opt.stylesSuffix ?? DEFAULTS.stylesSuffix;\n const stylesExtensions = opt.stylesExtensions ?? DEFAULTS.stylesExtensions;\n const directiveTag = opt.directiveTag ?? DEFAULTS.directiveTag;\n const stylesObjectName = opt.stylesObjectName ?? DEFAULTS.stylesObjectName;\n\n const mode: \"merge\" | \"override\" = opt.type ?? \"merge\";\n const STYLE_PROPS = buildStyleProps(\n DEFAULTS.styleProps,\n opt.styleProps,\n mode\n );\n\n const filename = context.filename;\n const sourceCode = context.sourceCode;\n\n if (!fileProbablyUsesStyles(sourceCode, stylesSuffix, stylesObjectName))\n return {};\n\n const ext = path.extname(filename);\n if (ext !== \".ts\" && ext !== \".tsx\") return {};\n\n const stylesPath = resolveSiblingStylesFile(\n filename,\n stylesSuffix,\n stylesExtensions\n );\n if (!stylesPath) return {};\n\n let declaredKeys: Set<string> = new Set();\n\n try {\n const stat = fs.statSync(stylesPath);\n const cached = stylesKeysCache.get(stylesPath);\n\n if (!cached || cached.mtimeMs !== stat.mtimeMs) {\n const text = fs.readFileSync(stylesPath, \"utf8\");\n const keys = extractStyleKeysFromText(text);\n cacheSet(stylesPath, { mtimeMs: stat.mtimeMs, keys });\n declaredKeys = keys;\n } else {\n declaredKeys = cached.keys;\n }\n } catch {\n declaredKeys = new Set();\n }\n\n const usedKeys = new Set<string>();\n const directiveKeys = parseDirectiveKeys(sourceCode, directiveTag);\n directiveKeys.forEach((k) => usedKeys.add(k));\n\n let sawDynamic = false;\n let firstDynamicNode: any | null = null;\n\n function recordFromNode(node: any) {\n const info = isStylesMemberExpression(node, stylesObjectName);\n if (!info) return;\n\n if (info.key) {\n usedKeys.add(info.key);\n } else {\n sawDynamic = true;\n if (!firstDynamicNode) firstDynamicNode = node;\n }\n }\n\n function checkNoWholeStylesObject(node: any) {\n // <Child styles={styles} /> — запрещаем\n if (node.name?.type !== \"JSXIdentifier\") return;\n if (node.name.name !== \"styles\") return;\n\n const expr = node.value?.expression;\n if (isIdentifier(expr, stylesObjectName)) {\n context.report({ node, messageId: \"noWholeStylesObject\" });\n }\n }\n\n function visitExpression(expr: any) {\n if (!expr) return;\n\n recordFromNode(expr);\n\n if (expr.type === \"ArrayExpression\") {\n expr.elements?.forEach(visitExpression);\n } else if (expr.type === \"ObjectExpression\") {\n expr.properties?.forEach((p: any) => visitExpression(p.value));\n } else if (expr.type === \"ConditionalExpression\") {\n visitExpression(expr.consequent);\n visitExpression(expr.alternate);\n } else if (expr.type === \"LogicalExpression\") {\n visitExpression(expr.left);\n visitExpression(expr.right);\n }\n }\n\n function onJSXAttribute(node: any) {\n if (\n node.name?.type === \"JSXIdentifier\" &&\n STYLE_PROPS.has(node.name.name)\n ) {\n const expr = node.value?.expression;\n if (expr) visitExpression(expr);\n }\n\n checkNoWholeStylesObject(node);\n }\n\n function finish() {\n if (sawDynamic && directiveKeys.size === 0 && firstDynamicNode) {\n context.report({\n node: firstDynamicNode,\n messageId: \"dynamicNeedsDirective\",\n data: { tag: directiveTag, stylesName: stylesObjectName },\n });\n }\n\n const unused = [...declaredKeys].filter((k) => !usedKeys.has(k));\n if (unused.length) {\n context.report({\n node: findBestReportNode(sourceCode),\n messageId: \"unusedStyles\",\n data: {\n stylesFile: path.basename(stylesPath as string),\n keys: unused.sort().join(\", \"),\n },\n });\n }\n }\n\n return {\n JSXAttribute: onJSXAttribute,\n \"Program:exit\": finish,\n };\n },\n};\n\nexport default rule;\n","import type { Rule } from \"eslint\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\ntype Options = [\n {\n /**\n * Suffix for styles files.\n * Default: \".styles\"\n */\n stylesSuffix?: string;\n\n /**\n * Allowed extensions.\n * Default: [\"ts\", \"tsx\"]\n */\n stylesExtensions?: string[];\n }\n];\n\nconst DEFAULTS = {\n stylesSuffix: \".styles\",\n stylesExtensions: [\"ts\", \"tsx\"],\n} as const;\n\nconst SNAKE_CASE_RE = /^[a-z][a-z0-9_]*$/;\n\nfunction extractTopLevelStyleKeys(\n text: string\n): { key: string; index: number }[] {\n const result: { key: string; index: number }[] = [];\n\n const idx = text.indexOf(\"StyleSheet.create\");\n if (idx === -1) return result;\n\n const braceStart = text.indexOf(\"{\", idx);\n if (braceStart === -1) return result;\n\n let depth = 0;\n let readingKey = false;\n let currentKey = \"\";\n let keyStartIndex = -1;\n\n for (let i = braceStart; i < text.length; i++) {\n const ch = text[i];\n\n if (ch === \"{\") {\n depth++;\n continue;\n }\n\n if (ch === \"}\") {\n depth--;\n if (depth === 0) break;\n continue;\n }\n\n if (depth !== 1) continue;\n\n if (!readingKey && /[A-Za-z_$]/.test(ch)) {\n readingKey = true;\n currentKey = ch;\n keyStartIndex = i;\n continue;\n }\n\n if (readingKey) {\n if (/[\\w$]/.test(ch)) {\n currentKey += ch;\n continue;\n }\n\n if (ch === \":\") {\n result.push({ key: currentKey, index: keyStartIndex });\n readingKey = false;\n currentKey = \"\";\n keyStartIndex = -1;\n continue;\n }\n\n readingKey = false;\n currentKey = \"\";\n keyStartIndex = -1;\n }\n }\n\n return result;\n}\n\nfunction isStylesFile(\n filename: string,\n stylesSuffix: string,\n stylesExtensions: readonly string[]\n): boolean {\n const ext = path.extname(filename);\n if (!stylesExtensions.includes(ext.replace(\".\", \"\"))) return false;\n return path.basename(filename).includes(stylesSuffix);\n}\n\nconst rule: Rule.RuleModule = {\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Enforce snake_case naming for style keys in *.styles.ts(x) files.\",\n },\n schema: [\n {\n type: \"object\",\n properties: {\n stylesSuffix: { type: \"string\" },\n stylesExtensions: { type: \"array\", items: { type: \"string\" } },\n },\n additionalProperties: false,\n },\n ],\n messages: {\n invalidName:\n 'Style name \"{{name}}\" must be snake_case (e.g. \"{{suggestion}}\").',\n },\n },\n\n create(context) {\n const opt = (context.options?.[0] ?? {}) as Options[0];\n\n const stylesSuffix = opt.stylesSuffix ?? DEFAULTS.stylesSuffix;\n const stylesExtensions = opt.stylesExtensions ?? DEFAULTS.stylesExtensions;\n\n const filename = context.getFilename();\n if (!isStylesFile(filename, stylesSuffix, stylesExtensions)) {\n return {};\n }\n\n const sourceCode = context.getSourceCode();\n const text = sourceCode.getText();\n\n const keys = extractTopLevelStyleKeys(text);\n\n function toSnakeCase(input: string): string {\n return input\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .replace(/[-\\s]+/g, \"_\")\n .toLowerCase();\n }\n\n for (const { key, index } of keys) {\n if (!SNAKE_CASE_RE.test(key)) {\n const loc = sourceCode.getLocFromIndex(index);\n\n context.report({\n loc: {\n start: loc,\n end: { line: loc.line, column: loc.column + key.length },\n },\n messageId: \"invalidName\",\n data: {\n name: key,\n suggestion: toSnakeCase(key),\n },\n });\n }\n }\n\n return {};\n },\n};\n\nexport default rule;\n","import type { Rule } from \"eslint\";\nimport path from \"node:path\";\n\ntype Options = [\n {\n /**\n * Allowed FSD layers in dependency order:\n * shared -> entities -> features -> widgets -> pages -> app\n */\n layers?: string[];\n\n /**\n * Source root marker in absolute filename.\n * Used to detect current layer/slice from file path.\n * Default: \"src\"\n */\n srcRoot?: string;\n },\n];\n\nconst DEFAULTS = {\n layers: [\"shared\", \"entities\", \"features\", \"widgets\", \"pages\", \"app\"],\n srcRoot: \"src\",\n} as const;\n\ntype FileContext = {\n layer: string;\n slice: string | null;\n};\n\ntype ImportContext = {\n layer: string;\n slice: string | null;\n rest: string[];\n};\n\nfunction normalizePath(filepath: string): string {\n return filepath.split(path.sep).join(\"/\");\n}\n\nfunction getFileContext(\n filename: string,\n srcRoot: string,\n layers: readonly string[],\n): FileContext | null {\n const normalized = normalizePath(filename);\n const parts = normalized.split(\"/\");\n\n const srcIndex = parts.lastIndexOf(srcRoot);\n if (srcIndex === -1) return null;\n\n const layer = parts[srcIndex + 1];\n if (!layer || !layers.includes(layer)) return null;\n\n // shared is not slice-oriented for this rule\n if (layer === \"shared\") {\n return { layer, slice: null };\n }\n\n const slice = parts[srcIndex + 2];\n if (!slice) return null;\n\n return { layer, slice };\n}\n\nfunction parseAliasImport(\n importPath: string,\n layers: readonly string[],\n): ImportContext | null {\n if (!importPath.startsWith(\"@\")) return null;\n\n const normalized = importPath.replace(/^@/, \"\");\n const parts = normalized.split(\"/\").filter(Boolean);\n\n const layer = parts[0];\n if (!layer || !layers.includes(layer)) return null;\n\n if (layer === \"shared\") {\n return {\n layer,\n slice: null,\n rest: parts.slice(1),\n };\n }\n\n const slice = parts[1];\n if (!slice) {\n return {\n layer,\n slice: null,\n rest: [],\n };\n }\n\n return {\n layer,\n slice,\n rest: parts.slice(2),\n };\n}\n\nfunction getLayerIndex(layer: string, layers: readonly string[]): number {\n return layers.indexOf(layer);\n}\n\nfunction isRelativeImport(importPath: string): boolean {\n return importPath.startsWith(\"./\") || importPath.startsWith(\"../\");\n}\n\nfunction isCrossSliceXImport(\n imported: ImportContext,\n currentSlice: string,\n): boolean {\n // expected:\n // @entities/product/@x/cart\n // @entities/product/@x/cart/...\n return imported.rest[0] === \"@x\" && imported.rest[1] === currentSlice;\n}\n\nconst rule: Rule.RuleModule = {\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Enforces FSD import boundaries: layer order, same-slice relative imports only, and cross-slice access only through @x/<currentSlice>.\",\n },\n schema: [\n {\n type: \"object\",\n properties: {\n layers: {\n type: \"array\",\n items: { type: \"string\" },\n },\n srcRoot: { type: \"string\" },\n },\n additionalProperties: false,\n },\n ],\n messages: {\n forbiddenHigherLayer:\n 'Layer \"{{currentLayer}}\" cannot import from higher layer \"{{importedLayer}}\".',\n sameSliceMustBeRelative:\n 'Same-slice imports must be relative. Replace \"{{importPath}}\" with a relative path.',\n crossSliceMustUseX:\n 'Cross-slice imports inside layer \"{{layer}}\" are allowed only through \"@{{layer}}/{{targetSlice}}/@x/{{currentSlice}}\".',\n },\n },\n\n create(context) {\n const opt = (context.options?.[0] ?? {}) as Options[0];\n const layers = opt.layers ?? DEFAULTS.layers;\n const srcRoot = opt.srcRoot ?? DEFAULTS.srcRoot;\n\n const filename = context.getFilename();\n const fileCtx = getFileContext(filename, srcRoot, layers);\n\n if (!fileCtx) return {};\n\n return {\n ImportDeclaration(node: any) {\n const importPath = node.source?.value;\n if (typeof importPath !== \"string\") return;\n\n // rule only validates alias imports for now\n if (isRelativeImport(importPath)) return;\n\n const imported = parseAliasImport(importPath, layers);\n if (!imported) return;\n\n const currentLayer = fileCtx.layer;\n const currentSlice = fileCtx.slice;\n\n const importedLayer = imported.layer;\n const importedSlice = imported.slice;\n\n const currentLayerIndex = getLayerIndex(currentLayer, layers);\n const importedLayerIndex = getLayerIndex(importedLayer, layers);\n\n if (currentLayerIndex === -1 || importedLayerIndex === -1) return;\n\n // 1) Layer order\n // lower layers must not import higher layers\n if (importedLayerIndex > currentLayerIndex) {\n context.report({\n node: node.source,\n messageId: \"forbiddenHigherLayer\",\n data: {\n currentLayer,\n importedLayer,\n },\n });\n return;\n }\n\n // shared is not slice-oriented here\n if (currentLayer === \"shared\") {\n return;\n }\n\n // if current file has no slice, do nothing further\n if (!currentSlice) return;\n\n // 2) Same-layer restrictions\n if (importedLayer !== currentLayer) return;\n\n // no valid slice in target -> still forbidden as direct same-layer import\n if (!importedSlice) {\n context.report({\n node: node.source,\n messageId: \"crossSliceMustUseX\",\n data: {\n layer: currentLayer,\n targetSlice: \"<targetSlice>\",\n currentSlice,\n },\n });\n return;\n }\n\n // 2a) Same slice via alias -> forbidden, must be relative\n if (importedSlice === currentSlice) {\n context.report({\n node: node.source,\n messageId: \"sameSliceMustBeRelative\",\n data: {\n importPath,\n },\n });\n return;\n }\n\n // 2b) Other slice in same layer -> only through @x/<currentSlice>\n if (!isCrossSliceXImport(imported, currentSlice)) {\n context.report({\n node: node.source,\n messageId: \"crossSliceMustUseX\",\n data: {\n layer: currentLayer,\n targetSlice: importedSlice,\n currentSlice,\n },\n });\n }\n },\n };\n },\n};\n\nexport default rule;\n","import stylesUsageRule from \"./rules/styles-usage\";\nimport stylesNamingRule from \"./rules/styles-naming\";\nimport sliceImportsRule from \"./rules/slice-imports\";\n\nconst plugin = {\n rules: {\n \"slice-imports\": sliceImportsRule,\n \"styles-usage\": stylesUsageRule,\n \"styles-naming\": stylesNamingRule,\n },\n};\n\nexport default plugin;\n","import plugin from \"../plugin\";\n\nexport = [\n {\n plugins: { rnzeus: plugin },\n rules: {\n \"rnzeus/slice-imports\": \"error\",\n },\n },\n];\n"],"mappings":"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","names":["path","fs","import_node_path","DEFAULTS","path","rule","import_node_path","DEFAULTS","path","rule"]}