pasika 0.5.9 → 0.5.11

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.
@@ -2218,6 +2218,7 @@ var jsxHygieneRule = {
2218
2218
  };
2219
2219
 
2220
2220
  // eslint/rules/interactive-component.ts
2221
+ import path20 from "path";
2221
2222
  var INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
2222
2223
  "a",
2223
2224
  "button",
@@ -2230,6 +2231,28 @@ var INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
2230
2231
  "textarea",
2231
2232
  "video"
2232
2233
  ]);
2234
+ var NEXT_ROUTING_FILES3 = /* @__PURE__ */ new Set([
2235
+ "default",
2236
+ "error",
2237
+ "global-error",
2238
+ "instrumentation",
2239
+ "layout",
2240
+ "loading",
2241
+ "middleware",
2242
+ "not-found",
2243
+ "page",
2244
+ "route",
2245
+ "template",
2246
+ // File conventions Next.js requires to keep their exact names in src/app/
2247
+ "apple-icon",
2248
+ "icon",
2249
+ "manifest",
2250
+ "opengraph-image",
2251
+ "robots",
2252
+ "sitemap",
2253
+ "twitter-image"
2254
+ ]);
2255
+ var INTERACTIVE_ATTRIBUTES = /* @__PURE__ */ new Set(["onClick", "onChange", "onSubmit", "href", "onKeyDown", "onKeyUp", "onFocus", "onBlur", "htmlFor"]);
2233
2256
  function tagName(node) {
2234
2257
  const name = node.openingElement?.name;
2235
2258
  if (name?.type !== "JSXIdentifier") return void 0;
@@ -2237,7 +2260,12 @@ function tagName(node) {
2237
2260
  }
2238
2261
  function isInteractive(node) {
2239
2262
  const name = tagName(node);
2240
- return name !== void 0 && INTERACTIVE_TAGS.has(name);
2263
+ if (name === void 0 || !INTERACTIVE_TAGS.has(name)) return false;
2264
+ const attributes = node.openingElement?.attributes;
2265
+ if (!attributes) return false;
2266
+ return attributes.some(
2267
+ (attribute) => attribute.type === "JSXAttribute" && typeof attribute.name === "object" && "name" in attribute.name && typeof attribute.name.name === "string" && INTERACTIVE_ATTRIBUTES.has(attribute.name.name)
2268
+ );
2241
2269
  }
2242
2270
  function isComponentElement(node) {
2243
2271
  const name = tagName(node);
@@ -2248,6 +2276,63 @@ function isComponentReturn(node) {
2248
2276
  if (parent.type === "ReturnStatement") return true;
2249
2277
  return parent.type === "ArrowFunctionExpression" && parent.body === node;
2250
2278
  }
2279
+ function isJsxElementWithChildren(node) {
2280
+ return "children" in node && Array.isArray(node.children);
2281
+ }
2282
+ function isJsxElementChild(node) {
2283
+ return "openingElement" in node;
2284
+ }
2285
+ function decorativeTagName(node) {
2286
+ const name = node.openingElement.name;
2287
+ if (name && typeof name === "object" && "name" in name && typeof name.name === "string") return name.name;
2288
+ return void 0;
2289
+ }
2290
+ function isInteractiveChild(node) {
2291
+ const name = decorativeTagName(node);
2292
+ return name !== void 0 && INTERACTIVE_TAGS.has(name);
2293
+ }
2294
+ function isComponentChild(node) {
2295
+ const name = decorativeTagName(node);
2296
+ return name !== void 0 && /^[A-Z]/.test(name);
2297
+ }
2298
+ function isDecorative(node) {
2299
+ const name = decorativeTagName(node);
2300
+ if (name === void 0) return false;
2301
+ if (INTERACTIVE_TAGS.has(name)) return false;
2302
+ if (/^[A-Z]/.test(name)) return false;
2303
+ const children = node.children ?? [];
2304
+ const meaningfulText = children.some(
2305
+ (child) => child.type === "JSXText" && typeof child.value === "string" && child.value.trim().length > 0
2306
+ );
2307
+ return !meaningfulText && !isContentElement(name);
2308
+ }
2309
+ function isContentElement(name) {
2310
+ return /^(?:h[1-6]|p|li|dt|dd|blockquote|pre|code|figcaption|caption|th|td|form|fieldset|select|textarea)$/.test(name);
2311
+ }
2312
+ function isSoleContentOfWrapper(node) {
2313
+ const parent = node.parent;
2314
+ if (!isJsxElementChild(parent)) return false;
2315
+ let current = parent;
2316
+ while (current && isJsxElementWithChildren(current) && !isInteractiveChild(current) && !isComponentChild(current)) {
2317
+ const children = current.children ?? [];
2318
+ const siblings = children.filter(isJsxElementChild);
2319
+ const meaningful = siblings.filter((sibling) => !isDecorative(sibling));
2320
+ const textContent = children.some(
2321
+ (child) => child.type === "JSXText" && typeof child.value === "string" && child.value.trim().length > 0
2322
+ );
2323
+ const expressionContent = children.some((child) => {
2324
+ if (child.type !== "JSXExpressionContainer") return false;
2325
+ const expression = child.expression;
2326
+ return typeof expression === "object" && expression !== null && "type" in expression && expression.type !== "Literal";
2327
+ });
2328
+ if (meaningful.length <= 1 && !textContent && !expressionContent) {
2329
+ return true;
2330
+ }
2331
+ const nextParent = current.parent;
2332
+ current = nextParent !== void 0 && isJsxElementChild(nextParent) ? nextParent : void 0;
2333
+ }
2334
+ return false;
2335
+ }
2251
2336
  var interactiveComponentRule = {
2252
2337
  meta: {
2253
2338
  schema: [],
@@ -2258,6 +2343,9 @@ var interactiveComponentRule = {
2258
2343
  },
2259
2344
  create(context) {
2260
2345
  if (!context.filename.endsWith(".tsx") && !context.filename.endsWith(".jsx")) return {};
2346
+ const filename = path20.resolve(context.filename);
2347
+ const base = path20.basename(filename, path20.extname(filename));
2348
+ if (NEXT_ROUTING_FILES3.has(base)) return {};
2261
2349
  return {
2262
2350
  JSXElement(node) {
2263
2351
  if (!isInteractive(node)) return;
@@ -2270,6 +2358,9 @@ var interactiveComponentRule = {
2270
2358
  if (isComponentReturn(node)) {
2271
2359
  return;
2272
2360
  }
2361
+ if (isSoleContentOfWrapper(node)) {
2362
+ return;
2363
+ }
2273
2364
  const name = tagName(node);
2274
2365
  if (name === void 0) return;
2275
2366
  context.report({
@@ -2501,12 +2592,12 @@ var cvaBooleanVariantsRule = {
2501
2592
  };
2502
2593
 
2503
2594
  // eslint/rules/cross-feature-import.ts
2504
- import path20 from "path";
2595
+ import path21 from "path";
2505
2596
  var FEATURES_SEGMENT = "features";
2506
2597
  function featureNameOf(resolvedPath, sourceRoot) {
2507
- const relative = path20.relative(sourceRoot, resolvedPath);
2598
+ const relative = path21.relative(sourceRoot, resolvedPath);
2508
2599
  if (relative.startsWith("..")) return void 0;
2509
- const segments = relative.split(path20.sep);
2600
+ const segments = relative.split(path21.sep);
2510
2601
  if (segments[0] !== FEATURES_SEGMENT || segments.length < 2) return void 0;
2511
2602
  return segments[1];
2512
2603
  }
@@ -2522,9 +2613,9 @@ var crossFeatureImportRule = {
2522
2613
  const filename = context.filename;
2523
2614
  if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
2524
2615
  const sourceRoot = sourceRootOf(context);
2525
- const fileRelative = path20.relative(sourceRoot, filename);
2616
+ const fileRelative = path21.relative(sourceRoot, filename);
2526
2617
  if (fileRelative.startsWith("..")) return {};
2527
- const fileSegments = fileRelative.split(path20.sep);
2618
+ const fileSegments = fileRelative.split(path21.sep);
2528
2619
  const isInCompositions = fileSegments[0] === "compositions";
2529
2620
  const isInApp = fileSegments[0] === "app";
2530
2621
  const isConfig = fileSegments[0] === "config";
@@ -2538,9 +2629,9 @@ var crossFeatureImportRule = {
2538
2629
  if (typeof source.value !== "string") return;
2539
2630
  let resolved;
2540
2631
  if (source.value.startsWith("@/")) {
2541
- resolved = path20.resolve(sourceRoot, source.value.slice(2));
2632
+ resolved = path21.resolve(sourceRoot, source.value.slice(2));
2542
2633
  } else if (source.value.startsWith(".")) {
2543
- resolved = path20.resolve(path20.dirname(filename), source.value);
2634
+ resolved = path21.resolve(path21.dirname(filename), source.value);
2544
2635
  }
2545
2636
  if (!resolved) return;
2546
2637
  const feature = featureNameOf(resolved, sourceRoot);
@@ -2559,7 +2650,7 @@ var crossFeatureImportRule = {
2559
2650
  };
2560
2651
 
2561
2652
  // eslint/rules/pure-function-extract.ts
2562
- import path21 from "path";
2653
+ import path22 from "path";
2563
2654
  function isComponentLikeName(name) {
2564
2655
  return /^[A-Z]/.test(name);
2565
2656
  }
@@ -2588,9 +2679,9 @@ var pureFunctionExtractRule = {
2588
2679
  const filename = context.filename;
2589
2680
  if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
2590
2681
  const sourceRoot = sourceRootOf(context);
2591
- const relative = path21.relative(sourceRoot, filename);
2682
+ const relative = path22.relative(sourceRoot, filename);
2592
2683
  if (relative.startsWith("..")) return {};
2593
- const segments = relative.split(path21.sep);
2684
+ const segments = relative.split(path22.sep);
2594
2685
  if (segments[0] === "utils") return {};
2595
2686
  if (segments[0] === "app") return {};
2596
2687
  const supportFolders = /* @__PURE__ */ new Set(["hooks", "types", "schemas", "constants", "utils"]);
@@ -2630,7 +2721,7 @@ var pureFunctionExtractRule = {
2630
2721
  };
2631
2722
 
2632
2723
  // eslint/rules/hook-complexity.ts
2633
- import path22 from "path";
2724
+ import path23 from "path";
2634
2725
  import ts4 from "typescript";
2635
2726
  var REACT_HOOKS = /* @__PURE__ */ new Set([
2636
2727
  "useState",
@@ -2683,9 +2774,9 @@ var hookComplexityRule = {
2683
2774
  create(context) {
2684
2775
  const filename = context.filename;
2685
2776
  const sourceRoot = sourceRootOf(context);
2686
- const relative = path22.relative(sourceRoot, filename);
2777
+ const relative = path23.relative(sourceRoot, filename);
2687
2778
  if (relative.startsWith("..")) return {};
2688
- const segments = relative.split(path22.sep);
2779
+ const segments = relative.split(path23.sep);
2689
2780
  const sourceText = context.sourceCode.text;
2690
2781
  function checkHook(node, name, body, exported) {
2691
2782
  if (!exported) return;
@@ -2727,9 +2818,9 @@ var hookComplexityRule = {
2727
2818
  };
2728
2819
 
2729
2820
  // eslint/rules/locale-dotted-path.ts
2730
- import path23 from "path";
2821
+ import path24 from "path";
2731
2822
  function isInLocalesDir(filename) {
2732
- const segments = path23.resolve(filename).split(path23.sep);
2823
+ const segments = path24.resolve(filename).split(path24.sep);
2733
2824
  const srcIdx = segments.lastIndexOf("src");
2734
2825
  return srcIdx !== -1 && segments[srcIdx + 1] === "locales";
2735
2826
  }
@@ -2778,9 +2869,9 @@ var localeDottedPathRule = {
2778
2869
  };
2779
2870
 
2780
2871
  // eslint/rules/locales-location.ts
2781
- import path24 from "path";
2872
+ import path25 from "path";
2782
2873
  function isLocalesFile(filename) {
2783
- const segments = path24.resolve(filename).split(path24.sep);
2874
+ const segments = path25.resolve(filename).split(path25.sep);
2784
2875
  const srcIdx = segments.lastIndexOf("src");
2785
2876
  return srcIdx !== -1 && segments[srcIdx + 1] === "locales";
2786
2877
  }
@@ -2799,7 +2890,7 @@ var localesLocationRule = {
2799
2890
  create(context) {
2800
2891
  if (isLocalesFile(context.filename)) return {};
2801
2892
  const filename = context.filename;
2802
- const segments = path24.resolve(filename).split(path24.sep);
2893
+ const segments = path25.resolve(filename).split(path25.sep);
2803
2894
  const srcIdx = segments.lastIndexOf("src");
2804
2895
  if (srcIdx === -1) return {};
2805
2896
  const folder = segments[srcIdx + 1];
@@ -2821,7 +2912,7 @@ var localesLocationRule = {
2821
2912
  };
2822
2913
 
2823
2914
  // eslint/rules/hook-extraction.ts
2824
- import path25 from "path";
2915
+ import path26 from "path";
2825
2916
  var hookExtractionRule = {
2826
2917
  meta: {
2827
2918
  schema: [],
@@ -2832,7 +2923,7 @@ var hookExtractionRule = {
2832
2923
  },
2833
2924
  create(context) {
2834
2925
  const sourceRoot = sourceRootOf(context);
2835
- const file = path25.resolve(context.filename);
2926
+ const file = path26.resolve(context.filename);
2836
2927
  const segments = segmentsOf(file, sourceRoot);
2837
2928
  if (segments.length === 0) return {};
2838
2929
  const index = getProjectIndex(sourceRoot);
@@ -2858,7 +2949,7 @@ var hookExtractionRule = {
2858
2949
  };
2859
2950
 
2860
2951
  // eslint/rules/value-extraction.ts
2861
- import path26 from "path";
2952
+ import path27 from "path";
2862
2953
  var valueExtractionRule = {
2863
2954
  meta: {
2864
2955
  schema: [],
@@ -2869,7 +2960,7 @@ var valueExtractionRule = {
2869
2960
  },
2870
2961
  create(context) {
2871
2962
  const sourceRoot = sourceRootOf(context);
2872
- const file = path26.resolve(context.filename);
2963
+ const file = path27.resolve(context.filename);
2873
2964
  const segments = segmentsOf(file, sourceRoot);
2874
2965
  if (segments.length === 0 || segments[0] !== "app") return {};
2875
2966
  const index = getProjectIndex(sourceRoot);
@@ -2890,7 +2981,7 @@ var valueExtractionRule = {
2890
2981
  };
2891
2982
 
2892
2983
  // eslint/rules/config-extraction.ts
2893
- import path27 from "path";
2984
+ import path28 from "path";
2894
2985
  var configExtractionRule = {
2895
2986
  meta: {
2896
2987
  schema: [],
@@ -2901,7 +2992,7 @@ var configExtractionRule = {
2901
2992
  },
2902
2993
  create(context) {
2903
2994
  const sourceRoot = sourceRootOf(context);
2904
- const file = path27.resolve(context.filename);
2995
+ const file = path28.resolve(context.filename);
2905
2996
  const segments = segmentsOf(file, sourceRoot);
2906
2997
  if (segments.length < 3 || segments[0] !== "config") return {};
2907
2998
  if (SUPPORT_FOLDERS2.has(segments[2] ?? "")) return {};
@@ -2939,7 +3030,7 @@ var configExtractionRule = {
2939
3030
  };
2940
3031
 
2941
3032
  // eslint/rules/component-nesting.ts
2942
- import path28 from "path";
3033
+ import path29 from "path";
2943
3034
  var componentNestingRule = {
2944
3035
  meta: {
2945
3036
  schema: [],
@@ -2950,7 +3041,7 @@ var componentNestingRule = {
2950
3041
  },
2951
3042
  create(context) {
2952
3043
  const sourceRoot = sourceRootOf(context);
2953
- const file = path28.resolve(context.filename);
3044
+ const file = path29.resolve(context.filename);
2954
3045
  const segments = segmentsOf(file, sourceRoot);
2955
3046
  if (segments.length !== 4 || segments[0] !== "features") return {};
2956
3047
  const index = getProjectIndex(sourceRoot);
@@ -2983,7 +3074,7 @@ var componentNestingRule = {
2983
3074
  };
2984
3075
 
2985
3076
  // eslint/rules/stay-flat.ts
2986
- import path29 from "path";
3077
+ import path30 from "path";
2987
3078
  var stayFlatRule = {
2988
3079
  meta: {
2989
3080
  schema: [],
@@ -2994,7 +3085,7 @@ var stayFlatRule = {
2994
3085
  },
2995
3086
  create(context) {
2996
3087
  const sourceRoot = sourceRootOf(context);
2997
- const file = path29.resolve(context.filename);
3088
+ const file = path30.resolve(context.filename);
2998
3089
  const segments = segmentsOf(file, sourceRoot);
2999
3090
  if (segments.length !== 3 || segments[0] !== "features") return {};
3000
3091
  const index = getProjectIndex(sourceRoot);
@@ -3034,7 +3125,7 @@ var stayFlatRule = {
3034
3125
  };
3035
3126
 
3036
3127
  // eslint/rules/type-extraction.ts
3037
- import path30 from "path";
3128
+ import path31 from "path";
3038
3129
  var typeExtractionRule = {
3039
3130
  meta: {
3040
3131
  schema: [],
@@ -3045,7 +3136,7 @@ var typeExtractionRule = {
3045
3136
  },
3046
3137
  create(context) {
3047
3138
  const sourceRoot = sourceRootOf(context);
3048
- const file = path30.resolve(context.filename);
3139
+ const file = path31.resolve(context.filename);
3049
3140
  const segments = segmentsOf(file, sourceRoot);
3050
3141
  if (segments.length === 0) return {};
3051
3142
  const index = getProjectIndex(sourceRoot);
@@ -3091,7 +3182,7 @@ var typeExtractionRule = {
3091
3182
  };
3092
3183
 
3093
3184
  // eslint/rules/locale-placement.ts
3094
- import path31 from "path";
3185
+ import path32 from "path";
3095
3186
  import { readFileSync as readFileSync3 } from "fs";
3096
3187
  import ts5 from "typescript";
3097
3188
  var LOCALE_ACCESS = /\blocales\.(?<key>[A-Za-z_$][\w$]*)/g;
@@ -3139,7 +3230,7 @@ var localePlacementRule = {
3139
3230
  },
3140
3231
  create(context) {
3141
3232
  const sourceRoot = sourceRootOf(context);
3142
- const file = path31.resolve(context.filename);
3233
+ const file = path32.resolve(context.filename);
3143
3234
  const segments = segmentsOf(file, sourceRoot);
3144
3235
  if (segments.length === 0) return {};
3145
3236
  const index = getProjectIndex(sourceRoot);
@@ -3217,7 +3308,7 @@ var localePlacementRule = {
3217
3308
  };
3218
3309
 
3219
3310
  // eslint/rules/sole-state-owner.ts
3220
- import path32 from "path";
3311
+ import path33 from "path";
3221
3312
  import ts6 from "typescript";
3222
3313
  function findStateHooks(node) {
3223
3314
  const hooks = [];
@@ -3297,7 +3388,7 @@ var soleStateOwnerRule = {
3297
3388
  }
3298
3389
  },
3299
3390
  create(context) {
3300
- const filename = path32.resolve(context.filename);
3391
+ const filename = path33.resolve(context.filename);
3301
3392
  if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
3302
3393
  const text = context.sourceCode.text;
3303
3394
  const components = parseComponentInfo(text, filename);
@@ -3376,7 +3467,7 @@ function usesOutsideJsx(declaration, hook, children) {
3376
3467
  }
3377
3468
 
3378
3469
  // eslint/rules/locale-key-shape.ts
3379
- import path33 from "path";
3470
+ import path34 from "path";
3380
3471
  var MAX_KEY_LENGTH = 30;
3381
3472
  var ROLE_POSTFIXES = /* @__PURE__ */ new Set([
3382
3473
  "Button",
@@ -3426,7 +3517,7 @@ var ROLE_POSTFIXES = /* @__PURE__ */ new Set([
3426
3517
  var CAMEL_CASE = /^[a-z][a-zA-Z0-9]*$/;
3427
3518
  var ENGLISH = /^[A-Za-z0-9_]*$/;
3428
3519
  function isLocalesFile2(filename) {
3429
- const segments = path33.resolve(filename).split(path33.sep);
3520
+ const segments = path34.resolve(filename).split(path34.sep);
3430
3521
  const srcIdx = segments.lastIndexOf("src");
3431
3522
  return srcIdx !== -1 && segments[srcIdx + 1] === "locales";
3432
3523
  }
@@ -3497,7 +3588,7 @@ var localeKeyShapeRule = {
3497
3588
  };
3498
3589
 
3499
3590
  // eslint/rules/shared-style-dedup.ts
3500
- import path34 from "path";
3591
+ import path35 from "path";
3501
3592
  import { readFileSync as readFileSync4, statSync as statSync3 } from "fs";
3502
3593
  var CLASS_NAME = /className="(?<classes>[^"]+)"/g;
3503
3594
  var comboCache;
@@ -3539,7 +3630,7 @@ var sharedStyleDedupRule = {
3539
3630
  },
3540
3631
  create(context) {
3541
3632
  const sourceRoot = sourceRootOf(context);
3542
- const file = path34.resolve(context.filename);
3633
+ const file = path35.resolve(context.filename);
3543
3634
  const segments = segmentsOf(file, sourceRoot);
3544
3635
  if (segments.length === 0) return {};
3545
3636
  const index = getProjectIndex(sourceRoot);
@@ -3743,7 +3834,7 @@ var zodSchemaValidationRule = {
3743
3834
  };
3744
3835
 
3745
3836
  // eslint/rules/source-under-src.ts
3746
- import path35 from "path";
3837
+ import path36 from "path";
3747
3838
  var NON_SOURCE_ROOT_DIRS = /* @__PURE__ */ new Set([
3748
3839
  ".agents",
3749
3840
  ".cache",
@@ -3784,14 +3875,14 @@ var sourceUnderSrcRule = {
3784
3875
  }
3785
3876
  },
3786
3877
  create(context) {
3787
- const filename = path35.resolve(context.filename);
3878
+ const filename = path36.resolve(context.filename);
3788
3879
  if (!MODULE_EXTENSION.test(filename)) return {};
3789
- const relative = path35.relative(context.cwd, filename).replace(/\\/g, "/");
3880
+ const relative = path36.relative(context.cwd, filename).replace(/\\/g, "/");
3790
3881
  if (relative === "src" || relative.startsWith("src/")) return {};
3791
3882
  const topLevel = relative.split("/")[0] ?? "";
3792
3883
  if (NON_SOURCE_ROOT_DIRS.has(topLevel)) return {};
3793
3884
  if (!relative.includes("/")) {
3794
- const basename = path35.basename(filename);
3885
+ const basename = path36.basename(filename);
3795
3886
  if (CONFIG_FILE.test(basename) || DECLARATION_FILE.test(basename) || basename.startsWith(".")) return {};
3796
3887
  }
3797
3888
  return {
@@ -3808,7 +3899,7 @@ var sourceUnderSrcRule = {
3808
3899
 
3809
3900
  // eslint/rules/zirka-baseline.ts
3810
3901
  import fs5 from "fs";
3811
- import path36 from "path";
3902
+ import path37 from "path";
3812
3903
  var ESLINT_CONFIG = /^eslint\.config\.(?:ts|mts|cts|js|mjs|cjs)$/;
3813
3904
  var PRETTIER_CONFIGS = [
3814
3905
  "prettier.config.mjs",
@@ -3827,10 +3918,10 @@ var zirkaBaselineRule = {
3827
3918
  }
3828
3919
  },
3829
3920
  create(context) {
3830
- const filename = path36.resolve(context.filename);
3831
- const basename = path36.basename(filename);
3921
+ const filename = path37.resolve(context.filename);
3922
+ const basename = path37.basename(filename);
3832
3923
  if (!ESLINT_CONFIG.test(basename)) return {};
3833
- const projectRoot = path36.dirname(filename);
3924
+ const projectRoot = path37.dirname(filename);
3834
3925
  const report3 = (message) => {
3835
3926
  context.report({
3836
3927
  node: context.sourceCode.ast,
@@ -3845,7 +3936,7 @@ var zirkaBaselineRule = {
3845
3936
  'ESLint config must take its configuration from zirka (import { styleguide } from "zirka") instead of restating rules locally.'
3846
3937
  );
3847
3938
  }
3848
- const tsconfigPath = path36.join(projectRoot, "tsconfig.json");
3939
+ const tsconfigPath = path37.join(projectRoot, "tsconfig.json");
3849
3940
  if (!fs5.existsSync(tsconfigPath)) {
3850
3941
  report3('No tsconfig.json found. Create one extending the zirka TypeScript base config ("zirka/typescript").');
3851
3942
  } else {
@@ -3863,13 +3954,13 @@ var zirkaBaselineRule = {
3863
3954
  report3('tsconfig.json must extend the zirka TypeScript base config ("zirka/typescript").');
3864
3955
  }
3865
3956
  }
3866
- const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs5.existsSync(path36.join(projectRoot, name)));
3957
+ const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs5.existsSync(path37.join(projectRoot, name)));
3867
3958
  if (!prettierConfigFile) {
3868
3959
  report3(
3869
3960
  "No prettier config found. Create one that takes its configuration from zirka (styleguide({ prettier: true }).prettierConfig)."
3870
3961
  );
3871
3962
  } else {
3872
- const content = fs5.readFileSync(path36.join(projectRoot, prettierConfigFile), "utf8");
3963
+ const content = fs5.readFileSync(path37.join(projectRoot, prettierConfigFile), "utf8");
3873
3964
  if (!content.includes("zirka")) {
3874
3965
  report3(
3875
3966
  "The prettier config must take its configuration from zirka (styleguide({ prettier: true }).prettierConfig) instead of restating it locally."
@@ -3939,7 +4030,7 @@ var docKindSuffixRule = {
3939
4030
  };
3940
4031
 
3941
4032
  // eslint/rules/documentation/title-matches-file-name.ts
3942
- import path37 from "path";
4033
+ import path38 from "path";
3943
4034
  function toExpectedFileName(title) {
3944
4035
  return `${title.toLowerCase().replaceAll(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "")}.md`;
3945
4036
  }
@@ -3959,7 +4050,7 @@ var titleMatchesFileNameRule = {
3959
4050
  if (!filename.endsWith(".md")) return;
3960
4051
  const title = getTextContent(node).trim();
3961
4052
  const expectedFileName = toExpectedFileName(title);
3962
- const actualFileName = path37.basename(filename);
4053
+ const actualFileName = path38.basename(filename);
3963
4054
  if (!title) {
3964
4055
  context.report({
3965
4056
  node,
@@ -4366,7 +4457,7 @@ var referenceBlockHeadingsRule = {
4366
4457
  };
4367
4458
 
4368
4459
  // eslint/rules/documentation/support-document-placement.ts
4369
- import path38 from "path";
4460
+ import path39 from "path";
4370
4461
  var supportDocumentPlacementRule = {
4371
4462
  meta: {
4372
4463
  type: "problem",
@@ -4380,7 +4471,7 @@ var supportDocumentPlacementRule = {
4380
4471
  root(node) {
4381
4472
  const filename = getFilename(context);
4382
4473
  if (!filename.endsWith(".md")) return;
4383
- const parentFolder = path38.basename(path38.dirname(filename));
4474
+ const parentFolder = path39.basename(path39.dirname(filename));
4384
4475
  if (filename.endsWith("-rule.md") && parentFolder !== "rules") {
4385
4476
  context.report({
4386
4477
  node,
@@ -4423,11 +4514,11 @@ var noTemplatePromptRule = {
4423
4514
  };
4424
4515
 
4425
4516
  // eslint/rules/documentation/guide-folder-entry-point.ts
4426
- import path40 from "path";
4517
+ import path41 from "path";
4427
4518
 
4428
4519
  // eslint/rules/documentation/project-index.ts
4429
4520
  import { readdirSync as readdirSync3, readFileSync as readFileSync5, statSync as statSync4 } from "fs";
4430
- import path39 from "path";
4521
+ import path40 from "path";
4431
4522
  var KIND_BY_SUFFIX = [
4432
4523
  ["-rule.md", "rule"],
4433
4524
  ["-guide.md", "guide"],
@@ -4436,7 +4527,7 @@ var KIND_BY_SUFFIX = [
4436
4527
  ];
4437
4528
  function listMarkdownFiles(dir) {
4438
4529
  return readdirSync3(dir).flatMap((entry) => {
4439
- const entryPath = path39.join(dir, entry);
4530
+ const entryPath = path40.join(dir, entry);
4440
4531
  if (statSync4(entryPath).isDirectory()) {
4441
4532
  return entry.startsWith("_") ? [] : listMarkdownFiles(entryPath);
4442
4533
  }
@@ -4454,11 +4545,11 @@ function getProjectDocs(docsRoot) {
4454
4545
  if (cached) return cached;
4455
4546
  const files = listMarkdownFiles(docsRoot);
4456
4547
  const docs = files.sort((a, b) => a.localeCompare(b)).map((filePath) => {
4457
- const fileName = path39.basename(filePath);
4548
+ const fileName = path40.basename(filePath);
4458
4549
  const kind = KIND_BY_SUFFIX.find(([suffix]) => fileName.endsWith(suffix))?.[1];
4459
4550
  return {
4460
4551
  filePath,
4461
- doc: path39.relative(docsRoot, filePath).split(path39.sep).join("/"),
4552
+ doc: path40.relative(docsRoot, filePath).split(path40.sep).join("/"),
4462
4553
  fileName,
4463
4554
  kind,
4464
4555
  title: extractTitle(filePath)
@@ -4468,12 +4559,12 @@ function getProjectDocs(docsRoot) {
4468
4559
  return docs;
4469
4560
  }
4470
4561
  function findDocsRoot(filePath) {
4471
- let dir = path39.dirname(filePath);
4562
+ let dir = path40.dirname(filePath);
4472
4563
  for (; ; ) {
4473
- if (path39.basename(dir) === "docs" && statSync4(dir).isDirectory()) {
4564
+ if (path40.basename(dir) === "docs" && statSync4(dir).isDirectory()) {
4474
4565
  return dir;
4475
4566
  }
4476
- const parent = path39.dirname(dir);
4567
+ const parent = path40.dirname(dir);
4477
4568
  if (parent === dir) return void 0;
4478
4569
  dir = parent;
4479
4570
  }
@@ -4497,13 +4588,13 @@ var guideFolderEntryPointRule = {
4497
4588
  if (!docsRoot) return;
4498
4589
  const docs = getProjectDocs(docsRoot);
4499
4590
  const guideFolders = new Set(
4500
- docs.filter((doc) => ["rules", "references"].includes(path40.basename(path40.dirname(doc.filePath)))).map((doc) => path40.dirname(path40.dirname(doc.filePath))).filter((folder) => path40.resolve(folder) !== path40.resolve(docsRoot))
4591
+ docs.filter((doc) => ["rules", "references"].includes(path41.basename(path41.dirname(doc.filePath)))).map((doc) => path41.dirname(path41.dirname(doc.filePath))).filter((folder) => path41.resolve(folder) !== path41.resolve(docsRoot))
4501
4592
  );
4502
- const currentDir = path40.dirname(filename);
4593
+ const currentDir = path41.dirname(filename);
4503
4594
  if (guideFolders.has(currentDir)) {
4504
- const expectedEntryPoint = `${path40.basename(currentDir)}.md`;
4595
+ const expectedEntryPoint = `${path41.basename(currentDir)}.md`;
4505
4596
  const hasEntryPoint = docs.some(
4506
- (doc) => doc.kind === "guide" && path40.dirname(doc.filePath) === currentDir && doc.fileName === expectedEntryPoint
4597
+ (doc) => doc.kind === "guide" && path41.dirname(doc.filePath) === currentDir && doc.fileName === expectedEntryPoint
4507
4598
  );
4508
4599
  if (!hasEntryPoint) {
4509
4600
  context.report({
@@ -4728,7 +4819,7 @@ var noNestedHowToRule = {
4728
4819
 
4729
4820
  // eslint/rules/documentation/glossary-term-linking.ts
4730
4821
  import { readFileSync as readFileSync6 } from "fs";
4731
- import path41 from "path";
4822
+ import path42 from "path";
4732
4823
  function extractGlossaryTerms(filePath) {
4733
4824
  const content = readFileSync6(filePath, "utf8");
4734
4825
  const terms = [];
@@ -4782,9 +4873,9 @@ var glossaryTermLinkingRule = {
4782
4873
  const docsRoot = findDocsRoot(filename);
4783
4874
  if (!docsRoot) return;
4784
4875
  const docs = getProjectDocs(docsRoot);
4785
- const guideDir = path41.dirname(filename);
4876
+ const guideDir = path42.dirname(filename);
4786
4877
  const guideReferences = docs.filter(
4787
- (doc) => doc.kind === "reference" && path41.dirname(doc.filePath) === guideDir
4878
+ (doc) => doc.kind === "reference" && path42.dirname(doc.filePath) === guideDir
4788
4879
  );
4789
4880
  if (guideReferences.length === 0) return;
4790
4881
  const glossaryTerms = [];
@@ -4809,7 +4900,7 @@ var glossaryTermLinkingRule = {
4809
4900
 
4810
4901
  // eslint/rules/documentation/guide-mentions-documents.ts
4811
4902
  import { existsSync } from "fs";
4812
- import path42 from "path";
4903
+ import path43 from "path";
4813
4904
  function visitSteps3(node, check) {
4814
4905
  if (node.type === "list" && node.ordered) {
4815
4906
  for (const child of node.children) check(child);
@@ -4842,12 +4933,12 @@ var guideMentionsDocumentsRule = {
4842
4933
  if (!filename.endsWith("-guide.md")) return;
4843
4934
  const docsRoot = findDocsRoot(filename);
4844
4935
  if (!docsRoot) return;
4845
- const guideDir = path42.dirname(filename);
4846
- if (path42.basename(filename, ".md") !== path42.basename(guideDir)) return;
4936
+ const guideDir = path43.dirname(filename);
4937
+ if (path43.basename(filename, ".md") !== path43.basename(guideDir)) return;
4847
4938
  const docs = getProjectDocs(docsRoot);
4848
4939
  const owned = docs.filter((doc) => {
4849
- const parent = path42.dirname(doc.filePath);
4850
- return parent === path42.join(guideDir, "rules") || parent === path42.join(guideDir, "references");
4940
+ const parent = path43.dirname(doc.filePath);
4941
+ return parent === path43.join(guideDir, "rules") || parent === path43.join(guideDir, "references");
4851
4942
  });
4852
4943
  const allLinks = [];
4853
4944
  collectMarkdownLinks(node, allLinks);
@@ -4874,7 +4965,7 @@ var guideMentionsDocumentsRule = {
4874
4965
  for (const link of allLinks) {
4875
4966
  const target = linkTarget(link.url);
4876
4967
  if (!target.endsWith(".md")) continue;
4877
- const resolved = path42.normalize(path42.join(guideDir, target));
4968
+ const resolved = path43.normalize(path43.join(guideDir, target));
4878
4969
  if (!existsSync(resolved)) {
4879
4970
  context.report({
4880
4971
  node: link,
@@ -5326,11 +5417,11 @@ var themeVariableNamespaceRule = {
5326
5417
 
5327
5418
  // eslint/rules/tailwind/css-entry-point.ts
5328
5419
  import { statSync as statSync6 } from "fs";
5329
- import path45 from "path";
5420
+ import path46 from "path";
5330
5421
 
5331
5422
  // eslint/rules/tailwind/source-files.ts
5332
5423
  import { readdirSync as readdirSync4, readFileSync as readFileSync7, statSync as statSync5 } from "fs";
5333
- import path43 from "path";
5424
+ import path44 from "path";
5334
5425
  var CSS_EXTENSIONS = [".css"];
5335
5426
  var MODULE_EXTENSIONS3 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
5336
5427
  var SOURCE_EXTENSIONS = [...MODULE_EXTENSIONS3, ...CSS_EXTENSIONS];
@@ -5343,7 +5434,7 @@ function findFiles(dir, extensions) {
5343
5434
  }
5344
5435
  return entries.flatMap((entry) => {
5345
5436
  if (entry.startsWith(".") || entry === "node_modules") return [];
5346
- const entryPath = path43.join(dir, entry);
5437
+ const entryPath = path44.join(dir, entry);
5347
5438
  let stats;
5348
5439
  try {
5349
5440
  stats = statSync5(entryPath);
@@ -5351,7 +5442,7 @@ function findFiles(dir, extensions) {
5351
5442
  return [];
5352
5443
  }
5353
5444
  if (stats.isDirectory()) return findFiles(entryPath, extensions);
5354
- return extensions.includes(path43.extname(entry)) ? [entryPath] : [];
5445
+ return extensions.includes(path44.extname(entry)) ? [entryPath] : [];
5355
5446
  });
5356
5447
  }
5357
5448
  function cachedTextReader() {
@@ -5374,7 +5465,7 @@ function escapeRegExp(text) {
5374
5465
  }
5375
5466
 
5376
5467
  // eslint/rules/tailwind/stylesheet-graph.ts
5377
- import path44 from "path";
5468
+ import path45 from "path";
5378
5469
  function registersTailwind(text) {
5379
5470
  return /@import\s+(?:url\(\s*)?["']tailwindcss["']\s*\)?/i.test(text);
5380
5471
  }
@@ -5388,25 +5479,25 @@ function moduleImports(text, fileName) {
5388
5479
  return new RegExp(`(?:import|require)\\s*\\(?\\s*["'][^"']*${escaped}["']`, "i").test(text);
5389
5480
  }
5390
5481
  function resolveSpecifier2(fromFile, spec, sourceRoot) {
5391
- if (spec.startsWith("/")) return path44.resolve(spec);
5392
- if (spec.startsWith("./") || spec.startsWith("../")) return path44.resolve(path44.dirname(fromFile), spec);
5393
- if (spec.startsWith("@/")) return path44.resolve(sourceRoot, spec.slice(2));
5482
+ if (spec.startsWith("/")) return path45.resolve(spec);
5483
+ if (spec.startsWith("./") || spec.startsWith("../")) return path45.resolve(path45.dirname(fromFile), spec);
5484
+ if (spec.startsWith("@/")) return path45.resolve(sourceRoot, spec.slice(2));
5394
5485
  return void 0;
5395
5486
  }
5396
5487
  function buildStylesheetGraph(options) {
5397
5488
  const { cssFiles, sourceRoot, textOf } = options;
5398
- const cssSet = new Set(cssFiles.map((file) => path44.normalize(file)));
5489
+ const cssSet = new Set(cssFiles.map((file) => path45.normalize(file)));
5399
5490
  const globals = cssFiles.filter((file) => registersTailwind(textOf(file)));
5400
5491
  const reachable = /* @__PURE__ */ new Set();
5401
5492
  const queue = [...globals];
5402
- for (const global of globals) reachable.add(path44.normalize(global));
5493
+ for (const global of globals) reachable.add(path45.normalize(global));
5403
5494
  while (queue.length > 0) {
5404
5495
  const from = queue.shift();
5405
5496
  if (!from) continue;
5406
5497
  for (const spec of importedSpecifiers(textOf(from))) {
5407
5498
  const target = resolveSpecifier2(from, spec, sourceRoot);
5408
5499
  if (!target) continue;
5409
- const normalized = path44.normalize(target);
5500
+ const normalized = path45.normalize(target);
5410
5501
  if (cssSet.has(normalized) && !reachable.has(normalized)) {
5411
5502
  reachable.add(normalized);
5412
5503
  queue.push(normalized);
@@ -5418,7 +5509,7 @@ function buildStylesheetGraph(options) {
5418
5509
  for (const spec of importedSpecifiers(textOf(global))) {
5419
5510
  const target = resolveSpecifier2(global, spec, sourceRoot);
5420
5511
  if (!target) continue;
5421
- const normalized = path44.normalize(target);
5512
+ const normalized = path45.normalize(target);
5422
5513
  if (cssSet.has(normalized)) directChildren.add(normalized);
5423
5514
  }
5424
5515
  }
@@ -5451,7 +5542,7 @@ var cssEntryPointRule = {
5451
5542
  return {
5452
5543
  "StyleSheet:exit"(node) {
5453
5544
  if (globals.length === 0) return;
5454
- const current = path45.normalize(path45.resolve(context.filename));
5545
+ const current = path46.normalize(path46.resolve(context.filename));
5455
5546
  if (globals.includes(current)) {
5456
5547
  if (globals.length > 1) {
5457
5548
  context.report({
@@ -5460,7 +5551,7 @@ var cssEntryPointRule = {
5460
5551
  });
5461
5552
  return;
5462
5553
  }
5463
- const basename = path45.basename(current);
5554
+ const basename = path46.basename(current);
5464
5555
  const importCount = moduleFiles.filter((modulePath) => moduleImports(textOf(modulePath), basename)).length;
5465
5556
  if (importCount !== 1) {
5466
5557
  context.report({
@@ -5729,7 +5820,7 @@ var nextjsPackageJsonRules = {
5729
5820
 
5730
5821
  // eslint/rules/husky/husky-hook.ts
5731
5822
  import { existsSync as existsSync2, readFileSync as readFileSync8 } from "fs";
5732
- import path46 from "path";
5823
+ import path47 from "path";
5733
5824
  function memberName4(member) {
5734
5825
  return member.name.type === "String" ? member.name.value : member.name.name;
5735
5826
  }
@@ -5748,7 +5839,7 @@ var huskyHookRule = {
5748
5839
  if (root.type !== "Object") return;
5749
5840
  const scriptName = context.filename;
5750
5841
  if (!scriptName.endsWith("package.json")) return;
5751
- const hookPath = path46.join(context.cwd, ".husky", "pre-commit");
5842
+ const hookPath = path47.join(context.cwd, ".husky", "pre-commit");
5752
5843
  if (!existsSync2(hookPath)) {
5753
5844
  context.report({
5754
5845
  node,
@@ -5788,7 +5879,7 @@ var huskyRules = {
5788
5879
 
5789
5880
  // eslint/rules/vulyk/vulyk-docs.ts
5790
5881
  import { existsSync as existsSync3, readFileSync as readFileSync9 } from "fs";
5791
- import path47 from "path";
5882
+ import path48 from "path";
5792
5883
  var PASIKA_REPO = "Bredansky/pasika";
5793
5884
  var BASE_REQUIRED_DOCS = [
5794
5885
  { name: "documentation-guide", path: "docs/documentation-guide" },
@@ -5821,8 +5912,8 @@ var vulykDocsRule = {
5821
5912
  if (!context.filename.endsWith("package.json")) return;
5822
5913
  const root = node.body;
5823
5914
  if (root.type !== "Object") return;
5824
- const projectRoot = path47.dirname(path47.resolve(context.filename));
5825
- const configPath = path47.join(projectRoot, "vulyk.config.ts");
5915
+ const projectRoot = path48.dirname(path48.resolve(context.filename));
5916
+ const configPath = path48.join(projectRoot, "vulyk.config.ts");
5826
5917
  if (!existsSync3(configPath)) {
5827
5918
  context.report({
5828
5919
  node,
@@ -5847,7 +5938,7 @@ var vulykDocsRule = {
5847
5938
  });
5848
5939
  }
5849
5940
  }
5850
- const agentsPath = path47.join(projectRoot, "AGENTS.md");
5941
+ const agentsPath = path48.join(projectRoot, "AGENTS.md");
5851
5942
  if (!existsSync3(agentsPath)) {
5852
5943
  context.report({
5853
5944
  node,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pasika",
3
- "version": "0.5.9",
3
+ "version": "0.5.11",
4
4
  "description": "Reusable agent setup package",
5
5
  "repository": {
6
6
  "type": "git",