pasika 0.10.122 → 0.10.124
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 +53 -7
- package/package.json +1 -1
|
@@ -9889,20 +9889,33 @@ function colorRoleUsageMessage(className) {
|
|
|
9889
9889
|
|
|
9890
9890
|
// eslint/rules/tailwind/color-role-usage.ts
|
|
9891
9891
|
var COLOR_TOKEN = /^--color-[a-z][a-z0-9-]*-(?:canvas|ink|edge)$/u;
|
|
9892
|
+
var BACKGROUND_IMAGE_TOKEN = /^--background-image-[a-z][a-z0-9-]*-canvas$/u;
|
|
9892
9893
|
var colorRoleUsageRule = {
|
|
9893
9894
|
meta: {
|
|
9894
9895
|
schema: [],
|
|
9895
9896
|
type: "problem",
|
|
9896
|
-
docs: {
|
|
9897
|
+
docs: {
|
|
9898
|
+
description: "Require semantic color and background-image token names and matching Tailwind color utilities."
|
|
9899
|
+
}
|
|
9897
9900
|
},
|
|
9898
9901
|
create(context) {
|
|
9899
9902
|
return {
|
|
9900
9903
|
"StyleSheet:exit"(node) {
|
|
9901
9904
|
for (const theme of atrulesNamed(node, "theme")) {
|
|
9902
9905
|
const source = context.sourceCode.getText(theme).replace(/\/\*[\s\S]*?\*\//gu, " ");
|
|
9903
|
-
for (const match of source.matchAll(
|
|
9906
|
+
for (const match of source.matchAll(
|
|
9907
|
+
/(?:^|[{;\r\n])\s*(?<token>--(?:color|background-image)-[a-z][a-z0-9-]*)\s*:/gu
|
|
9908
|
+
)) {
|
|
9904
9909
|
const token = match.groups?.token;
|
|
9905
|
-
if (
|
|
9910
|
+
if (!token) continue;
|
|
9911
|
+
if (token.startsWith("--background-image-")) {
|
|
9912
|
+
if (!BACKGROUND_IMAGE_TOKEN.test(token)) {
|
|
9913
|
+
context.report({
|
|
9914
|
+
node: theme,
|
|
9915
|
+
message: `Background-image token "${token}" needs a semantic role ending in -canvas.`
|
|
9916
|
+
});
|
|
9917
|
+
}
|
|
9918
|
+
} else if (!COLOR_TOKEN.test(token)) {
|
|
9906
9919
|
context.report({
|
|
9907
9920
|
node: theme,
|
|
9908
9921
|
message: `Color token "${token}" needs a semantic role ending in -canvas, -ink, or -edge.`
|
|
@@ -10627,7 +10640,7 @@ import path72 from "path";
|
|
|
10627
10640
|
import { generate as generate3, parse as parse6, walk as walk3 } from "@eslint/css-tree";
|
|
10628
10641
|
var INLINE_MESSAGE = "Define design tokens with direct values in @theme, not @theme inline.";
|
|
10629
10642
|
var INDIRECT_MESSAGE = "Define design tokens that reference CSS variables via var() in @theme inline.";
|
|
10630
|
-
var MIXED_THEME_MESSAGE = "Use either @theme or @theme inline across the project
|
|
10643
|
+
var MIXED_THEME_MESSAGE = "Use either @theme or @theme inline across the project; external font-loader mappings with valid fallbacks are the only exception.";
|
|
10631
10644
|
var REDUNDANT_INLINE_MESSAGE = (name) => `Tailwind token "${name}" has no runtime overrides; define its value directly in @theme instead of using :root and @theme inline.`;
|
|
10632
10645
|
var EXTERNAL_FONT_FALLBACK_MESSAGE = (name, variable) => `Tailwind font token "${name}" references external font "${variable}" without a fallback inside var(); use var(${variable}, Arial) or another font-family fallback.`;
|
|
10633
10646
|
function hasVarFallback(source, variable) {
|
|
@@ -10644,7 +10657,7 @@ var rootVariablesRule = {
|
|
|
10644
10657
|
schema: [],
|
|
10645
10658
|
type: "problem",
|
|
10646
10659
|
docs: {
|
|
10647
|
-
description: "Require @theme for fixed tokens, matching :root variables for @theme inline tokens, and no other token redeclarations."
|
|
10660
|
+
description: "Require @theme for fixed tokens and fixed-token aliases, matching :root variables for @theme inline tokens, and no other token redeclarations."
|
|
10648
10661
|
}
|
|
10649
10662
|
},
|
|
10650
10663
|
create(context) {
|
|
@@ -10661,12 +10674,26 @@ var rootVariablesRule = {
|
|
|
10661
10674
|
modules: [],
|
|
10662
10675
|
includeReferences: false
|
|
10663
10676
|
});
|
|
10677
|
+
const themeValues = new Map(
|
|
10678
|
+
graph.definitions.filter((symbol) => symbol.kind === "theme-token" && symbol.value !== void 0).map((symbol) => [symbol.name, symbol.value ?? ""])
|
|
10679
|
+
);
|
|
10664
10680
|
const names = new Set(
|
|
10665
10681
|
graph.definitions.filter((symbol) => symbol.kind === "theme-token").map((symbol) => symbol.name)
|
|
10666
10682
|
);
|
|
10683
|
+
function isFixedThemeAlias(name, value, visited = /* @__PURE__ */ new Set()) {
|
|
10684
|
+
const match = /^var\(\s*(?<target>--[a-z][\w-]*)\s*\)$/u.exec(value.trim());
|
|
10685
|
+
const target = match?.groups?.target;
|
|
10686
|
+
if (!target || target === name || visited.has(target)) return false;
|
|
10687
|
+
const next = themeValues.get(target);
|
|
10688
|
+
if (!next) return false;
|
|
10689
|
+
if (!/\bvar\s*\(/u.test(next)) return true;
|
|
10690
|
+
visited.add(target);
|
|
10691
|
+
return isFixedThemeAlias(name, next, visited);
|
|
10692
|
+
}
|
|
10667
10693
|
const mirroredTokens = /* @__PURE__ */ new Set();
|
|
10668
10694
|
let hasPlainThemeBlocks = false;
|
|
10669
10695
|
let hasInlineThemeBlocks = false;
|
|
10696
|
+
let inlineBlocksAreExternalFonts = true;
|
|
10670
10697
|
for (const file of [...stylesheets.filter((candidate) => path72.normalize(candidate) !== current), current]) {
|
|
10671
10698
|
const source = (path72.normalize(file) === current ? context.sourceCode.text : textOf(file)).replace(
|
|
10672
10699
|
/\/\*[\s\S]*?\*\//gu,
|
|
@@ -10676,6 +10703,25 @@ var rootVariablesRule = {
|
|
|
10676
10703
|
if (/\binline\b/u.test(header.groups?.options ?? "")) hasInlineThemeBlocks = true;
|
|
10677
10704
|
else hasPlainThemeBlocks = true;
|
|
10678
10705
|
}
|
|
10706
|
+
const inlineHeaders = [...source.matchAll(/@theme\s+inline\s*\{/gu)];
|
|
10707
|
+
const inlineBlocks = [...source.matchAll(/@theme\s+inline\s*\{(?<body>[^{}]*)\}/gu)];
|
|
10708
|
+
if (inlineHeaders.length !== inlineBlocks.length) inlineBlocksAreExternalFonts = false;
|
|
10709
|
+
for (const block of inlineBlocks) {
|
|
10710
|
+
const declarations = (block.groups?.body ?? "").split(";").map((part) => part.trim()).filter(Boolean);
|
|
10711
|
+
if (declarations.length === 0) inlineBlocksAreExternalFonts = false;
|
|
10712
|
+
for (const declaration of declarations) {
|
|
10713
|
+
const match = /^(?<token>--font-[a-z][\w-]*)\s*:\s*(?<value>.+)$/u.exec(declaration);
|
|
10714
|
+
const name = match?.groups?.token;
|
|
10715
|
+
const value = match?.groups?.value ?? "";
|
|
10716
|
+
const references = [...value.matchAll(/\bvar\s*\(\s*(?<name>--[\w-]+)/gu)].map(
|
|
10717
|
+
(reference) => reference.groups?.name
|
|
10718
|
+
);
|
|
10719
|
+
const runtime = references[0];
|
|
10720
|
+
if (!name || references.length !== 1 || !runtime?.startsWith("--font-") || runtime === name || names.has(runtime) || !hasVarFallback(value, runtime)) {
|
|
10721
|
+
inlineBlocksAreExternalFonts = false;
|
|
10722
|
+
}
|
|
10723
|
+
}
|
|
10724
|
+
}
|
|
10679
10725
|
for (const theme of source.matchAll(/@theme(?<options>(?:\s+[\w-]+)*)\s*\{(?<body>[^{}]*)\}/gu)) {
|
|
10680
10726
|
const inline = /\binline\b/u.test(theme.groups?.options ?? "");
|
|
10681
10727
|
for (const declaration of (theme.groups?.body ?? "").matchAll(
|
|
@@ -10715,7 +10761,7 @@ var rootVariablesRule = {
|
|
|
10715
10761
|
return {
|
|
10716
10762
|
"StyleSheet:exit"(node) {
|
|
10717
10763
|
const localThemes = atrulesNamed(node, "theme");
|
|
10718
|
-
if (hasPlainThemeBlocks && hasInlineThemeBlocks && localThemes[0]) {
|
|
10764
|
+
if (hasPlainThemeBlocks && hasInlineThemeBlocks && !inlineBlocksAreExternalFonts && localThemes[0]) {
|
|
10719
10765
|
context.report({ node: localThemes[0], message: MIXED_THEME_MESSAGE });
|
|
10720
10766
|
}
|
|
10721
10767
|
for (const theme of localThemes) {
|
|
@@ -10757,7 +10803,7 @@ var rootVariablesRule = {
|
|
|
10757
10803
|
context.report({ node: theme, message: REDUNDANT_INLINE_MESSAGE(name) });
|
|
10758
10804
|
}
|
|
10759
10805
|
}
|
|
10760
|
-
if (inline === referencesVariable) continue;
|
|
10806
|
+
if (inline === referencesVariable || !inline && isFixedThemeAlias(name, unquoted)) continue;
|
|
10761
10807
|
const offset = (theme.loc?.start.offset ?? 0) + match.index + match[0].indexOf(name);
|
|
10762
10808
|
const preceding = context.sourceCode.text.slice(0, offset);
|
|
10763
10809
|
const line = preceding.split("\n").length;
|