pasika 0.10.118 → 0.10.120

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.
@@ -128,6 +128,7 @@ declare const tailwindRules: {
128
128
  "stylesheet-ordering": _eslint_css.CSSRuleDefinition;
129
129
  "custom-utility-apply": _eslint_css.CSSRuleDefinition;
130
130
  "utility-mapping": _eslint_css.CSSRuleDefinition;
131
+ "utility-name-parity": _eslint_css.CSSRuleDefinition;
131
132
  "css-entry-point": _eslint_css.CSSRuleDefinition;
132
133
  "feature-css-placement": _eslint_css.CSSRuleDefinition;
133
134
  "global-stylesheet": _eslint_css.CSSRuleDefinition;
@@ -168,6 +169,7 @@ declare const pasikaPlugin: {
168
169
  "stylesheet-ordering": _eslint_css.CSSRuleDefinition;
169
170
  "custom-utility-apply": _eslint_css.CSSRuleDefinition;
170
171
  "utility-mapping": _eslint_css.CSSRuleDefinition;
172
+ "utility-name-parity": _eslint_css.CSSRuleDefinition;
171
173
  "css-entry-point": _eslint_css.CSSRuleDefinition;
172
174
  "feature-css-placement": _eslint_css.CSSRuleDefinition;
173
175
  "global-stylesheet": _eslint_css.CSSRuleDefinition;
@@ -11200,30 +11200,29 @@ function themeCandidate(name, utilityText) {
11200
11200
  const property = arbitrary?.groups?.property ?? direct?.groups?.property;
11201
11201
  const matched = themeOperations.find((operation) => {
11202
11202
  if (property) return property === operation.property;
11203
- if (!name.startsWith(`${operation.prefix}-`) || name.length <= operation.prefix.length + 1) return false;
11204
11203
  if (typed?.groups?.kind !== operation.prefix) return false;
11205
11204
  const hint = typed.groups.hint;
11206
11205
  if (operation.prefix === "text") return hint === (operation.property === "font-size" ? "length:" : "color:");
11207
11206
  if (operation.prefix === "font") {
11208
11207
  return hint === (operation.property === "font-family" ? "family-name:" : "number:");
11209
11208
  }
11209
+ if (operation.prefix === "bg") {
11210
+ return hint === (operation.property === "background-image" ? "image:" : "color:");
11211
+ }
11212
+ if (["border", "outline", "decoration", "stroke"].includes(operation.prefix)) return hint === "color:";
11210
11213
  return hint === void 0;
11211
11214
  });
11212
11215
  if (!matched) return void 0;
11213
11216
  const value = arbitrary?.groups?.value?.trim() ?? direct?.groups?.value?.trim() ?? (typed?.groups?.variable ? `var(${typed.groups.variable})` : void 0);
11214
11217
  if (!value) return void 0;
11215
- const simple = /^-?(?:\d+(?:\.\d+)?|\.\d+)(?:px|rem|em|%|vh|vw|ch|deg)?$/u.test(value);
11216
- const variable = /^var\(--[a-z][a-z0-9-]*\)$/u.test(value);
11217
- const color = /^#[\da-f]{3,8}$/iu.test(value);
11218
- const keyword = /^[a-z][a-z-]*$/u.test(value);
11219
- const ratio = /^\d+\/\d+$/u.test(value);
11220
- if (!simple && !variable && !color && !keyword && !ratio) return void 0;
11221
- if (matched.property === "font-size" && value.startsWith("-")) return void 0;
11218
+ if (arbitrary && (/\\|["']|\burl\(/iu.test(value) || /var\(--[^)]*_/iu.test(value))) return void 0;
11219
+ const cssValue = arbitrary ? value.replaceAll("_", " ") : value;
11220
+ if (matched.property === "font-size" && cssValue.startsWith("-")) return void 0;
11222
11221
  const stem = name.startsWith(`${matched.prefix}-`) ? name.slice(matched.prefix.length + 1) : void 0;
11223
11222
  return {
11224
11223
  token: stem ? `--${matched.namespace}-${stem}` : "",
11225
11224
  property: matched.property,
11226
- value,
11225
+ value: cssValue,
11227
11226
  prefix: matched.prefix,
11228
11227
  namespace: matched.namespace
11229
11228
  };
@@ -11426,7 +11425,23 @@ var utilityMappingRule = {
11426
11425
  }
11427
11426
  for (const utility of utilities) {
11428
11427
  const name = preludeIdentifiers(utility)[0] ?? "unknown";
11429
- const candidate = themeCandidate(name, context.sourceCode.getText(utility));
11428
+ const source = context.sourceCode.getText(utility);
11429
+ const zIndex = /^@utility\s+[\w-]+\s*\{\s*@apply\s+\[z-index:(?<value>-?\d+|auto)\];?\s*\}$/u.exec(source)?.groups?.value;
11430
+ const numericZIndex = zIndex && zIndex !== "auto" ? Number(zIndex) : void 0;
11431
+ let nativeClass;
11432
+ if (zIndex === "auto") {
11433
+ nativeClass = "z-auto";
11434
+ } else if (numericZIndex !== void 0 && Number.isSafeInteger(numericZIndex)) {
11435
+ nativeClass = numericZIndex < 0 ? `-z-${String(-numericZIndex)}` : `z-${String(numericZIndex)}`;
11436
+ }
11437
+ if (nativeClass && zIndex) {
11438
+ context.report({
11439
+ node: utility,
11440
+ message: `Custom utility "${name}" duplicates built-in "${nativeClass}" (z-index: ${zIndex}); use "${nativeClass}" directly.`
11441
+ });
11442
+ continue;
11443
+ }
11444
+ const candidate = themeCandidate(name, source);
11430
11445
  const equivalent = candidate ? matchingThemeToken(candidate) : void 0;
11431
11446
  if (candidate && equivalent && nameCounts.get(name) === 1) {
11432
11447
  context.report({
@@ -11443,7 +11458,14 @@ var utilityMappingRule = {
11443
11458
  });
11444
11459
  continue;
11445
11460
  }
11446
- if (nameCounts.get(name) !== 1 || !candidate?.token) continue;
11461
+ if (nameCounts.get(name) !== 1 || !candidate) continue;
11462
+ if (!candidate.token) {
11463
+ context.report({
11464
+ node: utility,
11465
+ message: `Custom utility "${name}" only maps ${candidate.property} (${candidate.value}); define an @theme token in the "--${candidate.namespace}-*" namespace and use its generated "${candidate.prefix}-*" class instead.`
11466
+ });
11467
+ continue;
11468
+ }
11447
11469
  const tokenAlreadyDefined = themeTokens.has(candidate.token) || projectTokens.some((token) => token.name === candidate.token);
11448
11470
  if (tokenAlreadyDefined) continue;
11449
11471
  if (candidate.property === "font-size" && themeTokens.has(`--color-${name.slice(5)}`)) continue;
@@ -11505,6 +11527,188 @@ var utilityMappingRule = {
11505
11527
  }
11506
11528
  };
11507
11529
 
11530
+ // eslint/rules/tailwind/utility-name-parity.ts
11531
+ import { spawnSync } from "child_process";
11532
+ import { createHash } from "crypto";
11533
+ import { existsSync as existsSync12 } from "fs";
11534
+ import path78 from "path";
11535
+ import { generate as generate4, parse as parse7, toPlainObject as toPlainObject3 } from "@eslint/css-tree";
11536
+ function numericPart(value) {
11537
+ const match = /^(?<negative>-?)(?<number>(?:\d+(?:\.\d+)?|\.\d+))(?<unit>%|px|rem|em|vw|vh|dvw|dvh|ch|fr|s|ms|deg|turn)?$/u.exec(
11538
+ value
11539
+ );
11540
+ if (!match?.groups?.number) return void 0;
11541
+ const number = String(Number(match.groups.number)).replace(".", "p");
11542
+ const sign = match.groups.negative === "-" ? "neg-" : "";
11543
+ return sign + number + (match.groups.unit === "%" ? "pct" : match.groups.unit ?? "");
11544
+ }
11545
+ function readableValue(value) {
11546
+ const words = value.trim().replace(/,/gu, "_comma_").split(/[_\s]+/u).filter(Boolean);
11547
+ if (words.length === 0 || words.length > 8) return void 0;
11548
+ const parts = [];
11549
+ for (const word of words) {
11550
+ const numeric = numericPart(word);
11551
+ if (numeric) {
11552
+ parts.push(numeric);
11553
+ continue;
11554
+ }
11555
+ const hex = /^#(?<color>[\da-f]{3,4}|[\da-f]{6}|[\da-f]{8})$/iu.exec(word)?.groups?.color;
11556
+ if (hex) {
11557
+ parts.push("hex", hex.toLowerCase());
11558
+ continue;
11559
+ }
11560
+ const variable = /^var\(--(?<name>[a-z][a-z0-9-]*)\)$/u.exec(word)?.groups?.name;
11561
+ if (variable) {
11562
+ parts.push("var", variable);
11563
+ continue;
11564
+ }
11565
+ if (/^[a-z][a-z0-9-]*$/iu.test(word)) {
11566
+ parts.push(word.toLowerCase());
11567
+ continue;
11568
+ }
11569
+ return void 0;
11570
+ }
11571
+ const slug = parts.join("-");
11572
+ return slug.length <= 70 ? slug : void 0;
11573
+ }
11574
+ function compoundValue(value) {
11575
+ const readable = readableValue(value);
11576
+ if (readable) return readable;
11577
+ const candidate = /^(?<fn>[a-z][a-z0-9-]*)\(/iu.exec(value.trim())?.groups?.fn?.toLowerCase();
11578
+ const hint = candidate?.endsWith("-") ? void 0 : candidate;
11579
+ const digest = createHash("sha256").update(value.trim()).digest("hex").slice(0, 12);
11580
+ return [hint, "hash", digest].filter(Boolean).join("-");
11581
+ }
11582
+ var TAILWIND_WORKER = String.raw`
11583
+ import { readFileSync } from "node:fs";
11584
+ import { compile } from "tailwindcss";
11585
+ const applies = JSON.parse(readFileSync(0, "utf8"));
11586
+ const results = [];
11587
+ for (const [index, apply] of applies.entries()) {
11588
+ const name = "pasika-probe-" + index;
11589
+ try {
11590
+ const compiler = await compile("@tailwind utilities; @utility " + name + " { " + apply + " }");
11591
+ results.push({ css: compiler.build([name]) });
11592
+ } catch (error) {
11593
+ results.push({ error: String(error instanceof Error ? error.message : error) });
11594
+ }
11595
+ }
11596
+ process.stdout.write(JSON.stringify(results));
11597
+ `;
11598
+ var compilerCache = /* @__PURE__ */ new Map();
11599
+ function isCompiledResult(value) {
11600
+ if (typeof value !== "object" || value === null) return false;
11601
+ return "css" in value && typeof value.css === "string" || "error" in value && typeof value.error === "string";
11602
+ }
11603
+ function compileApplies(applies, cwd) {
11604
+ const key = `${cwd}\0${JSON.stringify(applies)}`;
11605
+ const cached = compilerCache.get(key);
11606
+ if (cached) return cached;
11607
+ const child = spawnSync(process.execPath, ["--input-type=module", "--eval", TAILWIND_WORKER], {
11608
+ cwd,
11609
+ input: JSON.stringify(applies),
11610
+ encoding: "utf8",
11611
+ timeout: 3e4,
11612
+ maxBuffer: 8 * 1024 * 1024,
11613
+ windowsHide: true
11614
+ });
11615
+ let results;
11616
+ if (child.error || child.status !== 0) {
11617
+ const reason = child.error?.message ?? (child.stderr.trim() || "Tailwind compilation failed");
11618
+ results = applies.map(() => ({ error: reason }));
11619
+ } else {
11620
+ try {
11621
+ const parsed = JSON.parse(child.stdout);
11622
+ if (!Array.isArray(parsed)) throw new Error("Unexpected Tailwind output");
11623
+ const values = parsed;
11624
+ results = values.filter(isCompiledResult);
11625
+ if (results.length !== applies.length) throw new Error("Unexpected Tailwind output");
11626
+ } catch {
11627
+ results = applies.map(() => ({ error: "Invalid Tailwind compiler response" }));
11628
+ }
11629
+ }
11630
+ compilerCache.set(key, results);
11631
+ return results;
11632
+ }
11633
+ function compiledOperation(compiled, index) {
11634
+ if (!compiled.css) return void 0;
11635
+ const sheet = toPlainObject3(parse7(compiled.css, { parseValue: false }));
11636
+ const probe = rules(sheet).find((candidate) => selectorNames(candidate).includes(`pasika-probe-${String(index)}`));
11637
+ if (!probe) return void 0;
11638
+ const declarations = blockChildren2(probe).filter(
11639
+ (child) => child.type === "Declaration" && !child.property.startsWith("--tw-")
11640
+ );
11641
+ if (declarations.length !== 1) return void 0;
11642
+ const declaration = declarations[0];
11643
+ if (declaration?.type !== "Declaration") return void 0;
11644
+ if (declaration.property === "box-shadow") {
11645
+ const shadow = blockChildren2(probe).find(
11646
+ (child) => child.type === "Declaration" && child.property === "--tw-shadow"
11647
+ );
11648
+ if (shadow?.type === "Declaration") {
11649
+ return { property: "box-shadow", value: generate4(shadow.value).trim() };
11650
+ }
11651
+ }
11652
+ return { property: declaration.property, value: generate4(declaration.value).trim() };
11653
+ }
11654
+ function expectedName(operation) {
11655
+ const value = compoundValue(operation.value);
11656
+ const property = operation.property.replace(/^-+/u, "").replace(/^background-/u, "bg-");
11657
+ return `${property}-${value}`;
11658
+ }
11659
+ function singleApply(utility, textOf) {
11660
+ const children = blockChildren2(utility);
11661
+ if (children.length !== 1) return void 0;
11662
+ const child = children[0];
11663
+ if (child?.type !== "Atrule" || child.name !== "apply") return void 0;
11664
+ return textOf(child);
11665
+ }
11666
+ var utilityNameParityRule = {
11667
+ meta: {
11668
+ schema: [],
11669
+ type: "problem",
11670
+ docs: {
11671
+ description: "Require single-operation custom utilities to have deterministic property/value-derived names."
11672
+ }
11673
+ },
11674
+ create(context) {
11675
+ return {
11676
+ "StyleSheet:exit"(node) {
11677
+ const candidates = atrulesNamed(node, "utility").flatMap((utility) => {
11678
+ const name = preludeIdentifiers(utility)[0];
11679
+ if (!name || name.endsWith("-*")) return [];
11680
+ const apply = singleApply(utility, (child) => context.sourceCode.getText(child));
11681
+ return apply ? [{ utility, name, apply }] : [];
11682
+ });
11683
+ if (candidates.length === 0) return;
11684
+ const physicalDir = path78.dirname(context.physicalFilename);
11685
+ const cwd = path78.isAbsolute(physicalDir) && existsSync12(physicalDir) ? physicalDir : context.cwd;
11686
+ const compiled = compileApplies(
11687
+ candidates.map((candidate) => candidate.apply),
11688
+ cwd
11689
+ );
11690
+ for (const [index, candidate] of candidates.entries()) {
11691
+ const result = compiled[index];
11692
+ const operation = result ? compiledOperation(result, index) : void 0;
11693
+ if (!operation) {
11694
+ context.report({
11695
+ node: candidate.utility,
11696
+ message: `Custom utility "${candidate.name}" applies "${candidate.apply}", but Tailwind cannot resolve exactly one CSS property${result?.error ? `: ${result.error}` : ""}; use an explicit [property:value] @apply mapping instead.`
11697
+ });
11698
+ continue;
11699
+ }
11700
+ const expected = expectedName(operation);
11701
+ if (candidate.name === expected) continue;
11702
+ context.report({
11703
+ node: candidate.utility,
11704
+ message: `Custom utility "${candidate.name}" maps ${operation.property}: ${operation.value}; rename it "${expected}" to preserve property/value parity.`
11705
+ });
11706
+ }
11707
+ }
11708
+ };
11709
+ }
11710
+ };
11711
+
11508
11712
  // eslint/rules/tailwind/index.ts
11509
11713
  var tailwindRules = {
11510
11714
  "theme-reset": themeResetRule,
@@ -11515,6 +11719,7 @@ var tailwindRules = {
11515
11719
  "stylesheet-ordering": stylesheetOrderingRule,
11516
11720
  "custom-utility-apply": customUtilityApplyRule,
11517
11721
  "utility-mapping": utilityMappingRule,
11722
+ "utility-name-parity": utilityNameParityRule,
11518
11723
  "css-entry-point": cssEntryPointRule,
11519
11724
  "feature-css-placement": featureCssPlacementRule,
11520
11725
  "global-stylesheet": globalStylesheetRule,
@@ -11526,7 +11731,7 @@ var tailwindRules = {
11526
11731
  };
11527
11732
 
11528
11733
  // eslint/rules/type-extraction.ts
11529
- import path78 from "path";
11734
+ import path79 from "path";
11530
11735
  var typeExtractionRule = {
11531
11736
  meta: {
11532
11737
  schema: [],
@@ -11537,7 +11742,7 @@ var typeExtractionRule = {
11537
11742
  },
11538
11743
  create(context) {
11539
11744
  const sourceRoot = sourceRootOf(context);
11540
- const file = path78.resolve(context.filename);
11745
+ const file = path79.resolve(context.filename);
11541
11746
  const segments = segmentsOf(file, sourceRoot);
11542
11747
  if (segments.length === 0) return {};
11543
11748
  const index = getProjectIndex(sourceRoot);
@@ -11676,9 +11881,9 @@ var uiStateRule = {
11676
11881
  };
11677
11882
 
11678
11883
  // eslint/rules/unknown-utility.ts
11679
- import { existsSync as existsSync12, readdirSync as readdirSync6, readFileSync as readFileSync15, statSync as statSync6 } from "fs";
11884
+ import { existsSync as existsSync13, readdirSync as readdirSync6, readFileSync as readFileSync15, statSync as statSync6 } from "fs";
11680
11885
  import { createRequire } from "module";
11681
- import path79 from "path";
11886
+ import path80 from "path";
11682
11887
  var PREFIX_NAMESPACES = {
11683
11888
  bg: ["color", "background-image"],
11684
11889
  text: ["color", "text"],
@@ -11959,7 +12164,7 @@ function stylesheetFiles(dir) {
11959
12164
  }
11960
12165
  return entries.flatMap((entry) => {
11961
12166
  if (entry.startsWith(".") || entry === "node_modules") return [];
11962
- const entryPath = path79.join(dir, entry);
12167
+ const entryPath = path80.join(dir, entry);
11963
12168
  let stats;
11964
12169
  try {
11965
12170
  stats = statSync6(entryPath);
@@ -11967,7 +12172,7 @@ function stylesheetFiles(dir) {
11967
12172
  return [];
11968
12173
  }
11969
12174
  if (stats.isDirectory()) return stylesheetFiles(entryPath);
11970
- return path79.extname(entry) === ".css" ? [entryPath] : [];
12175
+ return path80.extname(entry) === ".css" ? [entryPath] : [];
11971
12176
  });
11972
12177
  }
11973
12178
  function packageNameOf(specifier) {
@@ -11978,24 +12183,24 @@ function packageNameOf(specifier) {
11978
12183
  function resolvePackageStylesheet(fromFile, specifier) {
11979
12184
  const packageName = packageNameOf(specifier);
11980
12185
  if (!packageName || packageName === "tailwindcss") return void 0;
11981
- let directory = path79.dirname(fromFile);
11982
- while (directory !== path79.dirname(directory)) {
11983
- const packageRoot = path79.join(directory, "node_modules", packageName);
11984
- const manifestPath = path79.join(packageRoot, "package.json");
11985
- if (existsSync12(manifestPath)) {
12186
+ let directory = path80.dirname(fromFile);
12187
+ while (directory !== path80.dirname(directory)) {
12188
+ const packageRoot = path80.join(directory, "node_modules", packageName);
12189
+ const manifestPath = path80.join(packageRoot, "package.json");
12190
+ if (existsSync13(manifestPath)) {
11986
12191
  try {
11987
12192
  const manifest = readFileSync15(manifestPath, "utf8");
11988
12193
  const stylesheet = /"style"\s*:\s*"(?<file>[^"]+\.css)"/.exec(manifest)?.groups?.file;
11989
12194
  const main = /"main"\s*:\s*"(?<file>[^"]+\.css)"/.exec(manifest)?.groups?.file;
11990
12195
  const target = stylesheet ?? main;
11991
12196
  if (!target) return void 0;
11992
- const resolved = path79.resolve(packageRoot, target);
11993
- return existsSync12(resolved) ? resolved : void 0;
12197
+ const resolved = path80.resolve(packageRoot, target);
12198
+ return existsSync13(resolved) ? resolved : void 0;
11994
12199
  } catch {
11995
12200
  return void 0;
11996
12201
  }
11997
12202
  }
11998
- directory = path79.dirname(directory);
12203
+ directory = path80.dirname(directory);
11999
12204
  }
12000
12205
  return void 0;
12001
12206
  }
@@ -12255,7 +12460,7 @@ var unknownUtilityRule = {
12255
12460
  };
12256
12461
 
12257
12462
  // eslint/rules/util-file-name.ts
12258
- import path80 from "path";
12463
+ import path81 from "path";
12259
12464
  function toKebabCase2(value) {
12260
12465
  return value.replace(/(?<lower>[a-z0-9])(?<upper>[A-Z])/g, "$<lower>-$<upper>").replace(/(?<first>[A-Z])(?<rest>[A-Z][a-z])/g, "$<first>-$<rest>").toLowerCase();
12261
12466
  }
@@ -12268,7 +12473,7 @@ var utilFileNameRule = {
12268
12473
  }
12269
12474
  },
12270
12475
  create(context) {
12271
- const filename = path80.resolve(context.filename);
12476
+ const filename = path81.resolve(context.filename);
12272
12477
  const segments = filename.replace(/\\/g, "/").split("/");
12273
12478
  if (!segments.includes("utils")) return {};
12274
12479
  let module;
@@ -12282,13 +12487,13 @@ var utilFileNameRule = {
12282
12487
  const functionName = functions[0]?.name;
12283
12488
  if (!functionName) return {};
12284
12489
  const expected = toKebabCase2(functionName);
12285
- const actual = path80.basename(filename, path80.extname(filename));
12490
+ const actual = path81.basename(filename, path81.extname(filename));
12286
12491
  if (!expected || actual === expected) return {};
12287
12492
  return {
12288
12493
  Program(node) {
12289
12494
  context.report({
12290
12495
  node,
12291
- message: `A utility file exporting ${functionName} must be named ${expected}.${path80.extname(filename).slice(1)}.`
12496
+ message: `A utility file exporting ${functionName} must be named ${expected}.${path81.extname(filename).slice(1)}.`
12292
12497
  });
12293
12498
  }
12294
12499
  };
@@ -12296,7 +12501,7 @@ var utilFileNameRule = {
12296
12501
  };
12297
12502
 
12298
12503
  // eslint/rules/value-extraction.ts
12299
- import path81 from "path";
12504
+ import path82 from "path";
12300
12505
  var valueExtractionRule = {
12301
12506
  meta: {
12302
12507
  schema: [],
@@ -12307,7 +12512,7 @@ var valueExtractionRule = {
12307
12512
  },
12308
12513
  create(context) {
12309
12514
  const sourceRoot = sourceRootOf(context);
12310
- const file = path81.resolve(context.filename);
12515
+ const file = path82.resolve(context.filename);
12311
12516
  const segments = segmentsOf(file, sourceRoot);
12312
12517
  if (segments.length === 0 || segments[0] !== "app") return {};
12313
12518
  const index = getProjectIndex(sourceRoot);
@@ -12328,8 +12533,8 @@ var valueExtractionRule = {
12328
12533
  };
12329
12534
 
12330
12535
  // eslint/rules/vulyk/tracked-docs.ts
12331
- import { existsSync as existsSync13, readFileSync as readFileSync16 } from "fs";
12332
- import path82 from "path";
12536
+ import { existsSync as existsSync14, readFileSync as readFileSync16 } from "fs";
12537
+ import path83 from "path";
12333
12538
  var PASIKA_REPO = "Bredansky/pasika";
12334
12539
  var BASE_REQUIRED_TRACKED_DOCS = [
12335
12540
  { name: "documentation-guide", path: "docs/documentation-guide" },
@@ -12362,9 +12567,9 @@ var trackedDocsRule = {
12362
12567
  if (!context.filename.endsWith("package.json")) return;
12363
12568
  const root = node.body;
12364
12569
  if (root.type !== "Object") return;
12365
- const projectRoot = path82.dirname(path82.resolve(context.filename));
12366
- const configPath = path82.join(projectRoot, "vulyk.config.ts");
12367
- if (!existsSync13(configPath)) {
12570
+ const projectRoot = path83.dirname(path83.resolve(context.filename));
12571
+ const configPath = path83.join(projectRoot, "vulyk.config.ts");
12572
+ if (!existsSync14(configPath)) {
12368
12573
  context.report({
12369
12574
  node,
12370
12575
  message: "No vulyk.config.ts found. Run npx vulyk init to create one that tracks the framework's required tracked docs."
@@ -12388,8 +12593,8 @@ var trackedDocsRule = {
12388
12593
  });
12389
12594
  }
12390
12595
  }
12391
- const agentsPath = path82.join(projectRoot, "AGENTS.md");
12392
- if (!existsSync13(agentsPath)) {
12596
+ const agentsPath = path83.join(projectRoot, "AGENTS.md");
12597
+ if (!existsSync14(agentsPath)) {
12393
12598
  context.report({
12394
12599
  node,
12395
12600
  message: "No AGENTS.md found. Run npx vulyk agents to generate the agent file that routes to the tracked docs."
@@ -12488,7 +12693,7 @@ var withResponseHelperRule = {
12488
12693
 
12489
12694
  // eslint/rules/zirka-baseline.ts
12490
12695
  import fs7 from "fs";
12491
- import path83 from "path";
12696
+ import path84 from "path";
12492
12697
  var ESLINT_CONFIG = /^eslint\.config\.(?:ts|mts|cts|js|mjs|cjs)$/;
12493
12698
  var PRETTIER_CONFIGS = [
12494
12699
  "prettier.config.mjs",
@@ -12507,10 +12712,10 @@ var zirkaBaselineRule = {
12507
12712
  }
12508
12713
  },
12509
12714
  create(context) {
12510
- const filename = path83.resolve(context.filename);
12511
- const basename = path83.basename(filename);
12715
+ const filename = path84.resolve(context.filename);
12716
+ const basename = path84.basename(filename);
12512
12717
  if (!ESLINT_CONFIG.test(basename)) return {};
12513
- const projectRoot = path83.dirname(filename);
12718
+ const projectRoot = path84.dirname(filename);
12514
12719
  const report3 = (message) => {
12515
12720
  context.report({
12516
12721
  node: context.sourceCode.ast,
@@ -12525,7 +12730,7 @@ var zirkaBaselineRule = {
12525
12730
  'ESLint config must take its configuration from zirka (import { styleguide } from "zirka") instead of restating rules locally.'
12526
12731
  );
12527
12732
  }
12528
- const tsconfigPath = path83.join(projectRoot, "tsconfig.json");
12733
+ const tsconfigPath = path84.join(projectRoot, "tsconfig.json");
12529
12734
  if (!fs7.existsSync(tsconfigPath)) {
12530
12735
  report3('No tsconfig.json found. Create one extending the zirka TypeScript base config ("zirka/typescript").');
12531
12736
  } else {
@@ -12543,13 +12748,13 @@ var zirkaBaselineRule = {
12543
12748
  report3('tsconfig.json must extend the zirka TypeScript base config ("zirka/typescript").');
12544
12749
  }
12545
12750
  }
12546
- const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs7.existsSync(path83.join(projectRoot, name)));
12751
+ const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs7.existsSync(path84.join(projectRoot, name)));
12547
12752
  if (!prettierConfigFile) {
12548
12753
  report3(
12549
12754
  "No prettier config found. Create one that takes its configuration from zirka (styleguide({ prettier: true }).prettierConfig)."
12550
12755
  );
12551
12756
  } else {
12552
- const content = fs7.readFileSync(path83.join(projectRoot, prettierConfigFile), "utf8");
12757
+ const content = fs7.readFileSync(path84.join(projectRoot, prettierConfigFile), "utf8");
12553
12758
  if (!content.includes("zirka")) {
12554
12759
  report3(
12555
12760
  "The prettier config must take its configuration from zirka (styleguide({ prettier: true }).prettierConfig) instead of restating it locally."
@@ -12885,7 +13090,7 @@ var tailwindStructureRules = {
12885
13090
  languageOptions: { tolerant: true },
12886
13091
  rules: Object.fromEntries(
12887
13092
  tailwindRuleIds.filter(
12888
- (id) => id !== "pasika/css-entry-point" && id !== "pasika/feature-css-placement" && id !== "pasika/unique-css-definition" && id !== "pasika/utility-mapping" && id !== "pasika/no-utility-alias" && id !== "pasika/root-variables" && id !== "pasika/color-role-usage"
13093
+ (id) => id !== "pasika/css-entry-point" && id !== "pasika/feature-css-placement" && id !== "pasika/unique-css-definition" && id !== "pasika/utility-mapping" && id !== "pasika/utility-name-parity" && id !== "pasika/no-utility-alias" && id !== "pasika/root-variables" && id !== "pasika/color-role-usage"
12889
13094
  ).map((id) => [id, "error"])
12890
13095
  )
12891
13096
  };
@@ -12903,6 +13108,7 @@ var tailwindImportGraph = {
12903
13108
  "pasika/unique-css-definition": "error",
12904
13109
  "pasika/unique-css-token-value": "error",
12905
13110
  "pasika/utility-mapping": "error",
13111
+ "pasika/utility-name-parity": "error",
12906
13112
  "pasika/no-utility-alias": "error",
12907
13113
  "pasika/root-variables": "error",
12908
13114
  "pasika/color-role-usage": "error"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pasika",
3
- "version": "0.10.118",
3
+ "version": "0.10.120",
4
4
  "description": "Reusable agent setup package",
5
5
  "repository": {
6
6
  "type": "git",
@@ -90,6 +90,7 @@
90
90
  "next": "16.3.5",
91
91
  "prettier": "3.8.1",
92
92
  "tailwind-merge": "3.7.0",
93
+ "tailwindcss": "4.3.3",
93
94
  "tsup": "8.5.1",
94
95
  "tsx": "4.23.12",
95
96
  "typescript": "6.0.3",
@@ -105,6 +106,7 @@
105
106
  "clsx": ">=2.0.0",
106
107
  "next": ">=15.0.0",
107
108
  "tailwind-merge": ">=3.0.0",
109
+ "tailwindcss": "^4.0.0",
108
110
  "zod": ">=4.0.0"
109
111
  },
110
112
  "peerDependenciesMeta": {
@@ -117,6 +119,9 @@
117
119
  "tailwind-merge": {
118
120
  "optional": true
119
121
  },
122
+ "tailwindcss": {
123
+ "optional": true
124
+ },
120
125
  "zod": {
121
126
  "optional": true
122
127
  }