pasika 0.7.0 → 0.7.1

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.
@@ -522,7 +522,7 @@ var noArbitraryTailwindRule = {
522
522
  };
523
523
 
524
524
  // eslint/rules/unknown-utility.ts
525
- import { readdirSync, readFileSync as readFileSync2, statSync } from "fs";
525
+ import { existsSync, readdirSync, readFileSync as readFileSync2, statSync } from "fs";
526
526
  import path5 from "path";
527
527
  var PREFIX_NAMESPACES = {
528
528
  bg: ["color"],
@@ -749,6 +749,53 @@ function stylesheetFiles(dir) {
749
749
  return path5.extname(entry) === ".css" ? [entryPath] : [];
750
750
  });
751
751
  }
752
+ function packageNameOf(specifier) {
753
+ if (specifier.startsWith(".") || specifier.startsWith("/")) return void 0;
754
+ const segments = specifier.split("/");
755
+ return specifier.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0];
756
+ }
757
+ function resolvePackageStylesheet(fromFile, specifier) {
758
+ const packageName = packageNameOf(specifier);
759
+ if (!packageName || packageName === "tailwindcss") return void 0;
760
+ let directory = path5.dirname(fromFile);
761
+ while (directory !== path5.dirname(directory)) {
762
+ const packageRoot = path5.join(directory, "node_modules", packageName);
763
+ const manifestPath = path5.join(packageRoot, "package.json");
764
+ if (existsSync(manifestPath)) {
765
+ try {
766
+ const manifest = readFileSync2(manifestPath, "utf8");
767
+ const stylesheet = /"style"\s*:\s*"(?<file>[^"]+\.css)"/.exec(manifest)?.groups?.file;
768
+ const main = /"main"\s*:\s*"(?<file>[^"]+\.css)"/.exec(manifest)?.groups?.file;
769
+ const target = stylesheet ?? main;
770
+ if (!target) return void 0;
771
+ const resolved = path5.resolve(packageRoot, target);
772
+ return existsSync(resolved) ? resolved : void 0;
773
+ } catch {
774
+ return void 0;
775
+ }
776
+ }
777
+ directory = path5.dirname(directory);
778
+ }
779
+ return void 0;
780
+ }
781
+ function inventoryStylesheetFiles(projectFiles) {
782
+ const files = new Set(projectFiles);
783
+ for (const file of projectFiles) {
784
+ let css2;
785
+ try {
786
+ css2 = readFileSync2(file, "utf8");
787
+ } catch {
788
+ continue;
789
+ }
790
+ for (const match of css2.matchAll(/@import\s+(?:url\(\s*)?["'](?<specifier>[^"']+)["']/gi)) {
791
+ const specifier = match.groups?.specifier;
792
+ if (!specifier) continue;
793
+ const imported = resolvePackageStylesheet(file, specifier);
794
+ if (imported) files.add(imported);
795
+ }
796
+ }
797
+ return [...files];
798
+ }
752
799
  function themeBlocks(css2) {
753
800
  const blocks = [];
754
801
  let index = 0;
@@ -794,6 +841,7 @@ function classSelectors(css2) {
794
841
  }
795
842
  function readInventory(files) {
796
843
  const utilities = /* @__PURE__ */ new Set();
844
+ const wildcardUtilities = /* @__PURE__ */ new Set();
797
845
  const utilityPrefixes = /* @__PURE__ */ new Set();
798
846
  const themeTokensByNamespace = /* @__PURE__ */ new Map();
799
847
  const plainClasses = /* @__PURE__ */ new Set();
@@ -805,9 +853,10 @@ function readInventory(files) {
805
853
  } catch {
806
854
  continue;
807
855
  }
808
- for (const name of css2.matchAll(/@utility\s+(?<utilityName>[a-zA-Z0-9_-]+)/g)) {
856
+ for (const name of css2.matchAll(/@utility\s+(?<utilityName>[a-zA-Z0-9_*-]+)/g)) {
809
857
  const utilityName = name.groups?.utilityName;
810
858
  if (!utilityName) continue;
859
+ if (utilityName.endsWith("-*")) wildcardUtilities.add(utilityName.slice(0, -1));
811
860
  utilities.add(utilityName);
812
861
  const dash = utilityName.indexOf("-");
813
862
  if (dash > 0) utilityPrefixes.add(utilityName.slice(0, dash));
@@ -828,7 +877,14 @@ function readInventory(files) {
828
877
  }
829
878
  }
830
879
  }
831
- return { utilities, utilityPrefixes, themeTokens: themeTokensByNamespace, defaultsReset, plainClasses };
880
+ return {
881
+ utilities,
882
+ wildcardUtilities,
883
+ utilityPrefixes,
884
+ themeTokens: themeTokensByNamespace,
885
+ defaultsReset,
886
+ plainClasses
887
+ };
832
888
  }
833
889
  function isColorToken(token, inventory) {
834
890
  if (inventory.themeTokens.get("color")?.has(token)) return true;
@@ -852,6 +908,7 @@ function isKnown(className, inventory) {
852
908
  const token = compound ? utility.slice(compound.length + 1) : utility.slice(dash + 1);
853
909
  if (!token) return true;
854
910
  if (inventory.utilities.has(utility)) return true;
911
+ if ([...inventory.wildcardUtilities].some((wildcardPrefix) => utility.startsWith(wildcardPrefix))) return true;
855
912
  const namespaces = PREFIX_NAMESPACES[prefix];
856
913
  if (!namespaces) {
857
914
  if (STATIC_VALUE_TOKENS[prefix]?.includes(token)) return true;
@@ -890,7 +947,7 @@ var unknownUtilityRule = {
890
947
  let inventory;
891
948
  try {
892
949
  if (!statSync(sourceRoot).isDirectory()) return {};
893
- inventory = readInventory(stylesheetFiles(sourceRoot));
950
+ inventory = readInventory(inventoryStylesheetFiles(stylesheetFiles(sourceRoot)));
894
951
  } catch {
895
952
  return {};
896
953
  }
@@ -5015,7 +5072,7 @@ var glossaryTermLinkingRule = {
5015
5072
  };
5016
5073
 
5017
5074
  // eslint/rules/documentation/guide-mentions-documents.ts
5018
- import { existsSync } from "fs";
5075
+ import { existsSync as existsSync2 } from "fs";
5019
5076
  import path43 from "path";
5020
5077
  function visitSteps3(node, check) {
5021
5078
  if (node.type === "list" && node.ordered) {
@@ -5082,7 +5139,7 @@ var guideMentionsDocumentsRule = {
5082
5139
  const target = linkTarget(link.url);
5083
5140
  if (!target.endsWith(".md")) continue;
5084
5141
  const resolved = path43.normalize(path43.join(guideDir, target));
5085
- if (!existsSync(resolved)) {
5142
+ if (!existsSync2(resolved)) {
5086
5143
  context.report({
5087
5144
  node: link,
5088
5145
  message: `Guide links a document that does not exist: ${link.url}`
@@ -5437,12 +5494,39 @@ var stylesheetOrderingRule = {
5437
5494
  };
5438
5495
 
5439
5496
  // eslint/rules/tailwind/css-variable-naming.ts
5440
- var EDGE_PROPERTY_WORDS = /* @__PURE__ */ new Set(["border", "divider", "outline", "ring", "stroke"]);
5441
- var NON_COLOR_WORDS = /* @__PURE__ */ new Set(["offset", "radius", "spacing", "style", "width"]);
5497
+ var EDGE_PROPERTY_WORDS = /* @__PURE__ */ new Set(["border", "outline", "ring", "stroke"]);
5498
+ var NON_COLOR_WORDS = /* @__PURE__ */ new Set(["height", "leading", "offset", "radius", "size", "spacing", "style", "width"]);
5499
+ var TAILWIND_THEME_NAMESPACES = /* @__PURE__ */ new Set([
5500
+ "animate",
5501
+ "aspect",
5502
+ "blur",
5503
+ "breakpoint",
5504
+ "color",
5505
+ "container",
5506
+ "drop",
5507
+ "ease",
5508
+ "font",
5509
+ "inset",
5510
+ "leading",
5511
+ "perspective",
5512
+ "radius",
5513
+ "shadow",
5514
+ "spacing",
5515
+ "text",
5516
+ "tracking"
5517
+ ]);
5518
+ function isTailwindThemeVariable(property) {
5519
+ const namespace = property.slice(2).split("-")[0];
5520
+ return namespace !== void 0 && TAILWIND_THEME_NAMESPACES.has(namespace);
5521
+ }
5442
5522
  function looksLikeEdgeColor(lower) {
5443
5523
  const words = lower.slice(2).split("-");
5444
5524
  return words.some((word) => EDGE_PROPERTY_WORDS.has(word)) && !words.some((word) => NON_COLOR_WORDS.has(word));
5445
5525
  }
5526
+ function looksLikeTextColor(lower) {
5527
+ const words = lower.slice(2).split("-");
5528
+ return words.includes("text") && !words.some((word) => NON_COLOR_WORDS.has(word));
5529
+ }
5446
5530
  var cssVariableNamingRule = {
5447
5531
  meta: {
5448
5532
  schema: [],
@@ -5456,6 +5540,7 @@ var cssVariableNamingRule = {
5456
5540
  Declaration(node) {
5457
5541
  const property = node.property;
5458
5542
  if (!property.startsWith("--")) return;
5543
+ if (isTailwindThemeVariable(property)) return;
5459
5544
  const lower = property.toLowerCase();
5460
5545
  if ((lower.includes("bg") || lower.includes("background")) && !lower.endsWith("-canvas")) {
5461
5546
  context.report({
@@ -5463,7 +5548,7 @@ var cssVariableNamingRule = {
5463
5548
  message: `CSS variable "${property}" looks like a background token; name it --<role>-canvas instead.`
5464
5549
  });
5465
5550
  }
5466
- if (lower.includes("text") && !lower.endsWith("-ink")) {
5551
+ if (looksLikeTextColor(lower) && !lower.endsWith("-ink")) {
5467
5552
  context.report({
5468
5553
  node,
5469
5554
  message: `CSS variable "${property}" looks like a text token; name it --<role>-ink instead.`
@@ -6098,7 +6183,7 @@ var nextjsStackRule = {
6098
6183
  };
6099
6184
 
6100
6185
  // eslint/rules/package-json/vitest-coverage.ts
6101
- import { existsSync as existsSync2, readFileSync as readFileSync9 } from "fs";
6186
+ import { existsSync as existsSync3, readFileSync as readFileSync9 } from "fs";
6102
6187
  import path47 from "path";
6103
6188
  function memberName5(member) {
6104
6189
  return member.name.type === "String" ? member.name.value : member.name.name;
@@ -6174,7 +6259,7 @@ var vitestCoverageRule = {
6174
6259
  message: 'package.json must declare a "test:unit:coverage" script that runs Vitest with coverage.'
6175
6260
  });
6176
6261
  }
6177
- const configName = VITEST_CONFIG_NAMES.find((name) => existsSync2(path47.join(context.cwd, name)));
6262
+ const configName = VITEST_CONFIG_NAMES.find((name) => existsSync3(path47.join(context.cwd, name)));
6178
6263
  if (!configName) {
6179
6264
  context.report({
6180
6265
  node,
@@ -6239,7 +6324,7 @@ var nextjsPackageJsonRules = {
6239
6324
  };
6240
6325
 
6241
6326
  // eslint/rules/husky/husky-hook.ts
6242
- import { existsSync as existsSync3, readFileSync as readFileSync10 } from "fs";
6327
+ import { existsSync as existsSync4, readFileSync as readFileSync10 } from "fs";
6243
6328
  import path48 from "path";
6244
6329
  function memberName6(member) {
6245
6330
  return member.name.type === "String" ? member.name.value : member.name.name;
@@ -6259,7 +6344,7 @@ var huskyHookRule = {
6259
6344
  if (root.type !== "Object") return;
6260
6345
  if (!context.filename.endsWith("package.json")) return;
6261
6346
  const hookPath = path48.join(context.cwd, ".husky", "pre-commit");
6262
- if (!existsSync3(hookPath)) {
6347
+ if (!existsSync4(hookPath)) {
6263
6348
  context.report({
6264
6349
  node,
6265
6350
  message: "No .husky/pre-commit hook found. Configure husky to run checks before commits."
@@ -6285,7 +6370,7 @@ var huskyHookRule = {
6285
6370
  context.report({ node, message: ".husky/pre-commit must run npx libyear --limit-major-individual=1." });
6286
6371
  }
6287
6372
  const suppressionsPath = path48.join(context.cwd, "eslint-suppressions.json");
6288
- if (existsSync3(suppressionsPath)) {
6373
+ if (existsSync4(suppressionsPath)) {
6289
6374
  requireNamedScript("lint:prune");
6290
6375
  }
6291
6376
  if (scripts?.value.type === "Object") {
@@ -6308,7 +6393,7 @@ var huskyRules = {
6308
6393
  };
6309
6394
 
6310
6395
  // eslint/rules/vulyk/vulyk-docs.ts
6311
- import { existsSync as existsSync4, readFileSync as readFileSync11 } from "fs";
6396
+ import { existsSync as existsSync5, readFileSync as readFileSync11 } from "fs";
6312
6397
  import path49 from "path";
6313
6398
  var PASIKA_REPO = "Bredansky/pasika";
6314
6399
  var BASE_REQUIRED_DOCS = [
@@ -6344,7 +6429,7 @@ var vulykDocsRule = {
6344
6429
  if (root.type !== "Object") return;
6345
6430
  const projectRoot = path49.dirname(path49.resolve(context.filename));
6346
6431
  const configPath = path49.join(projectRoot, "vulyk.config.ts");
6347
- if (!existsSync4(configPath)) {
6432
+ if (!existsSync5(configPath)) {
6348
6433
  context.report({
6349
6434
  node,
6350
6435
  message: "No vulyk.config.ts found. Run npx vulyk@latest init to create one that tracks the framework's docs."
@@ -6369,7 +6454,7 @@ var vulykDocsRule = {
6369
6454
  }
6370
6455
  }
6371
6456
  const agentsPath = path49.join(projectRoot, "AGENTS.md");
6372
- if (!existsSync4(agentsPath)) {
6457
+ if (!existsSync5(agentsPath)) {
6373
6458
  context.report({
6374
6459
  node,
6375
6460
  message: "No AGENTS.md found. Run npx vulyk@latest agents to generate the agent file that routes to the tracked docs."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pasika",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "Reusable agent setup package",
5
5
  "repository": {
6
6
  "type": "git",