@fremtind/jokul 5.0.0-next.10 → 5.0.0-next.11
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/codemods/CODEMODS.md +133 -0
- package/codemods/__tests__/import-paths.test.mjs +467 -92
- package/codemods/import-paths.mjs +25 -354
- package/codemods/transforms/color-tokens.mjs +77 -0
- package/codemods/transforms/font-family.mjs +23 -0
- package/codemods/transforms/import-specifiers.mjs +230 -0
- package/codemods/transforms/warnings.mjs +41 -0
- package/codemods/utils.mjs +35 -0
- package/package.json +1 -1
- package/styles/base.css +32 -50
- package/styles/base.min.css +1 -1
- package/styles/components/countdown/countdown.css +2 -2
- package/styles/components/countdown/countdown.min.css +1 -1
- package/styles/components/expander/expandable.css +13 -14
- package/styles/components/expander/expandable.min.css +1 -1
- package/styles/components/expander/expandable.scss +16 -17
- package/styles/components/feedback/feedback.css +2 -2
- package/styles/components/feedback/feedback.min.css +1 -1
- package/styles/components/file-input/file-input.css +9 -9
- package/styles/components/file-input/file-input.min.css +1 -1
- package/styles/components/input-group/input-group.css +2 -2
- package/styles/components/input-group/input-group.min.css +1 -1
- package/styles/components/list/list.css +37 -21
- package/styles/components/list/list.min.css +1 -1
- package/styles/components/list/list.scss +27 -23
- package/styles/components/loader/loader.css +6 -6
- package/styles/components/loader/loader.min.css +1 -1
- package/styles/components/loader/skeleton-loader.css +3 -3
- package/styles/components/loader/skeleton-loader.min.css +1 -1
- package/styles/components/message/message.css +2 -2
- package/styles/components/message/message.min.css +1 -1
- package/styles/components/progress-bar/progress-bar.css +1 -1
- package/styles/components/progress-bar/progress-bar.min.css +1 -1
- package/styles/components/segmented-control/segmented-control.css +2 -2
- package/styles/components/segmented-control/segmented-control.min.css +1 -1
- package/styles/components/system-message/system-message.css +2 -2
- package/styles/components/system-message/system-message.min.css +1 -1
- package/styles/components/toast/toast.css +4 -4
- package/styles/components/toast/toast.min.css +1 -1
- package/styles/components/typography/text.scss +2 -2
- package/styles/components/typography/title.scss +2 -2
- package/styles/components.css +74 -59
- package/styles/components.min.css +1 -1
- package/styles/tailwind.css +2 -2
- package/styles/theme/_dynamic-spacing.scss +21 -15
- package/styles/theme/_fonts.scss +3 -12
- package/styles/theme/_size.scss +20 -20
- package/styles/theme/_tokens.scss +11 -11
- package/styles/core/utility/_paragraphs.scss +0 -39
|
@@ -58,71 +58,42 @@ test("migrates internal relative core jkl imports", () => {
|
|
|
58
58
|
test("rewrites beta style imports when the beta component is used in the same file", () => {
|
|
59
59
|
const source = `
|
|
60
60
|
import { BETA_Select } from "@fremtind/jokul/select";
|
|
61
|
-
import "@fremtind/jokul/styles/components/select
|
|
61
|
+
import "@fremtind/jokul/styles/components/select";
|
|
62
62
|
`;
|
|
63
63
|
|
|
64
|
-
const result = transformImportPaths(source, "/tmp/
|
|
64
|
+
const result = transformImportPaths(source, "/tmp/MyForm.tsx");
|
|
65
65
|
|
|
66
66
|
assert.equal(
|
|
67
67
|
result.text.includes(
|
|
68
|
-
'@fremtind/jokul/styles/components/beta/select
|
|
68
|
+
'@fremtind/jokul/styles/components/beta/select',
|
|
69
69
|
),
|
|
70
70
|
true,
|
|
71
71
|
);
|
|
72
72
|
assert.deepEqual(result.warnings, []);
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
-
test("warns when beta style
|
|
75
|
+
test("warns when beta style import is ambiguous (no beta identifier in file)", () => {
|
|
76
76
|
const source = `
|
|
77
|
-
import "@fremtind/jokul/styles/components/
|
|
77
|
+
import "@fremtind/jokul/styles/components/select";
|
|
78
78
|
`;
|
|
79
79
|
|
|
80
|
-
const result = transformImportPaths(source, "/tmp/
|
|
80
|
+
const result = transformImportPaths(source, "/tmp/global.scss");
|
|
81
81
|
|
|
82
|
-
assert.equal(result.changed, false);
|
|
83
82
|
assert.equal(result.warnings.length, 1);
|
|
83
|
+
assert.match(result.warnings[0], /Select/);
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
-
test("removes
|
|
87
|
-
const source = `import "@fremtind/jokul/styles/
|
|
88
|
-
import "@fremtind/jokul/styles/core/core.css";
|
|
86
|
+
test("removes esm webfonts.css import when base or components css is present", () => {
|
|
87
|
+
const source = `import "@fremtind/jokul/styles/base.css";
|
|
89
88
|
import "@fremtind/jokul/styles/fonts/webfonts.css";
|
|
90
89
|
`;
|
|
91
90
|
|
|
92
91
|
const result = transformImportPaths(source, "/tmp/main.tsx");
|
|
93
92
|
|
|
94
|
-
assert.equal(
|
|
95
|
-
result.text.includes("@fremtind/jokul/styles/fonts/webfonts.css"),
|
|
96
|
-
false,
|
|
97
|
-
);
|
|
98
|
-
assert.equal(
|
|
99
|
-
result.text.includes('import "@fremtind/jokul/styles/components.css";'),
|
|
100
|
-
true,
|
|
101
|
-
);
|
|
102
|
-
assert.equal(
|
|
103
|
-
result.text.includes('import "@fremtind/jokul/styles/base.css";'),
|
|
104
|
-
true,
|
|
105
|
-
);
|
|
93
|
+
assert.equal(result.text.includes("webfonts"), false);
|
|
106
94
|
assert.deepEqual(result.warnings, []);
|
|
107
95
|
});
|
|
108
96
|
|
|
109
|
-
test("removes minified webfonts.css imports as well", () => {
|
|
110
|
-
const source = `import "@fremtind/jokul/styles/core/core.min.css";
|
|
111
|
-
import "@fremtind/jokul/styles/fonts/webfonts.min.css";
|
|
112
|
-
`;
|
|
113
|
-
|
|
114
|
-
const result = transformImportPaths(source, "/tmp/main.ts");
|
|
115
|
-
|
|
116
|
-
assert.equal(
|
|
117
|
-
result.text.includes("webfonts"),
|
|
118
|
-
false,
|
|
119
|
-
);
|
|
120
|
-
assert.equal(
|
|
121
|
-
result.text.includes('import "@fremtind/jokul/styles/base.min.css";'),
|
|
122
|
-
true,
|
|
123
|
-
);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
97
|
test("warns when webfonts.css is removed without a base or components import", () => {
|
|
127
98
|
const source = `import "@fremtind/jokul/styles/fonts/webfonts.css";
|
|
128
99
|
`;
|
|
@@ -149,121 +120,525 @@ test("removes css @import of webfonts.css", () => {
|
|
|
149
120
|
assert.deepEqual(result.warnings, []);
|
|
150
121
|
});
|
|
151
122
|
|
|
152
|
-
test("warns about removed sass color variables", () => {
|
|
153
|
-
const source = `@use "@fremtind/jokul/styles/jkl";
|
|
154
123
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
124
|
+
test("renames Fremtind Material Symbols font-family", () => {
|
|
125
|
+
const source = `.icon {
|
|
126
|
+
font-family: "Fremtind Material Symbols", "Fremtind Material Symbols Fallback", sans-serif;
|
|
158
127
|
}
|
|
159
128
|
`;
|
|
160
129
|
|
|
161
|
-
const result = transformImportPaths(source, "/tmp/
|
|
130
|
+
const result = transformImportPaths(source, "/tmp/icons.scss");
|
|
162
131
|
|
|
163
132
|
assert.equal(
|
|
164
|
-
result.
|
|
165
|
-
|
|
133
|
+
result.text.includes("Fremtind Material Symbols"),
|
|
134
|
+
false,
|
|
135
|
+
);
|
|
136
|
+
assert.equal(
|
|
137
|
+
result.text.includes(
|
|
138
|
+
'"Jokul Icons", "Jokul Icons Fallback", sans-serif',
|
|
166
139
|
),
|
|
167
140
|
true,
|
|
168
141
|
);
|
|
169
|
-
|
|
142
|
+
assert.equal(result.replacements, 2);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test("renames Fremtind Material Symbols inside CSS files too", () => {
|
|
146
|
+
const source = `.icon {
|
|
147
|
+
font-family: 'Fremtind Material Symbols';
|
|
148
|
+
}
|
|
149
|
+
`;
|
|
150
|
+
|
|
151
|
+
const result = transformImportPaths(source, "/tmp/icons.css");
|
|
152
|
+
|
|
170
153
|
assert.equal(
|
|
171
|
-
result.
|
|
172
|
-
|
|
173
|
-
).length,
|
|
174
|
-
1,
|
|
154
|
+
result.text.includes("Fremtind Material Symbols"),
|
|
155
|
+
false,
|
|
175
156
|
);
|
|
157
|
+
assert.equal(result.text.includes("'Jokul Icons'"), true);
|
|
176
158
|
});
|
|
177
159
|
|
|
178
|
-
test("
|
|
179
|
-
const source =
|
|
160
|
+
test("renames CSS background-action token", () => {
|
|
161
|
+
const source = `.btn {
|
|
162
|
+
background: var(--jkl-color-background-action);
|
|
163
|
+
color: var(--jkl-color-text-on-action);
|
|
164
|
+
}
|
|
165
|
+
`;
|
|
166
|
+
|
|
167
|
+
const result = transformImportPaths(source, "/tmp/button.css");
|
|
168
|
+
|
|
169
|
+
assert.equal(result.text.includes("--jkl-color-background-action"), false);
|
|
170
|
+
assert.equal(result.text.includes("--jkl-color-text-on-action"), false);
|
|
171
|
+
assert.equal(result.text.includes("--jkl-color-background-contrast"), true);
|
|
172
|
+
assert.equal(result.text.includes("--jkl-color-text-on-contrast"), true);
|
|
173
|
+
assert.equal(result.changed, true);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
test("renames CSS text-inverted token to text-on-contrast", () => {
|
|
177
|
+
const source = `.inverted {
|
|
178
|
+
color: var(--jkl-color-text-inverted);
|
|
179
|
+
}
|
|
180
|
+
`;
|
|
181
|
+
|
|
182
|
+
const result = transformImportPaths(source, "/tmp/theme.css");
|
|
183
|
+
|
|
184
|
+
assert.equal(result.text.includes("--jkl-color-text-inverted"), false);
|
|
185
|
+
assert.equal(result.text.includes("--jkl-color-text-on-contrast"), true);
|
|
186
|
+
});
|
|
180
187
|
|
|
181
|
-
|
|
182
|
-
|
|
188
|
+
test("renames CSS container-high and container-low tokens", () => {
|
|
189
|
+
const source = `.card-high {
|
|
190
|
+
background: var(--jkl-color-background-container-high);
|
|
183
191
|
}
|
|
184
|
-
|
|
185
|
-
|
|
192
|
+
.card-low {
|
|
193
|
+
background: var(--jkl-color-background-container-low);
|
|
186
194
|
}
|
|
187
195
|
`;
|
|
188
196
|
|
|
189
|
-
const result = transformImportPaths(source, "/tmp/
|
|
197
|
+
const result = transformImportPaths(source, "/tmp/card.css");
|
|
190
198
|
|
|
199
|
+
assert.equal(result.text.includes("--jkl-color-background-container-high"), false);
|
|
200
|
+
assert.equal(result.text.includes("--jkl-color-background-container-low"), false);
|
|
191
201
|
assert.equal(
|
|
192
|
-
result.
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
true,
|
|
202
|
+
result.text.split("--jkl-color-background-container").length - 1,
|
|
203
|
+
2,
|
|
204
|
+
"should have two occurrences of the new token",
|
|
196
205
|
);
|
|
197
206
|
});
|
|
198
207
|
|
|
199
|
-
test("
|
|
200
|
-
const source =
|
|
208
|
+
test("renames CSS alert tokens to feedback tokens", () => {
|
|
209
|
+
const source = `.info { background: var(--jkl-color-background-alert-info); }
|
|
210
|
+
.warning { background: var(--jkl-color-background-alert-warning); }
|
|
211
|
+
.error { background: var(--jkl-color-background-alert-error); }
|
|
212
|
+
.success { background: var(--jkl-color-background-alert-success); }
|
|
213
|
+
`;
|
|
201
214
|
|
|
202
|
-
.
|
|
203
|
-
|
|
204
|
-
|
|
215
|
+
const result = transformImportPaths(source, "/tmp/alerts.css");
|
|
216
|
+
|
|
217
|
+
assert.equal(result.text.includes("--jkl-color-background-alert-"), false);
|
|
218
|
+
assert.equal(result.text.includes("--jkl-color-info-background-container"), true);
|
|
219
|
+
assert.equal(result.text.includes("--jkl-color-warning-background-container"), true);
|
|
220
|
+
assert.equal(result.text.includes("--jkl-color-error-background-container"), true);
|
|
221
|
+
assert.equal(result.text.includes("--jkl-color-success-background-container"), true);
|
|
222
|
+
});
|
|
205
223
|
|
|
206
|
-
|
|
207
|
-
|
|
224
|
+
test("warns about removed interactive tokens", () => {
|
|
225
|
+
const source = `.item {
|
|
226
|
+
background: var(--jkl-color-background-interactive);
|
|
227
|
+
color: var(--jkl-color-text-interactive);
|
|
208
228
|
}
|
|
209
229
|
`;
|
|
210
230
|
|
|
211
|
-
const result = transformImportPaths(source, "/tmp/
|
|
231
|
+
const result = transformImportPaths(source, "/tmp/interactive.css");
|
|
212
232
|
|
|
213
233
|
assert.equal(
|
|
214
|
-
result.warnings.some((
|
|
215
|
-
/paragraph-large\/medium\/small/.test(warning),
|
|
216
|
-
),
|
|
234
|
+
result.warnings.some((w) => /interactive/.test(w)),
|
|
217
235
|
true,
|
|
218
236
|
);
|
|
219
237
|
assert.equal(
|
|
220
|
-
result.warnings.
|
|
238
|
+
result.warnings.filter((w) => /interactive/.test(w)).length,
|
|
239
|
+
1,
|
|
240
|
+
"should produce one warning for both interactive tokens",
|
|
241
|
+
);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
test("warns about removed text-on-alert tokens", () => {
|
|
245
|
+
const source = `.info { color: var(--jkl-color-text-on-alert-info); }
|
|
246
|
+
`;
|
|
247
|
+
|
|
248
|
+
const result = transformImportPaths(source, "/tmp/alerts.css");
|
|
249
|
+
|
|
250
|
+
assert.equal(
|
|
251
|
+
result.warnings.some((w) => /text-on-alert/.test(w)),
|
|
221
252
|
true,
|
|
222
253
|
);
|
|
223
254
|
});
|
|
224
255
|
|
|
225
|
-
test("
|
|
226
|
-
const source =
|
|
227
|
-
|
|
228
|
-
|
|
256
|
+
test("warns about Card variant prop", () => {
|
|
257
|
+
const source = `<Card variant="outlined">
|
|
258
|
+
<p>Innhold</p>
|
|
259
|
+
</Card>
|
|
229
260
|
`;
|
|
230
261
|
|
|
231
|
-
const result = transformImportPaths(source, "/tmp/
|
|
262
|
+
const result = transformImportPaths(source, "/tmp/MyCard.tsx");
|
|
232
263
|
|
|
233
264
|
assert.equal(
|
|
234
|
-
result.
|
|
235
|
-
|
|
265
|
+
result.warnings.some((w) => /variant/.test(w) && /Card/.test(w)),
|
|
266
|
+
true,
|
|
267
|
+
);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
test("warns about Card variant high and low", () => {
|
|
271
|
+
const source = `function Page() {
|
|
272
|
+
return (
|
|
273
|
+
<>
|
|
274
|
+
<Card variant="high">Høy</Card>
|
|
275
|
+
<Card variant="low">Lav</Card>
|
|
276
|
+
</>
|
|
236
277
|
);
|
|
278
|
+
}
|
|
279
|
+
`;
|
|
280
|
+
|
|
281
|
+
const result = transformImportPaths(source, "/tmp/Page.tsx");
|
|
282
|
+
|
|
237
283
|
assert.equal(
|
|
238
|
-
result.
|
|
239
|
-
'"Jokul Icons", "Jokul Icons Fallback", sans-serif',
|
|
240
|
-
),
|
|
284
|
+
result.warnings.some((w) => /variant/.test(w)),
|
|
241
285
|
true,
|
|
242
286
|
);
|
|
287
|
+
assert.equal(
|
|
288
|
+
result.warnings.filter((w) => /variant/.test(w)).length,
|
|
289
|
+
1,
|
|
290
|
+
"should produce one warning even with multiple variant usages",
|
|
291
|
+
);
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
test("renames container-inverted to background-contrast", () => {
|
|
295
|
+
const source = `.inverted { background: var(--jkl-color-background-container-inverted); }
|
|
296
|
+
`;
|
|
297
|
+
|
|
298
|
+
const result = transformImportPaths(source, "/tmp/inverted.css");
|
|
299
|
+
|
|
300
|
+
assert.equal(result.text.includes("--jkl-color-background-container-inverted"), false);
|
|
301
|
+
assert.equal(result.text.includes("--jkl-color-background-contrast"), true);
|
|
302
|
+
assert.deepEqual(result.warnings, []);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// --- idempotency ---
|
|
306
|
+
|
|
307
|
+
test("is idempotent — running twice gives same result", () => {
|
|
308
|
+
const source = `import "@fremtind/jokul/styles/core/core.scss";
|
|
309
|
+
|
|
310
|
+
.btn { background: var(--jkl-color-background-action); }
|
|
311
|
+
`;
|
|
312
|
+
|
|
313
|
+
const first = transformImportPaths(source, "/tmp/page.scss");
|
|
314
|
+
const second = transformImportPaths(first.text, "/tmp/page.scss");
|
|
315
|
+
|
|
316
|
+
assert.equal(second.changed, false);
|
|
317
|
+
assert.equal(second.replacements, 0);
|
|
318
|
+
assert.equal(second.text, first.text);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// --- no-op ---
|
|
322
|
+
|
|
323
|
+
test("returns changed: false for an already-migrated file", () => {
|
|
324
|
+
const source = `import "@fremtind/jokul/styles/base.scss";
|
|
325
|
+
|
|
326
|
+
.btn { background: var(--jkl-color-background-contrast); }
|
|
327
|
+
`;
|
|
328
|
+
|
|
329
|
+
const result = transformImportPaths(source, "/tmp/page.ts");
|
|
330
|
+
|
|
331
|
+
assert.equal(result.changed, false);
|
|
332
|
+
assert.equal(result.replacements, 0);
|
|
333
|
+
assert.deepEqual(result.warnings, []);
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
// --- token boundary safety ---
|
|
337
|
+
|
|
338
|
+
test("does not rename token that is a prefix of a longer token", () => {
|
|
339
|
+
// --jkl-color-text-inverted should not match inside --jkl-color-text-inverted-extra
|
|
340
|
+
const source = `.x { color: var(--jkl-color-text-inverted-extra); }`;
|
|
341
|
+
|
|
342
|
+
const result = transformImportPaths(source, "/tmp/x.css");
|
|
343
|
+
|
|
344
|
+
assert.equal(result.text.includes("--jkl-color-text-inverted-extra"), true);
|
|
345
|
+
assert.equal(result.changed, false);
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
test("does not rename --jkl-color-background-container (base token, not a v4 token)", () => {
|
|
349
|
+
const source = `.x { background: var(--jkl-color-background-container); }`;
|
|
350
|
+
|
|
351
|
+
const result = transformImportPaths(source, "/tmp/x.css");
|
|
352
|
+
|
|
353
|
+
assert.equal(result.text, source);
|
|
354
|
+
assert.equal(result.changed, false);
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
test("renames container-high but leaves sibling container-low and base container intact in same rule", () => {
|
|
358
|
+
const source = `.x {
|
|
359
|
+
--high: var(--jkl-color-background-container-high);
|
|
360
|
+
--low: var(--jkl-color-background-container-low);
|
|
361
|
+
--base: var(--jkl-color-background-container);
|
|
362
|
+
}
|
|
363
|
+
`;
|
|
364
|
+
|
|
365
|
+
const result = transformImportPaths(source, "/tmp/x.css");
|
|
366
|
+
|
|
367
|
+
assert.equal(result.text.includes("--jkl-color-background-container-high"), false);
|
|
368
|
+
assert.equal(result.text.includes("--jkl-color-background-container-low"), false);
|
|
369
|
+
assert.equal(result.text.includes("var(--jkl-color-background-container)"), true,
|
|
370
|
+
"base container token must survive unchanged");
|
|
243
371
|
assert.equal(result.replacements, 2);
|
|
244
372
|
});
|
|
245
373
|
|
|
246
|
-
test("
|
|
374
|
+
test("does not rename alert-info token that has a longer suffix", () => {
|
|
375
|
+
const source = `.x { background: var(--jkl-color-background-alert-info-extra); }`;
|
|
376
|
+
|
|
377
|
+
const result = transformImportPaths(source, "/tmp/x.css");
|
|
378
|
+
|
|
379
|
+
assert.equal(result.changed, false);
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
// --- CSS token as custom property definition ---
|
|
383
|
+
|
|
384
|
+
test("renames token used as a custom property definition, not just inside var()", () => {
|
|
385
|
+
const source = `:root {
|
|
386
|
+
--jkl-color-background-action: #005aa4;
|
|
387
|
+
--jkl-color-text-inverted: #fff;
|
|
388
|
+
}
|
|
389
|
+
`;
|
|
390
|
+
|
|
391
|
+
const result = transformImportPaths(source, "/tmp/overrides.css");
|
|
392
|
+
|
|
393
|
+
assert.equal(result.text.includes("--jkl-color-background-action:"), false);
|
|
394
|
+
assert.equal(result.text.includes("--jkl-color-text-inverted:"), false);
|
|
395
|
+
assert.equal(result.text.includes("--jkl-color-background-contrast:"), true);
|
|
396
|
+
assert.equal(result.text.includes("--jkl-color-text-on-contrast:"), true);
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
// --- webfonts edge cases ---
|
|
400
|
+
|
|
401
|
+
test("removes webfonts.min.css import", () => {
|
|
402
|
+
const source = `import "@fremtind/jokul/styles/base.css";
|
|
403
|
+
import "@fremtind/jokul/styles/fonts/webfonts.min.css";
|
|
404
|
+
`;
|
|
405
|
+
|
|
406
|
+
const result = transformImportPaths(source, "/tmp/main.tsx");
|
|
407
|
+
|
|
408
|
+
assert.equal(result.text.includes("webfonts"), false);
|
|
409
|
+
assert.deepEqual(result.warnings, []);
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
test("removes webfonts.css when imported with require()", () => {
|
|
413
|
+
const source = `require("@fremtind/jokul/styles/base.css");
|
|
414
|
+
require("@fremtind/jokul/styles/fonts/webfonts.css");
|
|
415
|
+
`;
|
|
416
|
+
|
|
417
|
+
const result = transformImportPaths(source, "/tmp/main.cjs");
|
|
418
|
+
|
|
419
|
+
assert.equal(result.text.includes("webfonts"), false);
|
|
420
|
+
assert.deepEqual(result.warnings, []);
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
// --- font family edge cases ---
|
|
424
|
+
|
|
425
|
+
test("renames only the fallback font-family if primary is absent", () => {
|
|
247
426
|
const source = `.icon {
|
|
248
|
-
font-family:
|
|
427
|
+
font-family: "Fremtind Material Symbols Fallback";
|
|
249
428
|
}
|
|
250
429
|
`;
|
|
251
430
|
|
|
252
431
|
const result = transformImportPaths(source, "/tmp/icons.css");
|
|
253
432
|
|
|
254
|
-
assert.equal(
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
433
|
+
assert.equal(result.text.includes("Fremtind Material Symbols Fallback"), false);
|
|
434
|
+
assert.equal(result.text.includes("Jokul Icons Fallback"), true);
|
|
435
|
+
assert.equal(result.replacements, 1);
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
// --- combined transforms ---
|
|
439
|
+
|
|
440
|
+
test("applies import path and token rename in one pass", () => {
|
|
441
|
+
const source = `import "@fremtind/jokul/styles/core/core.scss";
|
|
442
|
+
|
|
443
|
+
.inverted {
|
|
444
|
+
background: var(--jkl-color-background-action);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
export default function Page() {
|
|
448
|
+
return <section />;
|
|
449
|
+
}
|
|
450
|
+
`;
|
|
451
|
+
|
|
452
|
+
const result = transformImportPaths(source, "/tmp/page.tsx");
|
|
453
|
+
|
|
454
|
+
assert.equal(result.text.includes("styles/core/core"), false);
|
|
455
|
+
assert.equal(result.text.includes("--jkl-color-background-action"), false);
|
|
456
|
+
assert.equal(result.text.includes("styles/base.scss"), true);
|
|
457
|
+
assert.equal(result.text.includes("--jkl-color-background-contrast"), true);
|
|
458
|
+
assert.equal(result.replacements, 2);
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
// --- SCSS-only transforms ---
|
|
462
|
+
|
|
463
|
+
test("does not reorder font import in a .css file", () => {
|
|
464
|
+
const source = `@import "@fremtind/jokul/styles/base.css";
|
|
465
|
+
@import "@fremtind/jokul/styles/theme/fonts";
|
|
466
|
+
`;
|
|
467
|
+
|
|
468
|
+
const result = transformImportPaths(source, "/tmp/global.css");
|
|
469
|
+
|
|
470
|
+
assert.equal(result.reordered, false);
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
// --- Tailwind color class renames ---
|
|
474
|
+
|
|
475
|
+
test("renames bg-background-action to bg-background-contrast", () => {
|
|
476
|
+
const source = `<div className="bg-background-action text-white">Innhold</div>`;
|
|
477
|
+
|
|
478
|
+
const result = transformImportPaths(source, "/tmp/component.tsx");
|
|
479
|
+
|
|
480
|
+
assert.equal(result.text.includes("bg-background-action"), false);
|
|
481
|
+
assert.equal(result.text.includes("bg-background-contrast"), true);
|
|
482
|
+
assert.equal(result.replacements, 1);
|
|
259
483
|
});
|
|
260
484
|
|
|
485
|
+
test("renames text-text-inverted to text-text-on-contrast", () => {
|
|
486
|
+
const source = `<p className="text-text-inverted">Tekst</p>`;
|
|
487
|
+
|
|
488
|
+
const result = transformImportPaths(source, "/tmp/page.tsx");
|
|
489
|
+
|
|
490
|
+
assert.equal(result.text.includes("text-text-inverted"), false);
|
|
491
|
+
assert.equal(result.text.includes("text-text-on-contrast"), true);
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
test("renames text-text-on-action to text-text-on-contrast", () => {
|
|
495
|
+
const source = `<button className="bg-background-contrast text-text-on-action">Knapp</button>`;
|
|
496
|
+
|
|
497
|
+
const result = transformImportPaths(source, "/tmp/button.tsx");
|
|
498
|
+
|
|
499
|
+
assert.equal(result.text.includes("text-text-on-action"), false);
|
|
500
|
+
assert.equal(result.text.includes("text-text-on-contrast"), true);
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
test("renames bg-background-container-high and -low", () => {
|
|
504
|
+
const source = `<div className="bg-background-container-high md:bg-background-container-low">
|
|
505
|
+
Innhold
|
|
506
|
+
</div>`;
|
|
507
|
+
|
|
508
|
+
const result = transformImportPaths(source, "/tmp/card.tsx");
|
|
509
|
+
|
|
510
|
+
assert.equal(result.text.includes("bg-background-container-high"), false);
|
|
511
|
+
assert.equal(result.text.includes("bg-background-container-low"), false);
|
|
512
|
+
assert.equal(result.text.includes("bg-background-container"), true);
|
|
513
|
+
assert.equal(result.replacements, 2);
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
test("does not rename bg-background-container (base Tailwind class)", () => {
|
|
517
|
+
const source = `<div className="bg-background-container">Innhold</div>`;
|
|
518
|
+
|
|
519
|
+
const result = transformImportPaths(source, "/tmp/card.tsx");
|
|
520
|
+
|
|
521
|
+
assert.equal(result.text, source);
|
|
522
|
+
assert.equal(result.changed, false);
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
test("renames bg-background-alert-info to bg-info-background-container", () => {
|
|
526
|
+
const source = `<div className="bg-background-alert-info border-border-subdued">
|
|
527
|
+
Info
|
|
528
|
+
</div>`;
|
|
529
|
+
|
|
530
|
+
const result = transformImportPaths(source, "/tmp/alert.tsx");
|
|
531
|
+
|
|
532
|
+
assert.equal(result.text.includes("bg-background-alert-info"), false);
|
|
533
|
+
assert.equal(result.text.includes("bg-info-background-container"), true);
|
|
534
|
+
assert.equal(result.replacements, 1);
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
test("renames all four alert color classes", () => {
|
|
538
|
+
const source = `className="bg-background-alert-info bg-background-alert-warning bg-background-alert-error bg-background-alert-success"`;
|
|
539
|
+
|
|
540
|
+
const result = transformImportPaths(source, "/tmp/alerts.tsx");
|
|
541
|
+
|
|
542
|
+
assert.equal(result.text.includes("bg-background-alert-"), false);
|
|
543
|
+
assert.equal(result.text.includes("bg-info-background-container"), true);
|
|
544
|
+
assert.equal(result.text.includes("bg-warning-background-container"), true);
|
|
545
|
+
assert.equal(result.text.includes("bg-error-background-container"), true);
|
|
546
|
+
assert.equal(result.text.includes("bg-success-background-container"), true);
|
|
547
|
+
assert.equal(result.replacements, 4);
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
test("renames Tailwind class with hover: modifier", () => {
|
|
551
|
+
const source = `<div className="hover:bg-background-action focus:bg-background-action">X</div>`;
|
|
552
|
+
|
|
553
|
+
const result = transformImportPaths(source, "/tmp/cmp.tsx");
|
|
554
|
+
|
|
555
|
+
assert.equal(result.text.includes("bg-background-action"), false);
|
|
556
|
+
assert.equal(result.text.includes("hover:bg-background-contrast"), true);
|
|
557
|
+
assert.equal(result.text.includes("focus:bg-background-contrast"), true);
|
|
558
|
+
assert.equal(result.replacements, 2);
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
test("renames Tailwind class with opacity modifier (/50)", () => {
|
|
562
|
+
const source = `<div className="bg-background-action/50">X</div>`;
|
|
563
|
+
|
|
564
|
+
const result = transformImportPaths(source, "/tmp/cmp.tsx");
|
|
565
|
+
|
|
566
|
+
assert.equal(result.text.includes("bg-background-action/50"), false);
|
|
567
|
+
assert.equal(result.text.includes("bg-background-contrast/50"), true);
|
|
568
|
+
assert.equal(result.replacements, 1);
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
test("renames Tailwind class in @apply rule", () => {
|
|
572
|
+
const source = `.btn {
|
|
573
|
+
@apply bg-background-action text-text-inverted;
|
|
574
|
+
}
|
|
575
|
+
`;
|
|
576
|
+
|
|
577
|
+
const result = transformImportPaths(source, "/tmp/styles.css");
|
|
578
|
+
|
|
579
|
+
assert.equal(result.text.includes("bg-background-action"), false);
|
|
580
|
+
assert.equal(result.text.includes("text-text-inverted"), false);
|
|
581
|
+
assert.equal(result.text.includes("bg-background-contrast"), true);
|
|
582
|
+
assert.equal(result.text.includes("text-text-on-contrast"), true);
|
|
583
|
+
assert.equal(result.replacements, 2);
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
test("renames non-bg prefix: border-background-action", () => {
|
|
587
|
+
const source = `<div className="border-background-action">X</div>`;
|
|
588
|
+
|
|
589
|
+
const result = transformImportPaths(source, "/tmp/cmp.tsx");
|
|
590
|
+
|
|
591
|
+
assert.equal(result.text.includes("border-background-action"), false);
|
|
592
|
+
assert.equal(result.text.includes("border-background-contrast"), true);
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
test("does not rename longer Tailwind class that shares a prefix", () => {
|
|
596
|
+
// bg-background-container-inverted-extra must not match bg-background-container-inverted
|
|
597
|
+
const source = `<div className="bg-background-container-inverted-extra">X</div>`;
|
|
598
|
+
|
|
599
|
+
const result = transformImportPaths(source, "/tmp/cmp.tsx");
|
|
600
|
+
|
|
601
|
+
assert.equal(result.text, source);
|
|
602
|
+
assert.equal(result.changed, false);
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
test("Tailwind renames are idempotent", () => {
|
|
606
|
+
const source = `<div className="bg-background-contrast text-text-on-contrast">X</div>`;
|
|
607
|
+
|
|
608
|
+
const result = transformImportPaths(source, "/tmp/cmp.tsx");
|
|
609
|
+
|
|
610
|
+
assert.equal(result.changed, false);
|
|
611
|
+
assert.equal(result.replacements, 0);
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
// --- Tailwind warnings ---
|
|
615
|
+
|
|
616
|
+
test("warns about bg-background-interactive Tailwind class", () => {
|
|
617
|
+
const source = `<div className="bg-background-interactive hover:bg-background-interactive-hover">X</div>`;
|
|
618
|
+
|
|
619
|
+
const result = transformImportPaths(source, "/tmp/cmp.tsx");
|
|
620
|
+
|
|
621
|
+
assert.equal(result.warnings.some((w) => /background-interactive/.test(w)), true);
|
|
622
|
+
assert.equal(result.warnings.filter((w) => /background-interactive/.test(w)).length, 1);
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
test("warns about border-border-separator Tailwind class", () => {
|
|
626
|
+
const source = `<div className="border border-border-separator">X</div>`;
|
|
627
|
+
|
|
628
|
+
const result = transformImportPaths(source, "/tmp/cmp.tsx");
|
|
629
|
+
|
|
630
|
+
assert.equal(result.warnings.some((w) => /border-border-separator/.test(w) || /kantklasser/.test(w)), true);
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
// --- does not warn about valid 5.0 patterns ---
|
|
634
|
+
|
|
261
635
|
test("does not warn about valid 5.0 patterns", () => {
|
|
262
636
|
const source = `@use "@fremtind/jokul/styles/jkl";
|
|
263
637
|
|
|
264
638
|
.title {
|
|
265
639
|
@include jkl.text-style("heading-1");
|
|
266
640
|
color: var(--jkl-color-text-default);
|
|
641
|
+
background: var(--jkl-color-background-contrast);
|
|
267
642
|
}
|
|
268
643
|
`;
|
|
269
644
|
|