next-yak 0.0.28 → 0.0.30
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.
|
@@ -13,6 +13,18 @@ const loaderContext = {
|
|
|
13
13
|
xl: "@media (min-width: 1280px)",
|
|
14
14
|
xxl: "@media (min-width: 1536px)",
|
|
15
15
|
},
|
|
16
|
+
spacing: {
|
|
17
|
+
0.5: "4px",
|
|
18
|
+
1: "8px",
|
|
19
|
+
2: "16px",
|
|
20
|
+
4: "32px",
|
|
21
|
+
},
|
|
22
|
+
typography: {
|
|
23
|
+
"letter spacing": "0.05em",
|
|
24
|
+
primary: {
|
|
25
|
+
"font weight": 800,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
16
28
|
};
|
|
17
29
|
},
|
|
18
30
|
getOptions: () => ({
|
|
@@ -289,6 +301,40 @@ const headline = css\`
|
|
|
289
301
|
`);
|
|
290
302
|
});
|
|
291
303
|
|
|
304
|
+
it("should replace breakpoint references with actual media queries when using square brackets", async () => {
|
|
305
|
+
expect(
|
|
306
|
+
await cssloader.call(
|
|
307
|
+
loaderContext,
|
|
308
|
+
`
|
|
309
|
+
import { css } from "next-yak";
|
|
310
|
+
import { queries } from '@/theme.yak';
|
|
311
|
+
|
|
312
|
+
const headline = css\`
|
|
313
|
+
color: blue;
|
|
314
|
+
\${queries["sm"]} {
|
|
315
|
+
color: red;
|
|
316
|
+
}
|
|
317
|
+
transition: color \${duration} \${easing};
|
|
318
|
+
display: block;
|
|
319
|
+
\${css\`color: orange\`}
|
|
320
|
+
\`;
|
|
321
|
+
`
|
|
322
|
+
)
|
|
323
|
+
).toMatchInlineSnapshot(`
|
|
324
|
+
".headline_0 {
|
|
325
|
+
color: blue;
|
|
326
|
+
@media (min-width: 640px) {
|
|
327
|
+
color: red;
|
|
328
|
+
}
|
|
329
|
+
transition: color var(--🦬18fi82j0) var(--🦬18fi82j1);
|
|
330
|
+
display: block;
|
|
331
|
+
&:where(.headline_1) {
|
|
332
|
+
color: orange
|
|
333
|
+
}
|
|
334
|
+
}"
|
|
335
|
+
`);
|
|
336
|
+
});
|
|
337
|
+
|
|
292
338
|
it("should prevent double escaped chars", async () => {
|
|
293
339
|
// in styled-components \\ is replaced with \
|
|
294
340
|
// this test verifies that yak provides the same behavior
|
|
@@ -466,7 +512,7 @@ const Component = styled.div\`
|
|
|
466
512
|
background-color: brown;
|
|
467
513
|
\`}
|
|
468
514
|
\`}
|
|
469
|
-
|
|
515
|
+
|
|
470
516
|
border: 2px solid pink;
|
|
471
517
|
}
|
|
472
518
|
\`;
|
|
@@ -574,4 +620,33 @@ const Component = styled.div\`
|
|
|
574
620
|
}"
|
|
575
621
|
`);
|
|
576
622
|
});
|
|
623
|
+
|
|
624
|
+
it("should replace all array like constants", async () => {
|
|
625
|
+
expect(
|
|
626
|
+
await cssloader.call(
|
|
627
|
+
loaderContext,
|
|
628
|
+
`
|
|
629
|
+
import { css } from "next-yak";
|
|
630
|
+
import { queries, spacing, typography } from "@/theme.yak";
|
|
631
|
+
|
|
632
|
+
const headline = css\`
|
|
633
|
+
\${queries["xl"]} {
|
|
634
|
+
color: red;
|
|
635
|
+
}
|
|
636
|
+
margin: -\${spacing[2]};
|
|
637
|
+
font-weight: \${typography.primary["font weight"]};
|
|
638
|
+
letter-spacing: \${typography["letter spacing"]};
|
|
639
|
+
\``
|
|
640
|
+
)
|
|
641
|
+
).toMatchInlineSnapshot(`
|
|
642
|
+
".headline_0 {
|
|
643
|
+
@media (min-width: 1280px) {
|
|
644
|
+
color: red;
|
|
645
|
+
}
|
|
646
|
+
margin: -16px;
|
|
647
|
+
font-weight: 800;
|
|
648
|
+
letter-spacing: 0.05em;
|
|
649
|
+
}"
|
|
650
|
+
`);
|
|
651
|
+
});
|
|
577
652
|
});
|
|
@@ -25,43 +25,24 @@
|
|
|
25
25
|
* @param {import("@babel/types")} t
|
|
26
26
|
*/
|
|
27
27
|
module.exports = function replaceTokensInQuasiExpressions(quasi, replacer, t) {
|
|
28
|
-
|
|
28
|
+
// Iterate over the expressions in reverse order
|
|
29
|
+
// so removing items won't affect the index of the next item
|
|
30
|
+
for (let i = quasi.expressions.length - 1; i >= 0; i--) {
|
|
29
31
|
const expression = quasi.expressions[i];
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
) {
|
|
45
|
-
/** @type {any} */
|
|
46
|
-
let replacement = replacer(expression.object.name);
|
|
47
|
-
if (replacement === false) {
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
/** @type {import("@babel/types").Expression} */
|
|
51
|
-
let object = expression;
|
|
52
|
-
while (t.isMemberExpression(object)) {
|
|
53
|
-
if (!t.isIdentifier(object.property)) {
|
|
54
|
-
break;
|
|
55
|
-
}
|
|
56
|
-
if (typeof replacement !== "object" || replacement === null) {
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
replacement = replacement[object.property.name];
|
|
60
|
-
object = object.object;
|
|
61
|
-
}
|
|
62
|
-
replaceExpressionAndMergeQuasis(quasi, i, replacement);
|
|
63
|
-
i--;
|
|
64
|
-
}
|
|
32
|
+
// break the expression into parts
|
|
33
|
+
// e.g. x.y.z -> ["x", "y", "z"]
|
|
34
|
+
const parts = getExpressionParts(expression, t);
|
|
35
|
+
// find the replacement for the expression
|
|
36
|
+
const replacement = parts && replacer(parts[0]);
|
|
37
|
+
// if it is a nested value, find the value of the expression
|
|
38
|
+
// e.g. x.y.z -> find the value of z
|
|
39
|
+
const replacementValue = replacement && getReplacementValue(
|
|
40
|
+
replacement,
|
|
41
|
+
parts
|
|
42
|
+
);
|
|
43
|
+
if (replacementValue !== false && replacementValue !== null) {
|
|
44
|
+
replaceExpressionAndMergeQuasis(quasi, i, replacementValue);
|
|
45
|
+
}
|
|
65
46
|
}
|
|
66
47
|
};
|
|
67
48
|
|
|
@@ -85,3 +66,73 @@ function replaceExpressionAndMergeQuasis(quasi, expressionIndex, replacement) {
|
|
|
85
66
|
stringReplacement + quasi.quasis[expressionIndex + 1].value.cooked;
|
|
86
67
|
quasi.quasis.splice(expressionIndex + 1, 1);
|
|
87
68
|
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Find the replacement for the expression
|
|
72
|
+
*
|
|
73
|
+
* searches for:
|
|
74
|
+
* - `x` -> ["x"]
|
|
75
|
+
* - `x.y` -> ["x", "y"]
|
|
76
|
+
* - `x[0]` -> ["x", 0]
|
|
77
|
+
* - `x()` -> ["x"]
|
|
78
|
+
* - `x.y()` -> ["x", "y"]
|
|
79
|
+
* - (1 + 2) -> null
|
|
80
|
+
*
|
|
81
|
+
* @param {import("@babel/types").Expression | import("@babel/types").TSType} expression
|
|
82
|
+
* @param {import("@babel/types")} t
|
|
83
|
+
*/
|
|
84
|
+
function getExpressionParts(expression, t) {
|
|
85
|
+
let currentExpression = expression;
|
|
86
|
+
/** @type {string[]} */
|
|
87
|
+
const tokens = [];
|
|
88
|
+
while (currentExpression) {
|
|
89
|
+
// e.g. x
|
|
90
|
+
if (t.isIdentifier(currentExpression)) {
|
|
91
|
+
tokens.unshift(currentExpression.name);
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
// e.g. x.y
|
|
95
|
+
if (t.isMemberExpression(currentExpression)) {
|
|
96
|
+
if (currentExpression.computed === false && t.isIdentifier(currentExpression.property)) {
|
|
97
|
+
tokens.unshift(currentExpression.property.name);
|
|
98
|
+
} else if (t.isStringLiteral(currentExpression.property)) {
|
|
99
|
+
tokens.unshift(currentExpression.property.value);
|
|
100
|
+
} else if (t.isNumericLiteral(currentExpression.property)) {
|
|
101
|
+
tokens.unshift(String(currentExpression.property.value));
|
|
102
|
+
} else {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
currentExpression = currentExpression.object;
|
|
106
|
+
} else if (t.isCallExpression(currentExpression)) {
|
|
107
|
+
if (!t.isExpression(currentExpression.callee)) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
currentExpression = currentExpression.callee;
|
|
111
|
+
} else {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return tokens;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Get the value of the replacement
|
|
120
|
+
*
|
|
121
|
+
* e.g. for `replacement.x.y[0]` and `replacement = { x: { y: [42] } }`
|
|
122
|
+
* parts = ["replacement", "x", "y", 0]
|
|
123
|
+
* --> 42
|
|
124
|
+
*
|
|
125
|
+
* @param {any} replacement
|
|
126
|
+
* @param {string[]} parts
|
|
127
|
+
*/
|
|
128
|
+
function getReplacementValue(replacement, parts) {
|
|
129
|
+
let currentReplacement = replacement;
|
|
130
|
+
for (let i = 1; i < parts.length; i++) {
|
|
131
|
+
const part = parts[i];
|
|
132
|
+
if (currentReplacement == null || typeof currentReplacement !== "object") {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
currentReplacement = currentReplacement[part];
|
|
136
|
+
}
|
|
137
|
+
return currentReplacement;
|
|
138
|
+
}
|