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.
- package/dist/eslint/pasika/index.js +102 -17
- package/package.json +1 -1
|
@@ -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_
|
|
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 {
|
|
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 (!
|
|
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", "
|
|
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
|
|
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
|
|
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) =>
|
|
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
|
|
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 (!
|
|
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 (
|
|
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
|
|
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 (!
|
|
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 (!
|
|
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."
|