@akanjs/devkit 3.1.0-rc.18 → 3.1.0-rc.19
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.
|
@@ -23,6 +23,22 @@ describe("CssCandidateCache token extraction", () => {
|
|
|
23
23
|
expect(candidates).not.toContain("_td");
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
+
test("keeps a bracket nested one level inside another whole, rather than cutting it at the inner `]`", async () => {
|
|
27
|
+
const candidates = await scan(
|
|
28
|
+
`const c = "hidden [[data-theme=light]_&]:block has-[[aria-expanded=true]]:opacity-100 [&_[data-x]]:p-2 [&:has([data-state=open])]:p-1";`,
|
|
29
|
+
);
|
|
30
|
+
expect(candidates).toEqual(
|
|
31
|
+
expect.arrayContaining([
|
|
32
|
+
"[[data-theme=light]_&]:block",
|
|
33
|
+
"has-[[aria-expanded=true]]:opacity-100",
|
|
34
|
+
"[&_[data-x]]:p-2",
|
|
35
|
+
"[&:has([data-state=open])]:p-1",
|
|
36
|
+
]),
|
|
37
|
+
);
|
|
38
|
+
expect(candidates).not.toContain("[[data-theme=light]_");
|
|
39
|
+
expect(candidates).not.toContain("[&_[data-x]");
|
|
40
|
+
});
|
|
41
|
+
|
|
26
42
|
test("keeps Tailwind v4's variable shorthand whole, and leaves a call's argument its own candidate", async () => {
|
|
27
43
|
const candidates = await scan(
|
|
28
44
|
`const c = "max-md:top-(--keyboard-top) min-h-(--x) bg-(color:--brand)/50"; cn("flex"); fn(value);`,
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { stat } from "node:fs/promises";
|
|
2
2
|
|
|
3
|
-
// The leading `[` alternation keeps arbitrary variants (`[&_td]:px-3`) whole
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
|
|
3
|
+
// The leading `[` alternation keeps arbitrary variants (`[&_td]:px-3`) whole, and a bracket may hold one nested
|
|
4
|
+
// bracket (`[&_[data-slot=x]]:p-2`, `has-[[aria-expanded=true]]:x`), or the candidate is cut at the inner `]` and the
|
|
5
|
+
// rule silently never compiles. Brackets hold no whitespace: a labelled tuple type scanned as a class compiles to a
|
|
6
|
+
// rule lightningcss cannot parse, and it then drops every variant rule. Parentheses pass only as Tailwind v4's
|
|
7
|
+
// variable shorthand, `(--x)` or `(length:--x)`, so `cn("flex")` still yields `flex` on its own.
|
|
8
|
+
const CANDIDATE_RE =
|
|
9
|
+
/-?(?:[\w@]|\[(?:[^[\]\s]|\[[^[\]\s]+\])+\])[\w:/.-]*(?:(?:\[(?:[^[\]\s]|\[[^[\]\s]+\])+\]|\((?:[a-z-]+:)?--[^)\s]+\))[\w:/.-]*)*/g;
|
|
8
10
|
|
|
9
11
|
interface CachedFile {
|
|
10
12
|
mtimeMs: number;
|
|
@@ -20,7 +22,7 @@ interface CacheFile {
|
|
|
20
22
|
/** Tailwind candidates per source file, on disk: the batch worker that compiles CSS exits before the next save. */
|
|
21
23
|
export class CssCandidateCache {
|
|
22
24
|
// Bump when the token regex or the entry shape changes, so stale extractions are not reused.
|
|
23
|
-
static readonly #version =
|
|
25
|
+
static readonly #version = 5;
|
|
24
26
|
readonly #path: string;
|
|
25
27
|
readonly #entries = new Map<string, CachedFile>();
|
|
26
28
|
#dirty = false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akanjs/devkit",
|
|
3
|
-
"version": "3.1.0-rc.
|
|
3
|
+
"version": "3.1.0-rc.19",
|
|
4
4
|
"sourceType": "module",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"@earendil-works/pi-tui": "1.3.0",
|
|
49
49
|
"@inquirer/prompts": "^8.7.3",
|
|
50
50
|
"@tailwindcss/node": "^4.3.3",
|
|
51
|
-
"akanjs": "3.1.0-rc.
|
|
51
|
+
"akanjs": "3.1.0-rc.19",
|
|
52
52
|
"chalk": "^6.0.1",
|
|
53
53
|
"commander": "^15.0.0",
|
|
54
54
|
"dayjs": "^1.11.23",
|