next-yak 0.0.35 → 0.0.39
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/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/loaders/cssloader.cjs +649 -0
- package/dist/loaders/cssloader.cjs.map +1 -0
- package/dist/loaders/cssloader.d.cts +3 -0
- package/dist/loaders/cssloader.d.ts +3 -0
- package/dist/loaders/cssloader.js +616 -0
- package/dist/loaders/cssloader.js.map +1 -0
- package/dist/loaders/tsloader.cjs +844 -0
- package/dist/loaders/tsloader.cjs.map +1 -0
- package/dist/loaders/tsloader.d.cts +6 -0
- package/dist/loaders/tsloader.d.ts +6 -0
- package/dist/loaders/tsloader.js +820 -0
- package/dist/loaders/tsloader.js.map +1 -0
- package/{withYak → dist/withYak}/index.cjs +14 -7
- package/dist/withYak/index.cjs.map +1 -0
- package/{withYak → dist/withYak}/index.d.cts +2 -2
- package/dist/withYak/index.d.ts +37 -0
- package/dist/withYak/index.js +68 -0
- package/dist/withYak/index.js.map +1 -0
- package/loaders/__tests__/classifier.test.ts +99 -93
- package/loaders/__tests__/cssloader.test.ts +1 -1
- package/loaders/__tests__/getCssName.test.ts +1 -1
- package/loaders/__tests__/tsloader.test.ts +1 -1
- package/loaders/{babel-yak-plugin.cjs → babel-yak-plugin.ts} +69 -68
- package/loaders/{cssloader.cjs → cssloader.ts} +73 -97
- package/loaders/lib/{appendCssUnitToExpressionValue.cjs → appendCssUnitToExpressionValue.ts} +7 -10
- package/loaders/lib/{getConstantValues.cjs → getConstantValues.ts} +10 -17
- package/loaders/lib/{getCssName.cjs → getCssName.ts} +19 -31
- package/loaders/lib/{getStyledComponentName.cjs → getStyledComponentName.ts} +7 -10
- package/loaders/lib/{getYakImports.cjs → getYakImports.ts} +4 -10
- package/loaders/lib/{hash.cjs → hash.ts} +3 -5
- package/loaders/lib/{localIdent.cjs → localIdent.ts} +5 -7
- package/loaders/lib/{quasiClassifier.cjs → quasiClassifier.ts} +7 -16
- package/loaders/lib/{replaceQuasiExpressionTokens.cjs → replaceQuasiExpressionTokens.ts} +27 -26
- package/loaders/lib/{stripCssComments.cjs → stripCssComments.ts} +3 -9
- package/loaders/{tsloader.cjs → tsloader.ts} +11 -15
- package/package.json +12 -21
- package/runtime/__tests__/attrs.test.tsx +4 -14
- package/runtime/__tests__/styled.test.tsx +25 -6
- package/runtime/styled.tsx +5 -5
- package/withYak/index.ts +43 -34
- package/withYak/index.cjs.map +0 -1
|
@@ -1,21 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
/** @typedef {import("@babel/types")} babel */
|
|
1
|
+
import type { NodePath, types as babelTypes } from "@babel/core";
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
4
|
* Extracts the conditions from a path
|
|
7
|
-
* @param {babel.NodePath<babel.types.TaggedTemplateExpression>} path
|
|
8
5
|
*/
|
|
9
|
-
function extractConditions(
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
function extractConditions(
|
|
7
|
+
path: NodePath<babelTypes.TaggedTemplateExpression>
|
|
8
|
+
) {
|
|
9
|
+
const conditions: string[] = [];
|
|
12
10
|
const visitedNodes = new Set();
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const getConditions = (node, previousNode, isNegated = false) => {
|
|
11
|
+
const getConditions = (
|
|
12
|
+
node: babelTypes.Node,
|
|
13
|
+
previousNode: babelTypes.Node,
|
|
14
|
+
isNegated = false
|
|
15
|
+
) => {
|
|
19
16
|
if (visitedNodes.has(node)) return;
|
|
20
17
|
visitedNodes.add(node);
|
|
21
18
|
// Support for && and || operators e.g. disabled && "disabled"
|
|
@@ -58,10 +55,8 @@ function extractConditions(path) {
|
|
|
58
55
|
);
|
|
59
56
|
}
|
|
60
57
|
};
|
|
61
|
-
|
|
62
|
-
let
|
|
63
|
-
/** @type {babel.NodePath} */
|
|
64
|
-
let previousPath = path;
|
|
58
|
+
let currentPath: NodePath | null = path;
|
|
59
|
+
let previousPath: NodePath = path;
|
|
65
60
|
while (currentPath) {
|
|
66
61
|
getConditions(currentPath.node, previousPath.node);
|
|
67
62
|
previousPath = currentPath;
|
|
@@ -77,11 +72,10 @@ function extractConditions(path) {
|
|
|
77
72
|
* Try to get the name of a css component from a literal expression
|
|
78
73
|
*
|
|
79
74
|
* e.g. const mixin = css`...` -> "mixin"
|
|
80
|
-
*
|
|
81
|
-
* @param {babel.NodePath<babel.types.TaggedTemplateExpression>} taggedTemplateExpressionPath
|
|
82
|
-
* @returns {string | null}
|
|
83
75
|
*/
|
|
84
|
-
const getStyledComponentName = (
|
|
76
|
+
const getStyledComponentName = (
|
|
77
|
+
taggedTemplateExpressionPath: NodePath<babelTypes.TaggedTemplateExpression>
|
|
78
|
+
) => {
|
|
85
79
|
const variableDeclaratorPath = taggedTemplateExpressionPath.findParent(
|
|
86
80
|
(path) => path.isVariableDeclarator()
|
|
87
81
|
);
|
|
@@ -100,11 +94,8 @@ const getStyledComponentName = (taggedTemplateExpressionPath) => {
|
|
|
100
94
|
*
|
|
101
95
|
* e.g. props.disabled -> "propsDisabled"
|
|
102
96
|
* e.g. props.user.disabled -> "propsUserDisabled
|
|
103
|
-
*
|
|
104
|
-
* @param {babel.types.MemberExpression} node
|
|
105
|
-
* @returns {string}
|
|
106
97
|
*/
|
|
107
|
-
function getMemberExpressionName(node) {
|
|
98
|
+
function getMemberExpressionName(node: babelTypes.MemberExpression): string {
|
|
108
99
|
if (
|
|
109
100
|
!node.object ||
|
|
110
101
|
!node.property ||
|
|
@@ -134,11 +125,10 @@ function getMemberExpressionName(node) {
|
|
|
134
125
|
* Try to get the name of a css literal
|
|
135
126
|
*
|
|
136
127
|
* e.g. ({$disabled}) => $disabled && css`...` -> "is_$disabled"
|
|
137
|
-
*
|
|
138
|
-
* @param {babel.NodePath<babel.types.TaggedTemplateExpression>} literal
|
|
139
|
-
* @returns {string}
|
|
140
128
|
*/
|
|
141
|
-
function getCssName(
|
|
129
|
+
export default function getCssName(
|
|
130
|
+
literal: NodePath<babelTypes.TaggedTemplateExpression>
|
|
131
|
+
) {
|
|
142
132
|
const conditions = extractConditions(literal);
|
|
143
133
|
if (conditions.length === 0) {
|
|
144
134
|
const mixinName = getStyledComponentName(literal);
|
|
@@ -146,5 +136,3 @@ function getCssName(literal) {
|
|
|
146
136
|
}
|
|
147
137
|
return conditions.join("_").replace(/\$/g, "");
|
|
148
138
|
}
|
|
149
|
-
|
|
150
|
-
module.exports = getCssName;
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
/** @typedef {import("@babel/types")} babel */
|
|
1
|
+
import type { NodePath, types as babelTypes } from "@babel/core";
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
4
|
* Try to get the name of a styled component from a call or member expression
|
|
7
5
|
*
|
|
8
6
|
* e.g. const MyButton = styled.div`...` -> "MyButton"
|
|
9
7
|
* e.g. const FancyButton = styled(MyButton)`...` -> "FancyButton"
|
|
10
|
-
*
|
|
11
|
-
* @param {babel.NodePath<babel.types.TaggedTemplateExpression>} taggedTemplateExpressionPath
|
|
12
|
-
* @returns {string}
|
|
13
8
|
*/
|
|
14
|
-
const getStyledComponentName = (
|
|
9
|
+
const getStyledComponentName = (
|
|
10
|
+
taggedTemplateExpressionPath: NodePath<babelTypes.TaggedTemplateExpression>
|
|
11
|
+
) => {
|
|
15
12
|
const variableDeclaratorPath = taggedTemplateExpressionPath.findParent(
|
|
16
|
-
(path) => path.isVariableDeclarator()
|
|
13
|
+
(path) => path.isVariableDeclarator()
|
|
17
14
|
);
|
|
18
15
|
if (
|
|
19
16
|
!variableDeclaratorPath ||
|
|
@@ -22,10 +19,10 @@ const getStyledComponentName = (taggedTemplateExpressionPath) => {
|
|
|
22
19
|
) {
|
|
23
20
|
throw new Error(
|
|
24
21
|
"Could not find variable declaration for styled component at " +
|
|
25
|
-
taggedTemplateExpressionPath.node.loc
|
|
22
|
+
taggedTemplateExpressionPath.node.loc
|
|
26
23
|
);
|
|
27
24
|
}
|
|
28
25
|
return variableDeclaratorPath.node.id.name;
|
|
29
26
|
};
|
|
30
27
|
|
|
31
|
-
|
|
28
|
+
export default getStyledComponentName;
|
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
// @ts-check
|
|
2
1
|
/**
|
|
3
2
|
* Finds all imports in a given code string which import from a .yak file
|
|
4
3
|
*
|
|
5
4
|
* Uses regex to work with typescript and javascript
|
|
6
5
|
* Does not support lazy imports
|
|
7
|
-
*
|
|
8
|
-
* @param {string} code
|
|
9
|
-
* @returns { { imports: { localName: string, importedName: string }[], from: string }[] }
|
|
10
6
|
*/
|
|
11
|
-
const getYakImports = (code) => {
|
|
7
|
+
const getYakImports = (code: string) => {
|
|
12
8
|
const codeWithoutComments = code.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
13
9
|
const allImports = codeWithoutComments.matchAll(
|
|
14
|
-
/(^|\n|;)\s*import\s+(?:(\w+(?:\s+as\s+\w+)?)\s*,?\s*)?(?:{([^}]*)})?\s+from\s+["']([^'"]+\.yak)["'](;|\n)/g
|
|
10
|
+
/(^|\n|;)\s*import\s+(?:(\w+(?:\s+as\s+\w+)?)\s*,?\s*)?(?:{([^}]*)})?\s+from\s+["']([^'"]+\.yak)["'](;|\n)/g
|
|
15
11
|
);
|
|
16
12
|
return [...allImports].map(([, , defaultImport, namedImports, from]) => {
|
|
17
13
|
// parse named imports to { localName: string, importedName: string }[]
|
|
@@ -33,10 +29,8 @@ const getYakImports = (code) => {
|
|
|
33
29
|
|
|
34
30
|
/**
|
|
35
31
|
* Parses a default import string
|
|
36
|
-
* @param {string} defaultImport
|
|
37
|
-
* @returns {{ localName: string, importedName: string }}
|
|
38
32
|
*/
|
|
39
|
-
function parseDefaultImport(defaultImport) {
|
|
33
|
+
function parseDefaultImport(defaultImport: string) {
|
|
40
34
|
const defaultImportArray = defaultImport.split(/\s+as\s+/);
|
|
41
35
|
return {
|
|
42
36
|
localName: defaultImportArray[1] ?? defaultImportArray[0],
|
|
@@ -44,4 +38,4 @@ function parseDefaultImport(defaultImport) {
|
|
|
44
38
|
};
|
|
45
39
|
}
|
|
46
40
|
|
|
47
|
-
|
|
41
|
+
export default getYakImports;
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
* @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
|
|
7
7
|
* @see http://sites.google.com/site/murmurhash/
|
|
8
8
|
*
|
|
9
|
-
* @param
|
|
10
|
-
* @return
|
|
9
|
+
* @param str ASCII only
|
|
10
|
+
* @return Base 36 encoded hash result
|
|
11
11
|
*/
|
|
12
|
-
function murmurhash2_32_gc(str) {
|
|
12
|
+
export default function murmurhash2_32_gc(str: string) {
|
|
13
13
|
let l = str.length;
|
|
14
14
|
let h = l;
|
|
15
15
|
let i = 0;
|
|
@@ -56,5 +56,3 @@ function murmurhash2_32_gc(str) {
|
|
|
56
56
|
|
|
57
57
|
return (h >>> 0).toString(36);
|
|
58
58
|
}
|
|
59
|
-
|
|
60
|
-
module.exports = murmurhash2_32_gc;
|
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
* localIdent("myVariableName", 1, "keyframes") // "@keyframes myVariableName_1"
|
|
10
10
|
* localIdent("myVariableName", 1, "animation") // "myVariableName_1"
|
|
11
11
|
* ```
|
|
12
|
-
*
|
|
13
|
-
* @param {string} variableName
|
|
14
|
-
* @param {number | null} i
|
|
15
|
-
* @param {"selector" | "className" | "keyframes" | "animation"} kind
|
|
16
12
|
*/
|
|
17
|
-
function localIdent(
|
|
13
|
+
export default function localIdent(
|
|
14
|
+
variableName: string,
|
|
15
|
+
i: number | null,
|
|
16
|
+
kind: "selector" | "className" | "keyframes" | "animation"
|
|
17
|
+
) {
|
|
18
18
|
switch (kind) {
|
|
19
19
|
case "selector":
|
|
20
20
|
return `.${variableName}${i === null ? "" : `_${i}`}`;
|
|
@@ -27,5 +27,3 @@ function localIdent(variableName, i, kind) {
|
|
|
27
27
|
throw new Error("unknown kind");
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
module.exports = localIdent;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
const stripCssComments = require("./stripCssComments.cjs");
|
|
1
|
+
import stripCssComments from "./stripCssComments.js";
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* Checks a quasiValue and returns its type
|
|
@@ -7,18 +6,11 @@ const stripCssComments = require("./stripCssComments.cjs");
|
|
|
7
6
|
* - empty: no expressions, no text
|
|
8
7
|
* - unknownSelector: starts with a `{` e.g. `{ opacity: 0.5; }` or `,` e.g. `, bar { ... }`
|
|
9
8
|
* - insideCssValue: does not end with a `{` or `}` or `;` e.g. `color: `
|
|
10
|
-
*
|
|
11
|
-
* @param {string} quasiValue
|
|
12
|
-
* @param {string[]} currentNestingScopes - the current nesting scope
|
|
13
|
-
*
|
|
14
|
-
* @returns {{
|
|
15
|
-
* empty: boolean,
|
|
16
|
-
* unknownSelector: boolean,
|
|
17
|
-
* insideCssValue: boolean,
|
|
18
|
-
* currentNestingScopes: string[],
|
|
19
|
-
* }}
|
|
20
9
|
*/
|
|
21
|
-
|
|
10
|
+
export default function quasiClassifier(
|
|
11
|
+
quasiValue: string,
|
|
12
|
+
currentNestingScopes: string[]
|
|
13
|
+
) {
|
|
22
14
|
// TODO - for better performance we could move the comment skipping logic
|
|
23
15
|
// directly in the for loop below instead of calling stripCssComments
|
|
24
16
|
const trimmedCssString = stripCssComments(quasiValue).trim();
|
|
@@ -30,8 +22,7 @@ module.exports = function quasiClassifier(quasiValue, currentNestingScopes) {
|
|
|
30
22
|
currentNestingScopes,
|
|
31
23
|
};
|
|
32
24
|
}
|
|
33
|
-
|
|
34
|
-
let isInsideString = false;
|
|
25
|
+
let isInsideString: '"' | "'" | false = false;
|
|
35
26
|
let currentCharacter = "";
|
|
36
27
|
let newNestingLevel = [...currentNestingScopes];
|
|
37
28
|
let currentSelector = "";
|
|
@@ -87,4 +78,4 @@ module.exports = function quasiClassifier(quasiValue, currentNestingScopes) {
|
|
|
87
78
|
currentCharacter !== ";",
|
|
88
79
|
currentNestingScopes: newNestingLevel,
|
|
89
80
|
};
|
|
90
|
-
}
|
|
81
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { NodePath, types as babelTypes } from "@babel/core";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Replace tokens with predefined values e.g.
|
|
3
5
|
*
|
|
@@ -19,12 +21,12 @@
|
|
|
19
21
|
* }
|
|
20
22
|
* `
|
|
21
23
|
* ```
|
|
22
|
-
*
|
|
23
|
-
* @param {import("@babel/types").TemplateLiteral} quasi
|
|
24
|
-
* @param {(name: string) => unknown} replacer
|
|
25
|
-
* @param {import("@babel/types")} t
|
|
26
24
|
*/
|
|
27
|
-
|
|
25
|
+
export default function replaceTokensInQuasiExpressions(
|
|
26
|
+
quasi: babelTypes.TemplateLiteral,
|
|
27
|
+
replacer: (name: string) => unknown,
|
|
28
|
+
t: typeof babelTypes
|
|
29
|
+
) {
|
|
28
30
|
// Iterate over the expressions in reverse order
|
|
29
31
|
// so removing items won't affect the index of the next item
|
|
30
32
|
for (let i = quasi.expressions.length - 1; i >= 0; i--) {
|
|
@@ -36,23 +38,22 @@ module.exports = function replaceTokensInQuasiExpressions(quasi, replacer, t) {
|
|
|
36
38
|
const replacement = parts && replacer(parts[0]);
|
|
37
39
|
// if it is a nested value, find the value of the expression
|
|
38
40
|
// e.g. x.y.z -> find the value of z
|
|
39
|
-
const replacementValue =
|
|
40
|
-
replacement,
|
|
41
|
-
parts
|
|
42
|
-
);
|
|
41
|
+
const replacementValue =
|
|
42
|
+
replacement && getReplacementValue(replacement, parts);
|
|
43
43
|
if (replacementValue !== false && replacementValue !== null) {
|
|
44
44
|
replaceExpressionAndMergeQuasis(quasi, i, replacementValue);
|
|
45
|
-
}
|
|
45
|
+
}
|
|
46
46
|
}
|
|
47
|
-
}
|
|
47
|
+
}
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
50
|
* Replace tokens with predefined values
|
|
51
|
-
* @param {import("@babel/types").TemplateLiteral} quasi
|
|
52
|
-
* @param {number} expressionIndex
|
|
53
|
-
* @param {unknown} replacement
|
|
54
51
|
*/
|
|
55
|
-
function replaceExpressionAndMergeQuasis(
|
|
52
|
+
function replaceExpressionAndMergeQuasis(
|
|
53
|
+
quasi: babelTypes.TemplateLiteral,
|
|
54
|
+
expressionIndex: number,
|
|
55
|
+
replacement: unknown
|
|
56
|
+
) {
|
|
56
57
|
const stringReplacement =
|
|
57
58
|
typeof replacement === "string"
|
|
58
59
|
? replacement
|
|
@@ -77,11 +78,11 @@ function replaceExpressionAndMergeQuasis(quasi, expressionIndex, replacement) {
|
|
|
77
78
|
* - `x()` -> ["x"]
|
|
78
79
|
* - `x.y()` -> ["x", "y"]
|
|
79
80
|
* - (1 + 2) -> null
|
|
80
|
-
*
|
|
81
|
-
* @param {import("@babel/types").Expression | import("@babel/types").TSType} expression
|
|
82
|
-
* @param {import("@babel/types")} t
|
|
83
81
|
*/
|
|
84
|
-
function getExpressionParts(
|
|
82
|
+
function getExpressionParts(
|
|
83
|
+
expression: babelTypes.Expression | babelTypes.TSType,
|
|
84
|
+
t: typeof babelTypes
|
|
85
|
+
) {
|
|
85
86
|
let currentExpression = expression;
|
|
86
87
|
/** @type {string[]} */
|
|
87
88
|
const tokens = [];
|
|
@@ -93,7 +94,10 @@ function getExpressionParts(expression, t) {
|
|
|
93
94
|
}
|
|
94
95
|
// e.g. x.y
|
|
95
96
|
if (t.isMemberExpression(currentExpression)) {
|
|
96
|
-
if (
|
|
97
|
+
if (
|
|
98
|
+
currentExpression.computed === false &&
|
|
99
|
+
t.isIdentifier(currentExpression.property)
|
|
100
|
+
) {
|
|
97
101
|
tokens.unshift(currentExpression.property.name);
|
|
98
102
|
} else if (t.isStringLiteral(currentExpression.property)) {
|
|
99
103
|
tokens.unshift(currentExpression.property.value);
|
|
@@ -117,15 +121,12 @@ function getExpressionParts(expression, t) {
|
|
|
117
121
|
|
|
118
122
|
/**
|
|
119
123
|
* Get the value of the replacement
|
|
120
|
-
*
|
|
124
|
+
*
|
|
121
125
|
* e.g. for `replacement.x.y[0]` and `replacement = { x: { y: [42] } }`
|
|
122
126
|
* parts = ["replacement", "x", "y", 0]
|
|
123
127
|
* --> 42
|
|
124
|
-
*
|
|
125
|
-
* @param {any} replacement
|
|
126
|
-
* @param {string[]} parts
|
|
127
128
|
*/
|
|
128
|
-
function getReplacementValue(replacement, parts) {
|
|
129
|
+
function getReplacementValue(replacement: any, parts: string[]) {
|
|
129
130
|
let currentReplacement = replacement;
|
|
130
131
|
for (let i = 1; i < parts.length; i++) {
|
|
131
132
|
const part = parts[i];
|
|
@@ -135,4 +136,4 @@ function getReplacementValue(replacement, parts) {
|
|
|
135
136
|
currentReplacement = currentReplacement[part];
|
|
136
137
|
}
|
|
137
138
|
return currentReplacement;
|
|
138
|
-
}
|
|
139
|
+
}
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
/// @ts-check
|
|
2
1
|
// from https://github.com/sindresorhus/strip-css-comments/tree/main
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* @param {string} cssString
|
|
6
|
-
*/
|
|
7
|
-
module.exports = function stripCssComments(cssString) {
|
|
8
|
-
/** @type {string | false} */
|
|
9
|
-
let isInsideString = false;
|
|
2
|
+
export default function stripCssComments(cssString: string) {
|
|
3
|
+
let isInsideString: string | false = false;
|
|
10
4
|
let currentCharacter = "";
|
|
11
5
|
let comment = "";
|
|
12
6
|
let returnValue = "";
|
|
@@ -55,4 +49,4 @@ module.exports = function stripCssComments(cssString) {
|
|
|
55
49
|
returnValue += currentCharacter;
|
|
56
50
|
}
|
|
57
51
|
return returnValue;
|
|
58
|
-
}
|
|
52
|
+
}
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const InvalidPositionError =
|
|
5
|
-
require("./babel-yak-plugin.cjs").InvalidPositionError;
|
|
1
|
+
import babel, { BabelFileResult } from "@babel/core";
|
|
2
|
+
import getYakImports from "./lib/getYakImports.js";
|
|
3
|
+
import { InvalidPositionError } from "./babel-yak-plugin.js";
|
|
6
4
|
|
|
7
5
|
/**
|
|
8
6
|
* Loader for typescript files that use yak, it replaces the css template literal with a call to the 'styled' function
|
|
9
|
-
* @param {string} source
|
|
10
|
-
* @this {any}
|
|
11
|
-
* @returns {Promise<string | void>}
|
|
12
7
|
*/
|
|
13
|
-
|
|
8
|
+
export default async function tsloader(
|
|
9
|
+
this: any,
|
|
10
|
+
source: string
|
|
11
|
+
): Promise<string | void> {
|
|
14
12
|
// ignore files if they don't use yak
|
|
15
13
|
if (!source.includes("next-yak")) {
|
|
16
14
|
return source;
|
|
@@ -26,8 +24,7 @@ module.exports = async function tsloader(source) {
|
|
|
26
24
|
// However .yak files inside .yak files are not be compiled
|
|
27
25
|
// to avoid performance overhead
|
|
28
26
|
const importedYakConstants = isYakFile ? [] : getYakImports(source);
|
|
29
|
-
|
|
30
|
-
const replaces = {};
|
|
27
|
+
const replaces: Record<string, unknown> = {};
|
|
31
28
|
await Promise.all(
|
|
32
29
|
importedYakConstants.map(async ({ imports, from }) => {
|
|
33
30
|
const constantValues = await this.importModule(from, {
|
|
@@ -39,8 +36,7 @@ module.exports = async function tsloader(source) {
|
|
|
39
36
|
})
|
|
40
37
|
);
|
|
41
38
|
|
|
42
|
-
|
|
43
|
-
let result = null;
|
|
39
|
+
let result: BabelFileResult | null = null;
|
|
44
40
|
try {
|
|
45
41
|
// Compile the typescript file with babel - this will:
|
|
46
42
|
// - inject the import to the css-module (with .yak.module.css extension)
|
|
@@ -54,7 +50,7 @@ module.exports = async function tsloader(source) {
|
|
|
54
50
|
{ isTSX: this.resourcePath.endsWith(".tsx") },
|
|
55
51
|
],
|
|
56
52
|
[
|
|
57
|
-
|
|
53
|
+
await import("./babel-yak-plugin.js").then((m) => m.default),
|
|
58
54
|
{
|
|
59
55
|
replaces,
|
|
60
56
|
rootContext,
|
|
@@ -72,4 +68,4 @@ module.exports = async function tsloader(source) {
|
|
|
72
68
|
return callback(new Error("babel transform failed"));
|
|
73
69
|
}
|
|
74
70
|
return callback(null, result.code, result.map);
|
|
75
|
-
}
|
|
71
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-yak",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.39",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"types": "./dist/",
|
|
6
6
|
"exports": {
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
"require": "./dist/runtime-internals/index.cjs"
|
|
18
18
|
},
|
|
19
19
|
"./withYak": {
|
|
20
|
-
"
|
|
20
|
+
"import": "./dist/withYak/index.js",
|
|
21
|
+
"require": "./dist/withYak/index.cjs"
|
|
21
22
|
},
|
|
22
23
|
"./context/baseContext": {
|
|
23
24
|
"import": "./dist/context/baseContext.js",
|
|
@@ -34,23 +35,6 @@
|
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
},
|
|
37
|
-
"scripts": {
|
|
38
|
-
"prepublishOnly": "npm run build && npm run test && npm run test:types:code && npm run test:types:test",
|
|
39
|
-
"build": "pnpm run --filter . \"/^build:/\"",
|
|
40
|
-
"build:runtime": "tsup runtime/index.ts --target es2022 --clean --external react --external next-yak/context --format cjs,esm --minify --sourcemap --out-dir dist",
|
|
41
|
-
"build:runtime:types": "tsup runtime/index.ts --target es2022 --clean --external react --dts-only --format cjs,esm --minify --sourcemap --out-dir dist",
|
|
42
|
-
"build:runtimeInternals": "tsup runtime/internals/index.ts --target es2022 --clean --external react --external next-yak/runtime-internals --format cjs,esm --minify --sourcemap --out-dir dist/runtime-internals",
|
|
43
|
-
"build:static": "tsup static/index.ts --target es2022 --clean --external react --external next-yak/context --format cjs,esm --minify --sourcemap --out-dir dist/static",
|
|
44
|
-
"build:static:types": "tsup static/index.ts --target es2022 --clean --external react --dts-only --format cjs,esm --minify --sourcemap --out-dir dist/static",
|
|
45
|
-
"build:baseContext": "tsup runtime/context/baseContext.tsx --target es2022 --external react --dts --format cjs,esm --sourcemap --out-dir dist/context/",
|
|
46
|
-
"build:context:client": "tsup runtime/context/index.tsx --target es2022 --external react --external next-yak/context/baseContext --dts --format cjs,esm --sourcemap --out-dir dist/context/",
|
|
47
|
-
"build:context:server": "tsup runtime/context/index.server.tsx --target es2022 --external react --external next-yak/context/baseContext --external ./index.js --format cjs,esm --sourcemap --out-dir dist/context/",
|
|
48
|
-
"build:withYak": "tsup withYak/index.ts --target es2022 --dts --format cjs --sourcemap --out-dir withYak --external ../loaders/tsloader.cjs --external ../loaders/cssloader.cjs",
|
|
49
|
-
"test": "vitest run",
|
|
50
|
-
"test:types:code": "tsc -p tsconfig.json",
|
|
51
|
-
"test:types:test": "tsc -p ./runtime/__tests__/tsconfig.json",
|
|
52
|
-
"test:watch": "vitest --watch"
|
|
53
|
-
},
|
|
54
38
|
"dependencies": {
|
|
55
39
|
"@babel/core": "7.23.2",
|
|
56
40
|
"@babel/plugin-syntax-typescript": "7.22.5",
|
|
@@ -79,5 +63,12 @@
|
|
|
79
63
|
"loaders",
|
|
80
64
|
"runtime",
|
|
81
65
|
"withYak"
|
|
82
|
-
]
|
|
83
|
-
|
|
66
|
+
],
|
|
67
|
+
"scripts": {
|
|
68
|
+
"build": "tsup",
|
|
69
|
+
"test": "vitest run",
|
|
70
|
+
"test:types:code": "tsc -p tsconfig.json",
|
|
71
|
+
"test:types:test": "tsc -p ./runtime/__tests__/tsconfig.json",
|
|
72
|
+
"test:watch": "vitest --watch"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -256,18 +256,6 @@ it("should work with data and aria attributes", () => {
|
|
|
256
256
|
`);
|
|
257
257
|
});
|
|
258
258
|
|
|
259
|
-
// it("merge attrs", () => {
|
|
260
|
-
// const Comp = styled.button
|
|
261
|
-
// .attrs(() => ({
|
|
262
|
-
// type: "button",
|
|
263
|
-
// tabIndex: 0,
|
|
264
|
-
// }))
|
|
265
|
-
// .attrs(() => ({
|
|
266
|
-
// type: "submit",
|
|
267
|
-
// }))``;
|
|
268
|
-
// expect(TestRenderer.create(<Comp />).toJSON()).toMatchInlineSnapshot();
|
|
269
|
-
// });
|
|
270
|
-
|
|
271
259
|
it("merge attrs when inheriting SC", () => {
|
|
272
260
|
const Parent = styled.button.attrs(() => ({
|
|
273
261
|
type: "button",
|
|
@@ -281,7 +269,7 @@ it("merge attrs when inheriting SC", () => {
|
|
|
281
269
|
className=""
|
|
282
270
|
style={{}}
|
|
283
271
|
tabIndex={0}
|
|
284
|
-
type="
|
|
272
|
+
type="submit"
|
|
285
273
|
/>
|
|
286
274
|
`);
|
|
287
275
|
});
|
|
@@ -531,6 +519,8 @@ it("should pass theme if theme is overwritten", () => {
|
|
|
531
519
|
<pre
|
|
532
520
|
className=""
|
|
533
521
|
style={{}}
|
|
534
|
-
|
|
522
|
+
>
|
|
523
|
+
{"color":"blue"}
|
|
524
|
+
</pre>
|
|
535
525
|
`);
|
|
536
526
|
});
|
|
@@ -95,13 +95,28 @@ it("should filter out properties starting with $ when passing to custom", () =>
|
|
|
95
95
|
return null;
|
|
96
96
|
};
|
|
97
97
|
const StyledComponent = styled(Component)``;
|
|
98
|
-
|
|
99
|
-
<StyledComponent $forwardedProp="notForwarded" />,
|
|
100
|
-
);
|
|
98
|
+
render(<StyledComponent $forwardedProp="notForwarded" />);
|
|
101
99
|
|
|
102
100
|
expect(forwardedProps).toEqual({});
|
|
103
101
|
});
|
|
104
102
|
|
|
103
|
+
it("should forward properties to the next yak component", () => {
|
|
104
|
+
const Component = styled.input.attrs(({ $text }) => ({
|
|
105
|
+
"aria-label": $text,
|
|
106
|
+
}))``;
|
|
107
|
+
const StyledComponent = styled(Component)``;
|
|
108
|
+
const { container } = render(<StyledComponent $text="hello world" />);
|
|
109
|
+
|
|
110
|
+
expect(container).toMatchInlineSnapshot(`
|
|
111
|
+
<div>
|
|
112
|
+
<input
|
|
113
|
+
aria-label="hello world"
|
|
114
|
+
class=""
|
|
115
|
+
/>
|
|
116
|
+
</div>
|
|
117
|
+
`);
|
|
118
|
+
});
|
|
119
|
+
|
|
105
120
|
it("should concatenate classNames", () => {
|
|
106
121
|
const Component = styled.input("className1");
|
|
107
122
|
|
|
@@ -256,7 +271,7 @@ it("should remove theme if styled element", () => {
|
|
|
256
271
|
`);
|
|
257
272
|
});
|
|
258
273
|
|
|
259
|
-
it("should
|
|
274
|
+
it("should keep theme if theme is passed to element", () => {
|
|
260
275
|
const ThemePrinter = ({ theme, ...props }: { theme?: unknown }) => (
|
|
261
276
|
<pre {...props}>{JSON.stringify(theme)}</pre>
|
|
262
277
|
);
|
|
@@ -272,7 +287,9 @@ it("should not remove theme if theme is passed to element", () => {
|
|
|
272
287
|
<div>
|
|
273
288
|
<pre
|
|
274
289
|
class="test"
|
|
275
|
-
|
|
290
|
+
>
|
|
291
|
+
{"anything":"test"}
|
|
292
|
+
</pre>
|
|
276
293
|
</div>
|
|
277
294
|
`);
|
|
278
295
|
});
|
|
@@ -314,7 +331,9 @@ it("should not remove theme if theme is passed to wrapped element", () => {
|
|
|
314
331
|
<div>
|
|
315
332
|
<pre
|
|
316
333
|
class="test-wrapper test"
|
|
317
|
-
|
|
334
|
+
>
|
|
335
|
+
{"anything":"test"}
|
|
336
|
+
</pre>
|
|
318
337
|
</div>
|
|
319
338
|
`);
|
|
320
339
|
});
|
package/runtime/styled.tsx
CHANGED
|
@@ -22,7 +22,7 @@ const yakForwardRef: <TProps>(
|
|
|
22
22
|
// warning: `__yak` is undefined during runtime
|
|
23
23
|
__yak: true;
|
|
24
24
|
} = (component) =>
|
|
25
|
-
Object.assign(React.forwardRef(component), { component }) as any;
|
|
25
|
+
Object.assign(React.forwardRef(component), { yak: component }) as any;
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* All valid html tags
|
|
@@ -116,6 +116,8 @@ const yakStyled = <
|
|
|
116
116
|
// prevents passing the theme prop to the DOM element of a styled component
|
|
117
117
|
const { theme: themeAfterAttr, ...combinedPropsWithoutTheme } =
|
|
118
118
|
combinedProps as { theme?: unknown };
|
|
119
|
+
const propsBeforeFiltering =
|
|
120
|
+
themeAfterAttr === theme ? combinedPropsWithoutTheme : combinedProps;
|
|
119
121
|
|
|
120
122
|
const isYakComponent =
|
|
121
123
|
typeof Component !== "string" && "yak" in Component;
|
|
@@ -123,10 +125,8 @@ const yakStyled = <
|
|
|
123
125
|
// remove all props that start with a $ sign for string components e.g. "button" or "div"
|
|
124
126
|
// so that they are not passed to the DOM element
|
|
125
127
|
const filteredProps = !isYakComponent
|
|
126
|
-
? removePrefixedProperties(
|
|
127
|
-
:
|
|
128
|
-
? combinedPropsWithoutTheme
|
|
129
|
-
: combinedProps;
|
|
128
|
+
? removePrefixedProperties(propsBeforeFiltering)
|
|
129
|
+
: propsBeforeFiltering;
|
|
130
130
|
|
|
131
131
|
// yak provides a className and style prop that needs to be merged with the
|
|
132
132
|
// user provided className and style prop
|