next-yak 0.0.18 → 0.0.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.
- package/loaders/__tests__/classifier.test.ts +133 -0
- package/loaders/__tests__/tsloader.test.ts +100 -48
- package/loaders/babel-yak-plugin.cjs +47 -23
- package/loaders/cssloader.cjs +9 -11
- package/loaders/lib/getStyledComponentName.cjs +2 -2
- package/loaders/lib/getYakImports.cjs +29 -20
- package/loaders/lib/quasiClassifier.cjs +75 -21
- package/loaders/lib/replaceQuasiExpressionTokens.cjs +17 -7
- package/loaders/lib/stripCssComments.cjs +49 -42
- package/loaders/tsloader.cjs +39 -23
- package/package.json +1 -1
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import quasiClassifier from '../lib/quasiClassifier.cjs';
|
|
2
|
+
import { describe, it, expect } from "vitest";
|
|
3
|
+
|
|
4
|
+
describe('quasiClassifier', () => {
|
|
5
|
+
it('should classify empty quasi', () => {
|
|
6
|
+
expect(quasiClassifier('', [])).toEqual({
|
|
7
|
+
empty: true,
|
|
8
|
+
unknownSelector: false,
|
|
9
|
+
insideCssValue: false,
|
|
10
|
+
currentNestingScopes: [],
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
it("should recognize a comment as empty", () => {
|
|
14
|
+
expect(quasiClassifier("/* comment */", [])).toEqual({
|
|
15
|
+
empty: true,
|
|
16
|
+
unknownSelector: false,
|
|
17
|
+
insideCssValue: false,
|
|
18
|
+
currentNestingScopes: [],
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
it("should find incomplete css - unknownSelector", () => {
|
|
22
|
+
expect(quasiClassifier("{ color: blue;", [])).toEqual({
|
|
23
|
+
empty: false,
|
|
24
|
+
unknownSelector: true,
|
|
25
|
+
insideCssValue: false,
|
|
26
|
+
currentNestingScopes: [],
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
it("should find incomplete css - insideCssValue", () => {
|
|
30
|
+
expect(quasiClassifier("color: ", [
|
|
31
|
+
".foo"
|
|
32
|
+
])).toEqual({
|
|
33
|
+
empty: false,
|
|
34
|
+
unknownSelector: false,
|
|
35
|
+
insideCssValue: true,
|
|
36
|
+
currentNestingScopes: [".foo"],
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
it("should find incomplete css - insideCssValue after a media query", () => {
|
|
40
|
+
expect(quasiClassifier("} .foo { color: ", [
|
|
41
|
+
"@media (min-width: 640px)"
|
|
42
|
+
])).toEqual({
|
|
43
|
+
empty: false,
|
|
44
|
+
unknownSelector: false,
|
|
45
|
+
insideCssValue: true,
|
|
46
|
+
currentNestingScopes: [".foo"],
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
it("should find incomplete css - insideCssValue in a multi value", () => {
|
|
50
|
+
expect(quasiClassifier("} .foo { transition: 200ms ", [
|
|
51
|
+
"@media (min-width: 640px)"
|
|
52
|
+
])).toEqual({
|
|
53
|
+
empty: false,
|
|
54
|
+
unknownSelector: false,
|
|
55
|
+
insideCssValue: true,
|
|
56
|
+
currentNestingScopes: [".foo"],
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
it("should find nesting scopes", () => {
|
|
60
|
+
expect(quasiClassifier(`
|
|
61
|
+
.foo {
|
|
62
|
+
.bar {
|
|
63
|
+
@supports (display: grid) {
|
|
64
|
+
`, [
|
|
65
|
+
"@media (min-width: 640px)"
|
|
66
|
+
])).toEqual({
|
|
67
|
+
empty: false,
|
|
68
|
+
unknownSelector: false,
|
|
69
|
+
insideCssValue: false,
|
|
70
|
+
currentNestingScopes: [
|
|
71
|
+
"@media (min-width: 640px)",
|
|
72
|
+
".foo",
|
|
73
|
+
".bar",
|
|
74
|
+
"@supports (display: grid)",
|
|
75
|
+
],
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
it("should find nesting scopes with properties", () => {
|
|
79
|
+
expect(quasiClassifier(`
|
|
80
|
+
.foo {
|
|
81
|
+
color: purple;
|
|
82
|
+
.x {
|
|
83
|
+
color: green;
|
|
84
|
+
}
|
|
85
|
+
.bar {
|
|
86
|
+
color: orange;
|
|
87
|
+
@supports (display: grid) {
|
|
88
|
+
color: blue;
|
|
89
|
+
`, [
|
|
90
|
+
"@media (min-width: 640px)"
|
|
91
|
+
])).toEqual({
|
|
92
|
+
empty: false,
|
|
93
|
+
unknownSelector: false,
|
|
94
|
+
insideCssValue: false,
|
|
95
|
+
currentNestingScopes: [
|
|
96
|
+
"@media (min-width: 640px)",
|
|
97
|
+
".foo",
|
|
98
|
+
".bar",
|
|
99
|
+
"@supports (display: grid)",
|
|
100
|
+
],
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("should find nesting scopes with properties and closing nestings", () => {
|
|
105
|
+
expect(quasiClassifier(`
|
|
106
|
+
.foo {
|
|
107
|
+
/* }}}}} */
|
|
108
|
+
color: purple;
|
|
109
|
+
.x {
|
|
110
|
+
color: green;
|
|
111
|
+
}
|
|
112
|
+
.bar {
|
|
113
|
+
:before {
|
|
114
|
+
content: '{';
|
|
115
|
+
}
|
|
116
|
+
color: orange;
|
|
117
|
+
@supports (display: grid) {
|
|
118
|
+
color: blue;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
`, [
|
|
122
|
+
"@media (min-width: 640px)"
|
|
123
|
+
])).toEqual({
|
|
124
|
+
empty: false,
|
|
125
|
+
unknownSelector: false,
|
|
126
|
+
insideCssValue: false,
|
|
127
|
+
currentNestingScopes: [
|
|
128
|
+
"@media (min-width: 640px)",
|
|
129
|
+
".foo",
|
|
130
|
+
],
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
});
|
|
@@ -166,13 +166,12 @@ const FancyButton = styled(Button)\`
|
|
|
166
166
|
const FancyButton = styled(Button)(__styleYak.FancyButton_2);"
|
|
167
167
|
`);
|
|
168
168
|
});
|
|
169
|
-
});
|
|
170
169
|
|
|
171
|
-
it("should support attrs on intrinsic elements", async () => {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
170
|
+
it("should support attrs on intrinsic elements", async () => {
|
|
171
|
+
expect(
|
|
172
|
+
await tsloader.call(
|
|
173
|
+
loaderContext,
|
|
174
|
+
`
|
|
176
175
|
import { styled } from "next-yak";
|
|
177
176
|
|
|
178
177
|
const headline = styled.input.attrs({
|
|
@@ -181,21 +180,21 @@ const headline = styled.input.attrs({
|
|
|
181
180
|
color: red;
|
|
182
181
|
\`;
|
|
183
182
|
`
|
|
184
|
-
|
|
185
|
-
|
|
183
|
+
)
|
|
184
|
+
).toMatchInlineSnapshot(`
|
|
186
185
|
"import { styled } from \\"next-yak\\";
|
|
187
186
|
import __styleYak from \\"./page.yak.module.css!=!./page?./page.yak.module.css\\";
|
|
188
187
|
const headline = styled.input.attrs({
|
|
189
188
|
type: \\"text\\"
|
|
190
189
|
})(__styleYak.headline_0);"
|
|
191
190
|
`);
|
|
192
|
-
});
|
|
191
|
+
});
|
|
193
192
|
|
|
194
|
-
it("should support attrs on wrapped elements", async () => {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
193
|
+
it("should support attrs on wrapped elements", async () => {
|
|
194
|
+
expect(
|
|
195
|
+
await tsloader.call(
|
|
196
|
+
loaderContext,
|
|
197
|
+
`
|
|
199
198
|
import { styled } from "next-yak";
|
|
200
199
|
|
|
201
200
|
const headline = styled.input\`
|
|
@@ -208,8 +207,8 @@ const newHeadline = styled(headline).attrs({
|
|
|
208
207
|
color: black;
|
|
209
208
|
\`;
|
|
210
209
|
`
|
|
211
|
-
|
|
212
|
-
|
|
210
|
+
)
|
|
211
|
+
).toMatchInlineSnapshot(`
|
|
213
212
|
"import { styled } from \\"next-yak\\";
|
|
214
213
|
import __styleYak from \\"./page.yak.module.css!=!./page?./page.yak.module.css\\";
|
|
215
214
|
const headline = styled.input(__styleYak.headline_0);
|
|
@@ -217,13 +216,13 @@ const newHeadline = styled(headline).attrs({
|
|
|
217
216
|
type: \\"text\\"
|
|
218
217
|
})(__styleYak.newHeadline_1);"
|
|
219
218
|
`);
|
|
220
|
-
});
|
|
219
|
+
});
|
|
221
220
|
|
|
222
|
-
it("should support css variables with spaces", async () => {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
221
|
+
it("should support css variables with spaces", async () => {
|
|
222
|
+
expect(
|
|
223
|
+
await tsloader.call(
|
|
224
|
+
loaderContext,
|
|
225
|
+
`
|
|
227
226
|
import styles from "./page.module.css";
|
|
228
227
|
import { css } from "next-yak";
|
|
229
228
|
import { easing } from "styleguide";
|
|
@@ -235,8 +234,8 @@ const headline = css\`
|
|
|
235
234
|
\${css\`color: blue\`}
|
|
236
235
|
\`;
|
|
237
236
|
`
|
|
238
|
-
|
|
239
|
-
|
|
237
|
+
)
|
|
238
|
+
).toMatchInlineSnapshot(`
|
|
240
239
|
"import styles from \\"./page.module.css\\";
|
|
241
240
|
import { css } from \\"next-yak\\";
|
|
242
241
|
import __styleYak from \\"./page.yak.module.css!=!./page?./page.yak.module.css\\";
|
|
@@ -250,13 +249,13 @@ const headline = css\`
|
|
|
250
249
|
}
|
|
251
250
|
});"
|
|
252
251
|
`);
|
|
253
|
-
});
|
|
252
|
+
});
|
|
254
253
|
|
|
255
|
-
it("should convert keyframes", async () => {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
254
|
+
it("should convert keyframes", async () => {
|
|
255
|
+
expect(
|
|
256
|
+
await tsloader.call(
|
|
257
|
+
loaderContext,
|
|
258
|
+
`
|
|
260
259
|
import styles from "./page.module.css";
|
|
261
260
|
import { styled, keyframes } from "next-yak";
|
|
262
261
|
|
|
@@ -273,8 +272,8 @@ const FadeInButton = styled.button\`
|
|
|
273
272
|
animation: 1s \${fadeIn} ease-out;
|
|
274
273
|
\`
|
|
275
274
|
`
|
|
276
|
-
|
|
277
|
-
|
|
275
|
+
)
|
|
276
|
+
).toMatchInlineSnapshot(`
|
|
278
277
|
"import styles from \\"./page.module.css\\";
|
|
279
278
|
import { styled, keyframes } from \\"next-yak\\";
|
|
280
279
|
import __styleYak from \\"./page.yak.module.css!=!./page?./page.yak.module.css\\";
|
|
@@ -285,13 +284,13 @@ const FadeInButton = styled.button\`
|
|
|
285
284
|
}
|
|
286
285
|
});"
|
|
287
286
|
`);
|
|
288
|
-
});
|
|
287
|
+
});
|
|
289
288
|
|
|
290
|
-
it("should allow to target components", async () => {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
289
|
+
it("should allow to target components", async () => {
|
|
290
|
+
expect(
|
|
291
|
+
await tsloader.call(
|
|
292
|
+
loaderContext,
|
|
293
|
+
`
|
|
295
294
|
import { styled, keyframes } from "next-yak";
|
|
296
295
|
|
|
297
296
|
const Link = styled.a\`
|
|
@@ -317,21 +316,21 @@ const Wrapper = styled.div\`
|
|
|
317
316
|
\`
|
|
318
317
|
|
|
319
318
|
`
|
|
320
|
-
|
|
321
|
-
|
|
319
|
+
)
|
|
320
|
+
).toMatchInlineSnapshot(`
|
|
322
321
|
"import { styled, keyframes } from \\"next-yak\\";
|
|
323
322
|
import __styleYak from \\"./page.yak.module.css!=!./page?./page.yak.module.css\\";
|
|
324
323
|
const Link = styled.a(__styleYak.Link_0);
|
|
325
324
|
const Icon = styled.svg(__styleYak.Icon_1);
|
|
326
325
|
const Wrapper = styled.div(__styleYak.Wrapper_2);"
|
|
327
326
|
`);
|
|
328
|
-
});
|
|
327
|
+
});
|
|
329
328
|
|
|
330
|
-
it("should allow to target components even if they don't have styles", async () => {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
329
|
+
it("should allow to target components even if they don't have styles", async () => {
|
|
330
|
+
expect(
|
|
331
|
+
await tsloader.call(
|
|
332
|
+
loaderContext,
|
|
333
|
+
`
|
|
335
334
|
import { styled, keyframes } from "next-yak";
|
|
336
335
|
|
|
337
336
|
const Link = styled.a\`
|
|
@@ -347,12 +346,65 @@ const Wrapper = styled.div\`
|
|
|
347
346
|
\`
|
|
348
347
|
|
|
349
348
|
`
|
|
350
|
-
|
|
351
|
-
|
|
349
|
+
)
|
|
350
|
+
).toMatchInlineSnapshot(`
|
|
352
351
|
"import { styled, keyframes } from \\"next-yak\\";
|
|
353
352
|
import __styleYak from \\"./page.yak.module.css!=!./page?./page.yak.module.css\\";
|
|
354
353
|
const Link = styled.a();
|
|
355
354
|
const Icon = styled.svg(__styleYak.Icon_1);
|
|
356
355
|
const Wrapper = styled.div(__styleYak.Wrapper_2);"
|
|
357
356
|
`);
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
it("should show error when mixin is used in nested selector", async () => {
|
|
360
|
+
await expect(() =>
|
|
361
|
+
tsloader.call(
|
|
362
|
+
loaderContext,
|
|
363
|
+
`
|
|
364
|
+
import { styled, css } from "next-yak";
|
|
365
|
+
|
|
366
|
+
const bold = css\`
|
|
367
|
+
font-weight: bold;
|
|
368
|
+
\`
|
|
369
|
+
|
|
370
|
+
const Icon = styled.div\`
|
|
371
|
+
@media (min-width: 640px) {
|
|
372
|
+
.bar {
|
|
373
|
+
\${bold}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
\`
|
|
377
|
+
`
|
|
378
|
+
)
|
|
379
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(`
|
|
380
|
+
"/some/special/path/page.tsx: Expressions are not allowed inside nested selectors:
|
|
381
|
+
line 11: found \\"bold\\" inside \\"@media (min-width: 640px) { .bar {\\""
|
|
382
|
+
`);
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
it("should show error when mixin is used in nested selector inside a css", async () => {
|
|
386
|
+
await expect(() =>
|
|
387
|
+
tsloader.call(
|
|
388
|
+
loaderContext,
|
|
389
|
+
`
|
|
390
|
+
import { styled, css } from "next-yak";
|
|
391
|
+
|
|
392
|
+
const bold = css\`
|
|
393
|
+
font-weight: bold;
|
|
394
|
+
\`
|
|
395
|
+
|
|
396
|
+
const Icon = styled.div\`
|
|
397
|
+
@media (min-width: 640px) {
|
|
398
|
+
.bar {
|
|
399
|
+
\${() => css\`\${bold}\`}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
\`
|
|
403
|
+
`
|
|
404
|
+
)
|
|
405
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(`
|
|
406
|
+
"/some/special/path/page.tsx: Expressions are not allowed inside nested selectors:
|
|
407
|
+
line 11: found Expression inside \\"@media (min-width: 640px) { .bar {\\""
|
|
408
|
+
`);
|
|
409
|
+
});
|
|
358
410
|
});
|
|
@@ -62,9 +62,9 @@ module.exports = function (babel, options) {
|
|
|
62
62
|
t.importDeclaration(
|
|
63
63
|
[t.importDefaultSpecifier(t.identifier("__styleYak"))],
|
|
64
64
|
t.stringLiteral(
|
|
65
|
-
`./${fileName}.yak.module.css!=!./${fileName}?./${fileName}.yak.module.css
|
|
66
|
-
)
|
|
67
|
-
)
|
|
65
|
+
`./${fileName}.yak.module.css!=!./${fileName}?./${fileName}.yak.module.css`,
|
|
66
|
+
),
|
|
67
|
+
),
|
|
68
68
|
);
|
|
69
69
|
|
|
70
70
|
// Process import specifiers
|
|
@@ -115,7 +115,7 @@ module.exports = function (babel, options) {
|
|
|
115
115
|
const isStyledLiteral =
|
|
116
116
|
t.isMemberExpression(tag) &&
|
|
117
117
|
t.isIdentifier(
|
|
118
|
-
/** @type {babel.types.MemberExpression} */ (tag).object
|
|
118
|
+
/** @type {babel.types.MemberExpression} */ (tag).object,
|
|
119
119
|
) &&
|
|
120
120
|
/** @type {babel.types.Identifier} */ (
|
|
121
121
|
/** @type {babel.types.MemberExpression} */ (tag).object
|
|
@@ -123,7 +123,7 @@ module.exports = function (babel, options) {
|
|
|
123
123
|
const isStyledCall =
|
|
124
124
|
t.isCallExpression(tag) &&
|
|
125
125
|
t.isIdentifier(
|
|
126
|
-
/** @type {babel.types.CallExpression} */ (tag).callee
|
|
126
|
+
/** @type {babel.types.CallExpression} */ (tag).callee,
|
|
127
127
|
) &&
|
|
128
128
|
/** @type {babel.types.Identifier} */ (
|
|
129
129
|
/** @type {babel.types.CallExpression} */ (tag).callee
|
|
@@ -169,15 +169,15 @@ module.exports = function (babel, options) {
|
|
|
169
169
|
astNode.arguments.push(
|
|
170
170
|
t.memberExpression(
|
|
171
171
|
t.identifier("__styleYak"),
|
|
172
|
-
t.identifier(className)
|
|
173
|
-
)
|
|
172
|
+
t.identifier(className),
|
|
173
|
+
),
|
|
174
174
|
);
|
|
175
175
|
}
|
|
176
176
|
return className;
|
|
177
177
|
}
|
|
178
178
|
return false;
|
|
179
179
|
},
|
|
180
|
-
t
|
|
180
|
+
t,
|
|
181
181
|
);
|
|
182
182
|
|
|
183
183
|
let literalSelectorWasUsed = false;
|
|
@@ -189,17 +189,21 @@ module.exports = function (babel, options) {
|
|
|
189
189
|
localIdent(
|
|
190
190
|
variableName,
|
|
191
191
|
literalSelectorIndex,
|
|
192
|
-
isKeyframesLiteral ? "animation" : "className"
|
|
193
|
-
)
|
|
194
|
-
)
|
|
192
|
+
isKeyframesLiteral ? "animation" : "className",
|
|
193
|
+
),
|
|
194
|
+
),
|
|
195
195
|
);
|
|
196
196
|
|
|
197
197
|
// Replace the tagged template expression with a call to the 'styled' function
|
|
198
198
|
const newArguments = new Set();
|
|
199
199
|
const quasis = path.node.quasi.quasis;
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
)
|
|
200
|
+
/** @type {string[]} */
|
|
201
|
+
let currentNestingScopes = [];
|
|
202
|
+
const quasiTypes = quasis.map((quasi) => {
|
|
203
|
+
const classification = quasiClassifier(quasi.value.raw, currentNestingScopes);
|
|
204
|
+
currentNestingScopes = classification.currentNestingScopes;
|
|
205
|
+
return classification;
|
|
206
|
+
});
|
|
203
207
|
const expressions = path.node.quasi.expressions;
|
|
204
208
|
|
|
205
209
|
let cssVariablesInlineStyle;
|
|
@@ -226,8 +230,8 @@ module.exports = function (babel, options) {
|
|
|
226
230
|
const type = quasiTypes[i];
|
|
227
231
|
// expressions after a partial css are converted into css variables
|
|
228
232
|
if (
|
|
229
|
-
type.
|
|
230
|
-
type.
|
|
233
|
+
type.unknownSelector ||
|
|
234
|
+
type.insideCssValue ||
|
|
231
235
|
(isMerging && type.empty)
|
|
232
236
|
) {
|
|
233
237
|
isMerging = true;
|
|
@@ -249,7 +253,7 @@ module.exports = function (babel, options) {
|
|
|
249
253
|
}
|
|
250
254
|
const relativePath = relative(
|
|
251
255
|
rootContext,
|
|
252
|
-
resolve(rootContext, resourcePath)
|
|
256
|
+
resolve(rootContext, resourcePath),
|
|
253
257
|
);
|
|
254
258
|
hashedFile = murmurhash2_32_gc(relativePath);
|
|
255
259
|
}
|
|
@@ -257,14 +261,23 @@ module.exports = function (babel, options) {
|
|
|
257
261
|
cssVariablesInlineStyle.properties.push(
|
|
258
262
|
t.objectProperty(
|
|
259
263
|
t.stringLiteral(`--🦬${hashedFile}${this.varIndex++}`),
|
|
260
|
-
/** @type {babel.types.Expression} */ (expression)
|
|
261
|
-
)
|
|
264
|
+
/** @type {babel.types.Expression} */ (expression),
|
|
265
|
+
),
|
|
262
266
|
);
|
|
263
267
|
} else if (type.empty) {
|
|
264
|
-
// empty quasis can be ignored
|
|
268
|
+
// empty quasis can be ignored in typescript
|
|
265
269
|
// e.g. `transition: color ${duration} ${easing};`
|
|
270
|
+
// ^
|
|
266
271
|
} else {
|
|
267
272
|
if (expressions[i]) {
|
|
273
|
+
if (quasiTypes[i].currentNestingScopes.length > 0) {
|
|
274
|
+
const errorExpression = expressions[i];
|
|
275
|
+
const name = errorExpression.type === "Identifier" ? `"${errorExpression.name}"` : "Expression";
|
|
276
|
+
const line = errorExpression.loc?.start.line || -1
|
|
277
|
+
throw new InvalidPositionError(
|
|
278
|
+
`Expressions are not allowed inside nested selectors:\n${line !== -1 ? `line ${line}: ` : ""}found ${name} inside "${quasiTypes[i].currentNestingScopes.join(" { ")} {"`,
|
|
279
|
+
);
|
|
280
|
+
}
|
|
268
281
|
newArguments.add(expressions[i]);
|
|
269
282
|
}
|
|
270
283
|
break;
|
|
@@ -277,9 +290,9 @@ module.exports = function (babel, options) {
|
|
|
277
290
|
t.objectExpression([
|
|
278
291
|
t.objectProperty(
|
|
279
292
|
t.stringLiteral(`style`),
|
|
280
|
-
cssVariablesInlineStyle
|
|
293
|
+
cssVariablesInlineStyle,
|
|
281
294
|
),
|
|
282
|
-
])
|
|
295
|
+
]),
|
|
283
296
|
);
|
|
284
297
|
}
|
|
285
298
|
|
|
@@ -294,7 +307,7 @@ module.exports = function (babel, options) {
|
|
|
294
307
|
className: localIdent(
|
|
295
308
|
variableName,
|
|
296
309
|
literalSelectorIndex,
|
|
297
|
-
"className"
|
|
310
|
+
"className",
|
|
298
311
|
),
|
|
299
312
|
astNode: styledCall,
|
|
300
313
|
});
|
|
@@ -303,3 +316,14 @@ module.exports = function (babel, options) {
|
|
|
303
316
|
},
|
|
304
317
|
};
|
|
305
318
|
};
|
|
319
|
+
|
|
320
|
+
class InvalidPositionError extends Error {
|
|
321
|
+
/**
|
|
322
|
+
* @param {string} message
|
|
323
|
+
*/
|
|
324
|
+
constructor(message) {
|
|
325
|
+
super(message);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
module.exports.InvalidPositionError = InvalidPositionError;
|
package/loaders/cssloader.cjs
CHANGED
|
@@ -34,7 +34,7 @@ module.exports = async function cssLoader(source) {
|
|
|
34
34
|
imports.forEach(({ localName, importedName }) => {
|
|
35
35
|
replaces[localName] = constantValues[importedName];
|
|
36
36
|
});
|
|
37
|
-
})
|
|
37
|
+
}),
|
|
38
38
|
);
|
|
39
39
|
|
|
40
40
|
// parse source with babel
|
|
@@ -127,7 +127,7 @@ module.exports = async function cssLoader(source) {
|
|
|
127
127
|
const isStyledLiteral =
|
|
128
128
|
t.isMemberExpression(tag) &&
|
|
129
129
|
t.isIdentifier(
|
|
130
|
-
/** @type {babel.types.MemberExpression} */ (tag).object
|
|
130
|
+
/** @type {babel.types.MemberExpression} */ (tag).object,
|
|
131
131
|
) &&
|
|
132
132
|
/** @type {babel.types.Identifier} */ (
|
|
133
133
|
/** @type {babel.types.MemberExpression} */ (tag).object
|
|
@@ -136,7 +136,7 @@ module.exports = async function cssLoader(source) {
|
|
|
136
136
|
const isStyledCall =
|
|
137
137
|
t.isCallExpression(tag) &&
|
|
138
138
|
t.isIdentifier(
|
|
139
|
-
/** @type {babel.types.CallExpression} */ (tag).callee
|
|
139
|
+
/** @type {babel.types.CallExpression} */ (tag).callee,
|
|
140
140
|
) &&
|
|
141
141
|
/** @type {babel.types.Identifier} */ (
|
|
142
142
|
/** @type {babel.types.CallExpression} */ (tag).callee
|
|
@@ -176,7 +176,7 @@ module.exports = async function cssLoader(source) {
|
|
|
176
176
|
}
|
|
177
177
|
return false;
|
|
178
178
|
},
|
|
179
|
-
t
|
|
179
|
+
t,
|
|
180
180
|
);
|
|
181
181
|
|
|
182
182
|
// Keep the same selector for all quasis belonging to the same css block
|
|
@@ -184,14 +184,12 @@ module.exports = async function cssLoader(source) {
|
|
|
184
184
|
const literalSelector = localIdent(
|
|
185
185
|
variableName,
|
|
186
186
|
literalSelectorIndex,
|
|
187
|
-
isKeyFrameLiteral ? "keyframes" : "selector"
|
|
187
|
+
isKeyFrameLiteral ? "keyframes" : "selector",
|
|
188
188
|
);
|
|
189
189
|
|
|
190
190
|
// Replace the tagged template expression with a call to the 'styled' function
|
|
191
191
|
const quasis = path.node.quasi.quasis;
|
|
192
|
-
const quasiTypes = quasis.map((quasi) =>
|
|
193
|
-
quasiClassifier(quasi.value.raw)
|
|
194
|
-
);
|
|
192
|
+
const quasiTypes = quasis.map((quasi) => quasiClassifier(quasi.value.raw, []));
|
|
195
193
|
|
|
196
194
|
for (let i = 0; i < quasis.length; i++) {
|
|
197
195
|
const quasi = quasis[i];
|
|
@@ -206,8 +204,8 @@ module.exports = async function cssLoader(source) {
|
|
|
206
204
|
const type = quasiTypes[i];
|
|
207
205
|
// expressions after a partial css are converted into css variables
|
|
208
206
|
if (
|
|
209
|
-
type.
|
|
210
|
-
type.
|
|
207
|
+
type.unknownSelector ||
|
|
208
|
+
type.insideCssValue ||
|
|
211
209
|
(isMerging && type.empty)
|
|
212
210
|
) {
|
|
213
211
|
isMerging = true;
|
|
@@ -243,7 +241,7 @@ module.exports = async function cssLoader(source) {
|
|
|
243
241
|
if (isStyledLiteral || isStyledCall || isAttrsCall) {
|
|
244
242
|
variableNameToStyledClassName.set(
|
|
245
243
|
variableName,
|
|
246
|
-
localIdent(variableName, literalSelectorIndex, "selector")
|
|
244
|
+
localIdent(variableName, literalSelectorIndex, "selector"),
|
|
247
245
|
);
|
|
248
246
|
}
|
|
249
247
|
},
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
const getStyledComponentName = (taggedTemplateExpressionPath) => {
|
|
15
15
|
const variableDeclaratorPath = taggedTemplateExpressionPath.findParent(
|
|
16
|
-
(path) => path.isVariableDeclarator()
|
|
16
|
+
(path) => path.isVariableDeclarator(),
|
|
17
17
|
);
|
|
18
18
|
if (
|
|
19
19
|
!variableDeclaratorPath ||
|
|
@@ -22,7 +22,7 @@ const getStyledComponentName = (taggedTemplateExpressionPath) => {
|
|
|
22
22
|
) {
|
|
23
23
|
throw new Error(
|
|
24
24
|
"Could not find variable declaration for styled component at " +
|
|
25
|
-
taggedTemplateExpressionPath.node.loc
|
|
25
|
+
taggedTemplateExpressionPath.node.loc,
|
|
26
26
|
);
|
|
27
27
|
}
|
|
28
28
|
return variableDeclaratorPath.node.id.name;
|
|
@@ -1,38 +1,47 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
/**
|
|
3
3
|
* Finds all imports in a given code string which import from a .yak file
|
|
4
|
-
*
|
|
4
|
+
*
|
|
5
5
|
* Uses regex to work with typescript and javascript
|
|
6
6
|
* Does not support lazy imports
|
|
7
|
-
*
|
|
7
|
+
*
|
|
8
8
|
* @param {string} code
|
|
9
9
|
* @returns { { imports: { localName: string, importedName: string }[], from: string }[] }
|
|
10
10
|
*/
|
|
11
11
|
const getYakImports = (code) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return {
|
|
25
|
-
|
|
12
|
+
const codeWithoutComments = code.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
13
|
+
const allImports = codeWithoutComments.matchAll(
|
|
14
|
+
/(^|\n|;)\s*import\s+(?:(\w+(?:\s+as\s+\w+)?)\s*,?\s*)?(?:{([^}]*)})?\s+from\s+["']([^'"]+\.yak)["'](;|\n)/g,
|
|
15
|
+
);
|
|
16
|
+
return [...allImports].map(([, , defaultImport, namedImports, from]) => {
|
|
17
|
+
// parse named imports to { localName: string, importedName: string }[]
|
|
18
|
+
const imports =
|
|
19
|
+
namedImports?.split(",").map((namedImport) => {
|
|
20
|
+
const [importedName, localName = importedName] = namedImport
|
|
21
|
+
.replace(/^type\s+/, "")
|
|
22
|
+
.trim()
|
|
23
|
+
.split(/\s+as\s+/);
|
|
24
|
+
return { localName, importedName };
|
|
25
|
+
}) ?? [];
|
|
26
|
+
// parse default import to { localName: string, importedName: string }[]
|
|
27
|
+
if (defaultImport) {
|
|
28
|
+
imports.push(parseDefaultImport(defaultImport));
|
|
29
|
+
}
|
|
30
|
+
return { imports, from };
|
|
31
|
+
});
|
|
26
32
|
};
|
|
27
33
|
|
|
28
34
|
/**
|
|
29
35
|
* Parses a default import string
|
|
30
36
|
* @param {string} defaultImport
|
|
31
37
|
* @returns {{ localName: string, importedName: string }}
|
|
32
|
-
*/
|
|
38
|
+
*/
|
|
33
39
|
function parseDefaultImport(defaultImport) {
|
|
34
|
-
|
|
35
|
-
|
|
40
|
+
const defaultImportArray = defaultImport.split(/\s+as\s+/);
|
|
41
|
+
return {
|
|
42
|
+
localName: defaultImportArray[1] ?? defaultImportArray[0],
|
|
43
|
+
importedName: defaultImportArray[0],
|
|
44
|
+
};
|
|
36
45
|
}
|
|
37
46
|
|
|
38
|
-
module.exports = getYakImports;
|
|
47
|
+
module.exports = getYakImports;
|
|
@@ -3,31 +3,85 @@ const stripCssComments = require("./stripCssComments.cjs");
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Checks a quasiValue and returns its type
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
7
|
* - empty: no expressions, no text
|
|
8
|
-
* -
|
|
9
|
-
* -
|
|
10
|
-
*
|
|
11
|
-
* @param {string} quasiValue
|
|
8
|
+
* - unknownSelector: starts with a `{` e.g. `{ opacity: 0.5; }`
|
|
9
|
+
* - 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
|
+
*
|
|
12
14
|
* @returns {{
|
|
13
15
|
* empty: boolean,
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
+
* unknownSelector: boolean,
|
|
17
|
+
* insideCssValue: boolean,
|
|
18
|
+
* currentNestingScopes: string[],
|
|
16
19
|
* }}
|
|
17
20
|
*/
|
|
18
|
-
module.exports = function quasiClassifier(quasiValue) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
partialStart: false,
|
|
24
|
-
partialEnd: false,
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
21
|
+
module.exports = function quasiClassifier(quasiValue, currentNestingScopes) {
|
|
22
|
+
// TODO - for better performance we could move the comment skipping logic
|
|
23
|
+
// directly in the for loop below instead of calling stripCssComments
|
|
24
|
+
const trimmedCssString = stripCssComments(quasiValue).trim();
|
|
25
|
+
if (trimmedCssString === "") {
|
|
28
26
|
return {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
empty: true,
|
|
28
|
+
unknownSelector: false,
|
|
29
|
+
insideCssValue: false,
|
|
30
|
+
currentNestingScopes,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** @type {'"' | "'" | false} */
|
|
34
|
+
let isInsideString = false;
|
|
35
|
+
let currentCharacter = "";
|
|
36
|
+
let newNestingLevel = [...currentNestingScopes];
|
|
37
|
+
let currentSelector = "";
|
|
38
|
+
for (let index = 0; index < trimmedCssString.length; index++) {
|
|
39
|
+
currentCharacter = trimmedCssString[index];
|
|
40
|
+
if (
|
|
41
|
+
trimmedCssString[index - 1] !== "\\" &&
|
|
42
|
+
(currentCharacter === '"' || currentCharacter === "'")
|
|
43
|
+
) {
|
|
44
|
+
if (isInsideString === currentCharacter) {
|
|
45
|
+
isInsideString = false;
|
|
46
|
+
} else if (!isInsideString) {
|
|
47
|
+
isInsideString = currentCharacter;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (isInsideString) {
|
|
51
|
+
continue;
|
|
32
52
|
}
|
|
33
|
-
|
|
53
|
+
if (currentCharacter === "{") {
|
|
54
|
+
const selector = currentSelector.trim();
|
|
55
|
+
if (selector !== "") {
|
|
56
|
+
newNestingLevel.push(selector);
|
|
57
|
+
}
|
|
58
|
+
// after an opening bracket a new selector might start e.g.:
|
|
59
|
+
// .class {
|
|
60
|
+
// .nested-class {
|
|
61
|
+
currentSelector = "";
|
|
62
|
+
} else if (currentCharacter === "}") {
|
|
63
|
+
newNestingLevel.pop();
|
|
64
|
+
// after a closing bracket a new selector might start e.g.:
|
|
65
|
+
// .class {
|
|
66
|
+
// color: red;
|
|
67
|
+
// }
|
|
68
|
+
// .other-class {
|
|
69
|
+
currentSelector = "";
|
|
70
|
+
} else if (currentCharacter === ";") {
|
|
71
|
+
// after a semi-colon a nested selector might start e.g.:
|
|
72
|
+
// .class {
|
|
73
|
+
// color: red;
|
|
74
|
+
// .nested-class {
|
|
75
|
+
currentSelector = "";
|
|
76
|
+
} else {
|
|
77
|
+
currentSelector += currentCharacter;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
empty: false,
|
|
83
|
+
unknownSelector: trimmedCssString[0] === "{",
|
|
84
|
+
insideCssValue: currentCharacter !== "{" && currentCharacter !== "}" && currentCharacter !== ";",
|
|
85
|
+
currentNestingScopes: newNestingLevel,
|
|
86
|
+
};
|
|
87
|
+
};
|
|
@@ -35,10 +35,13 @@ module.exports = function replaceTokensInQuasiExpressions(quasi, replacer, t) {
|
|
|
35
35
|
}
|
|
36
36
|
replaceExpressionAndMergeQuasis(quasi, i, replacement);
|
|
37
37
|
i--;
|
|
38
|
-
}
|
|
38
|
+
}
|
|
39
39
|
// replace member expressions e.g. ${query.xs}
|
|
40
40
|
// replace deeply nested member expressions e.g. ${query.xs.min}
|
|
41
|
-
else if (
|
|
41
|
+
else if (
|
|
42
|
+
t.isMemberExpression(expression) &&
|
|
43
|
+
t.isIdentifier(expression.object)
|
|
44
|
+
) {
|
|
42
45
|
/** @type {any} */
|
|
43
46
|
let replacement = replacer(expression.object.name);
|
|
44
47
|
if (replacement === false) {
|
|
@@ -60,7 +63,7 @@ module.exports = function replaceTokensInQuasiExpressions(quasi, replacer, t) {
|
|
|
60
63
|
i--;
|
|
61
64
|
}
|
|
62
65
|
}
|
|
63
|
-
}
|
|
66
|
+
};
|
|
64
67
|
|
|
65
68
|
/**
|
|
66
69
|
* Replace tokens with predefined values
|
|
@@ -69,9 +72,16 @@ module.exports = function replaceTokensInQuasiExpressions(quasi, replacer, t) {
|
|
|
69
72
|
* @param {unknown} replacement
|
|
70
73
|
*/
|
|
71
74
|
function replaceExpressionAndMergeQuasis(quasi, expressionIndex, replacement) {
|
|
72
|
-
const stringReplacement =
|
|
75
|
+
const stringReplacement =
|
|
76
|
+
typeof replacement === "string"
|
|
77
|
+
? replacement
|
|
78
|
+
: replacement == null
|
|
79
|
+
? ""
|
|
80
|
+
: JSON.stringify(replacement);
|
|
73
81
|
quasi.expressions.splice(expressionIndex, 1);
|
|
74
|
-
quasi.quasis[expressionIndex].value.raw +=
|
|
75
|
-
|
|
82
|
+
quasi.quasis[expressionIndex].value.raw +=
|
|
83
|
+
stringReplacement + quasi.quasis[expressionIndex + 1].value.raw;
|
|
84
|
+
quasi.quasis[expressionIndex].value.cooked +=
|
|
85
|
+
stringReplacement + quasi.quasis[expressionIndex + 1].value.cooked;
|
|
76
86
|
quasi.quasis.splice(expressionIndex + 1, 1);
|
|
77
|
-
}
|
|
87
|
+
}
|
|
@@ -1,51 +1,58 @@
|
|
|
1
1
|
/// @ts-check
|
|
2
2
|
// from https://github.com/sindresorhus/strip-css-comments/tree/main
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
* @param {string} cssString
|
|
4
|
+
*
|
|
5
|
+
* @param {string} cssString
|
|
6
6
|
*/
|
|
7
7
|
module.exports = function stripCssComments(cssString) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
/** @type {string | false} */
|
|
9
|
+
let isInsideString = false;
|
|
10
|
+
let currentCharacter = "";
|
|
11
|
+
let comment = "";
|
|
12
|
+
let returnValue = "";
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
for (let index = 0; index < cssString.length; index++) {
|
|
15
|
+
currentCharacter = cssString[index];
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
if (
|
|
18
|
+
cssString[index - 1] !== "\\" &&
|
|
19
|
+
(currentCharacter === '"' || currentCharacter === "'")
|
|
20
|
+
) {
|
|
21
|
+
if (isInsideString === currentCharacter) {
|
|
22
|
+
isInsideString = false;
|
|
23
|
+
} else if (!isInsideString) {
|
|
24
|
+
isInsideString = currentCharacter;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
// Find beginning of `/*` type comment
|
|
29
|
+
if (
|
|
30
|
+
!isInsideString &&
|
|
31
|
+
currentCharacter === "/" &&
|
|
32
|
+
cssString[index + 1] === "*"
|
|
33
|
+
) {
|
|
34
|
+
let index2 = index + 2;
|
|
28
35
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
36
|
+
// Iterate over comment
|
|
37
|
+
for (; index2 < cssString.length; index2++) {
|
|
38
|
+
// Find end of comment
|
|
39
|
+
if (cssString[index2] === "*" && cssString[index2 + 1] === "/") {
|
|
40
|
+
if (cssString[index2 + 2] === "\n") {
|
|
41
|
+
index2++;
|
|
42
|
+
} else if (cssString[index2 + 2] + cssString[index2 + 3] === "\r\n") {
|
|
43
|
+
index2 += 2;
|
|
44
|
+
}
|
|
45
|
+
comment = "";
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
// Store comment text
|
|
49
|
+
comment += cssString[index2];
|
|
50
|
+
}
|
|
51
|
+
// Resume iteration over CSS string from the end of the comment
|
|
52
|
+
index = index2 + 1;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
returnValue += currentCharacter;
|
|
56
|
+
}
|
|
57
|
+
return returnValue;
|
|
58
|
+
};
|
package/loaders/tsloader.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// @ts-check
|
|
2
2
|
const babel = require("@babel/core");
|
|
3
3
|
const getYakImports = require("./lib/getYakImports.cjs");
|
|
4
|
+
const InvalidPositionError = require("./babel-yak-plugin.cjs").InvalidPositionError;
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Loader for typescript files that use yak, it replaces the css template literal with a call to the 'styled' function
|
|
@@ -20,34 +21,49 @@ module.exports = async function tsloader(source) {
|
|
|
20
21
|
const isYakFile = /\.yak\.(j|t)sx?$/.test(resourcePath.matches);
|
|
21
22
|
// The user may import constants from a .yak file
|
|
22
23
|
// e.g. import { primary } from './colors.yak'
|
|
23
|
-
//
|
|
24
|
+
//
|
|
24
25
|
// However .yak files inside .yak files are not be compiled
|
|
25
26
|
// to avoid performance overhead
|
|
26
|
-
const importedYakConstantNames = isYakFile
|
|
27
|
-
|
|
27
|
+
const importedYakConstantNames = isYakFile
|
|
28
|
+
? []
|
|
29
|
+
: getYakImports(source)
|
|
30
|
+
.map(({ imports }) => imports.map(({ localName }) => localName))
|
|
31
|
+
.flat(2);
|
|
32
|
+
const replaces = Object.fromEntries(
|
|
33
|
+
importedYakConstantNames.map((name) => [name, null])
|
|
34
|
+
);
|
|
28
35
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
/** @type {babel.BabelFileResult | null} */
|
|
37
|
+
let result = null;
|
|
38
|
+
try {
|
|
39
|
+
// Compile the typescript file with babel - this will:
|
|
40
|
+
// - inject the import to the css-module (with .yak.module.css extension)
|
|
41
|
+
// - replace the css template literal with styles from the css-module
|
|
42
|
+
result = babel.transformSync(source, {
|
|
43
|
+
filename: resourcePath,
|
|
44
|
+
configFile: false,
|
|
45
|
+
plugins: [
|
|
46
|
+
[
|
|
47
|
+
"@babel/plugin-syntax-typescript",
|
|
48
|
+
{ isTSX: this.resourcePath.endsWith(".tsx") },
|
|
49
|
+
],
|
|
50
|
+
[
|
|
51
|
+
require.resolve("./babel-yak-plugin.cjs"),
|
|
52
|
+
{
|
|
53
|
+
replaces,
|
|
54
|
+
rootContext,
|
|
55
|
+
},
|
|
56
|
+
],
|
|
39
57
|
],
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
],
|
|
48
|
-
});
|
|
58
|
+
});
|
|
59
|
+
} catch (error) {
|
|
60
|
+
if (error instanceof InvalidPositionError) {
|
|
61
|
+
return callback(new Error(error.message));
|
|
62
|
+
}
|
|
63
|
+
return callback(new Error("babel transform failed"));
|
|
64
|
+
}
|
|
49
65
|
if (!result?.code) {
|
|
50
|
-
|
|
66
|
+
return callback(new Error("babel transform failed"));
|
|
51
67
|
}
|
|
52
68
|
return callback(null, result.code, result.map);
|
|
53
69
|
};
|