@yak/react 0.0.0-stage → 10.0.0-rc.1
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/LICENSE +21 -0
- package/README.md +114 -2
- package/dist/context/baseContext.d.ts +5 -0
- package/dist/context/baseContext.js +8 -0
- package/dist/context/baseContext.js.map +1 -0
- package/dist/context/index.d.ts +20 -0
- package/dist/context/index.js +15 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/index.server.d.ts +9 -0
- package/dist/context/index.server.js +17 -0
- package/dist/context/index.server.js.map +1 -0
- package/dist/cross-file-resolver/index.d.ts +199 -0
- package/dist/cross-file-resolver/index.js +569 -0
- package/dist/cross-file-resolver/index.js.map +1 -0
- package/dist/index.d.ts +320 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +452 -0
- package/dist/internal.js +363 -0
- package/dist/internal.js.map +1 -0
- package/dist/isolated-source-eval/index.d.ts +30 -0
- package/dist/isolated-source-eval/index.js +317 -0
- package/dist/isolated-source-eval/index.js.map +1 -0
- package/dist/isolated-source-eval/worker.js +59 -0
- package/dist/isolated-source-eval/worker.js.map +1 -0
- package/dist/jsx-dev-runtime.d.ts +7 -0
- package/dist/jsx-dev-runtime.js +2 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime.d.ts +38 -0
- package/dist/jsx-runtime.js +2 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/loaders/turbo-loader.d.ts +15 -0
- package/dist/loaders/turbo-loader.js +816 -0
- package/dist/loaders/turbo-loader.js.map +1 -0
- package/dist/loaders/vite-plugin.d.ts +103 -0
- package/dist/loaders/vite-plugin.js +885 -0
- package/dist/loaders/vite-plugin.js.map +1 -0
- package/dist/loaders/webpack-loader.d.ts +12 -0
- package/dist/loaders/webpack-loader.js +710 -0
- package/dist/loaders/webpack-loader.js.map +1 -0
- package/dist/rsbuild/index.d.ts +29 -0
- package/dist/rsbuild/index.js +51 -0
- package/dist/rsbuild/index.js.map +1 -0
- package/dist/static/chunk-DK3Fl9T5.js +1 -0
- package/dist/static/index.d.ts +28 -0
- package/dist/static/index.js +2 -0
- package/dist/static/index.js.map +1 -0
- package/dist/withYak/index.d.ts +112 -0
- package/dist/withYak/index.js +171 -0
- package/dist/withYak/index.js.map +1 -0
- package/loaders/lib/resolveCrossFileSelectors.ts +161 -0
- package/loaders/turbo-evaluator.ts +134 -0
- package/loaders/turbo-loader.ts +184 -0
- package/loaders/vite-plugin.ts +28 -0
- package/loaders/webpack-loader.ts +41 -0
- package/package.json +155 -3
- package/rsbuild/index.ts +91 -0
- package/runtime/__tests__/atoms.test.tsx +48 -0
- package/runtime/__tests__/attrs.test.tsx +490 -0
- package/runtime/__tests__/cssLiteral.test.tsx +503 -0
- package/runtime/__tests__/cssProp.test.tsx +392 -0
- package/runtime/__tests__/cssPropTest.tsx +227 -0
- package/runtime/__tests__/foldedJsxParity.test.tsx +117 -0
- package/runtime/__tests__/styled.test.tsx +653 -0
- package/runtime/__tests__/tsconfig.json +18 -0
- package/runtime/__tests__/typeTest.tsx +374 -0
- package/runtime/atoms.tsx +36 -0
- package/runtime/context/README.md +84 -0
- package/runtime/context/baseContext.tsx +5 -0
- package/runtime/context/index.server.tsx +22 -0
- package/runtime/context/index.tsx +36 -0
- package/runtime/cssLiteral.tsx +214 -0
- package/runtime/globalStyle.tsx +54 -0
- package/runtime/index.ts +37 -0
- package/runtime/internal.ts +42 -0
- package/runtime/internals/mergeClassNames.ts +23 -0
- package/runtime/internals/mergeCssProp.ts +69 -0
- package/runtime/internals/propMarkers.ts +20 -0
- package/runtime/internals/unitPostFix.ts +34 -0
- package/runtime/jsx-dev-runtime.ts +6 -0
- package/runtime/jsx-runtime.ts +48 -0
- package/runtime/keyframes.tsx +30 -0
- package/runtime/mocks/cssLiteral.ts +74 -0
- package/runtime/mocks/globalStyle.ts +14 -0
- package/runtime/mocks/keyframes.ts +29 -0
- package/runtime/mocks/styled.ts +8 -0
- package/runtime/publicStyledApi.ts +159 -0
- package/runtime/styled.tsx +372 -0
- package/runtime/styledDom.tsx +139 -0
- package/withYak/allow-global-css.ts +94 -0
- package/withYak/index.ts +268 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { styled } from "./styled.js";
|
|
2
|
+
/// Internal API to create styled components
|
|
3
|
+
/// Optimization for faster rendering and smaller bundle size in production
|
|
4
|
+
/// thanks to better minification and dead code elimination
|
|
5
|
+
///
|
|
6
|
+
/// List taken from https://github.com/styled-components/styled-components/blob/e0019ba666fab4b5aaa2bff71ba6ad0005a299fd/packages/styled-components/src/utils/domElements.ts#L90
|
|
7
|
+
export const __yak_a = /*#__PURE__*/ styled("a");
|
|
8
|
+
export const __yak_abbr = /*#__PURE__*/ styled("abbr");
|
|
9
|
+
export const __yak_address = /*#__PURE__*/ styled("address");
|
|
10
|
+
export const __yak_area = /*#__PURE__*/ styled("area");
|
|
11
|
+
export const __yak_article = /*#__PURE__*/ styled("article");
|
|
12
|
+
export const __yak_aside = /*#__PURE__*/ styled("aside");
|
|
13
|
+
export const __yak_audio = /*#__PURE__*/ styled("audio");
|
|
14
|
+
export const __yak_b = /*#__PURE__*/ styled("b");
|
|
15
|
+
export const __yak_base = /*#__PURE__*/ styled("base");
|
|
16
|
+
export const __yak_bdi = /*#__PURE__*/ styled("bdi");
|
|
17
|
+
export const __yak_bdo = /*#__PURE__*/ styled("bdo");
|
|
18
|
+
export const __yak_big = /*#__PURE__*/ styled("big");
|
|
19
|
+
export const __yak_blockquote = /*#__PURE__*/ styled("blockquote");
|
|
20
|
+
export const __yak_body = /*#__PURE__*/ styled("body");
|
|
21
|
+
export const __yak_br = /*#__PURE__*/ styled("br");
|
|
22
|
+
export const __yak_button = /*#__PURE__*/ styled("button");
|
|
23
|
+
export const __yak_canvas = /*#__PURE__*/ styled("canvas");
|
|
24
|
+
export const __yak_caption = /*#__PURE__*/ styled("caption");
|
|
25
|
+
export const __yak_cite = /*#__PURE__*/ styled("cite");
|
|
26
|
+
export const __yak_code = /*#__PURE__*/ styled("code");
|
|
27
|
+
export const __yak_col = /*#__PURE__*/ styled("col");
|
|
28
|
+
export const __yak_colgroup = /*#__PURE__*/ styled("colgroup");
|
|
29
|
+
export const __yak_data = /*#__PURE__*/ styled("data");
|
|
30
|
+
export const __yak_datalist = /*#__PURE__*/ styled("datalist");
|
|
31
|
+
export const __yak_dd = /*#__PURE__*/ styled("dd");
|
|
32
|
+
export const __yak_del = /*#__PURE__*/ styled("del");
|
|
33
|
+
export const __yak_details = /*#__PURE__*/ styled("details");
|
|
34
|
+
export const __yak_dfn = /*#__PURE__*/ styled("dfn");
|
|
35
|
+
export const __yak_dialog = /*#__PURE__*/ styled("dialog");
|
|
36
|
+
export const __yak_div = /*#__PURE__*/ styled("div");
|
|
37
|
+
export const __yak_dl = /*#__PURE__*/ styled("dl");
|
|
38
|
+
export const __yak_dt = /*#__PURE__*/ styled("dt");
|
|
39
|
+
export const __yak_em = /*#__PURE__*/ styled("em");
|
|
40
|
+
export const __yak_embed = /*#__PURE__*/ styled("embed");
|
|
41
|
+
export const __yak_fieldset = /*#__PURE__*/ styled("fieldset");
|
|
42
|
+
export const __yak_figcaption = /*#__PURE__*/ styled("figcaption");
|
|
43
|
+
export const __yak_figure = /*#__PURE__*/ styled("figure");
|
|
44
|
+
export const __yak_footer = /*#__PURE__*/ styled("footer");
|
|
45
|
+
export const __yak_form = /*#__PURE__*/ styled("form");
|
|
46
|
+
export const __yak_h1 = /*#__PURE__*/ styled("h1");
|
|
47
|
+
export const __yak_h2 = /*#__PURE__*/ styled("h2");
|
|
48
|
+
export const __yak_h3 = /*#__PURE__*/ styled("h3");
|
|
49
|
+
export const __yak_h4 = /*#__PURE__*/ styled("h4");
|
|
50
|
+
export const __yak_h5 = /*#__PURE__*/ styled("h5");
|
|
51
|
+
export const __yak_h6 = /*#__PURE__*/ styled("h6");
|
|
52
|
+
export const __yak_header = /*#__PURE__*/ styled("header");
|
|
53
|
+
export const __yak_hgroup = /*#__PURE__*/ styled("hgroup");
|
|
54
|
+
export const __yak_hr = /*#__PURE__*/ styled("hr");
|
|
55
|
+
export const __yak_html = /*#__PURE__*/ styled("html");
|
|
56
|
+
export const __yak_i = /*#__PURE__*/ styled("i");
|
|
57
|
+
export const __yak_iframe = /*#__PURE__*/ styled("iframe");
|
|
58
|
+
export const __yak_img = /*#__PURE__*/ styled("img");
|
|
59
|
+
export const __yak_input = /*#__PURE__*/ styled("input");
|
|
60
|
+
export const __yak_ins = /*#__PURE__*/ styled("ins");
|
|
61
|
+
export const __yak_kbd = /*#__PURE__*/ styled("kbd");
|
|
62
|
+
export const __yak_keygen = /*#__PURE__*/ styled("keygen");
|
|
63
|
+
export const __yak_label = /*#__PURE__*/ styled("label");
|
|
64
|
+
export const __yak_legend = /*#__PURE__*/ styled("legend");
|
|
65
|
+
export const __yak_li = /*#__PURE__*/ styled("li");
|
|
66
|
+
export const __yak_link = /*#__PURE__*/ styled("link");
|
|
67
|
+
export const __yak_main = /*#__PURE__*/ styled("main");
|
|
68
|
+
export const __yak_map = /*#__PURE__*/ styled("map");
|
|
69
|
+
export const __yak_mark = /*#__PURE__*/ styled("mark");
|
|
70
|
+
export const __yak_menu = /*#__PURE__*/ styled("menu");
|
|
71
|
+
export const __yak_menuitem = /*#__PURE__*/ styled("menuitem");
|
|
72
|
+
export const __yak_meta = /*#__PURE__*/ styled("meta");
|
|
73
|
+
export const __yak_meter = /*#__PURE__*/ styled("meter");
|
|
74
|
+
export const __yak_nav = /*#__PURE__*/ styled("nav");
|
|
75
|
+
export const __yak_noscript = /*#__PURE__*/ styled("noscript");
|
|
76
|
+
export const __yak_object = /*#__PURE__*/ styled("object");
|
|
77
|
+
export const __yak_ol = /*#__PURE__*/ styled("ol");
|
|
78
|
+
export const __yak_optgroup = /*#__PURE__*/ styled("optgroup");
|
|
79
|
+
export const __yak_option = /*#__PURE__*/ styled("option");
|
|
80
|
+
export const __yak_output = /*#__PURE__*/ styled("output");
|
|
81
|
+
export const __yak_p = /*#__PURE__*/ styled("p");
|
|
82
|
+
export const __yak_param = /*#__PURE__*/ styled("param");
|
|
83
|
+
export const __yak_picture = /*#__PURE__*/ styled("picture");
|
|
84
|
+
export const __yak_pre = /*#__PURE__*/ styled("pre");
|
|
85
|
+
export const __yak_progress = /*#__PURE__*/ styled("progress");
|
|
86
|
+
export const __yak_q = /*#__PURE__*/ styled("q");
|
|
87
|
+
export const __yak_rp = /*#__PURE__*/ styled("rp");
|
|
88
|
+
export const __yak_rt = /*#__PURE__*/ styled("rt");
|
|
89
|
+
export const __yak_ruby = /*#__PURE__*/ styled("ruby");
|
|
90
|
+
export const __yak_s = /*#__PURE__*/ styled("s");
|
|
91
|
+
export const __yak_samp = /*#__PURE__*/ styled("samp");
|
|
92
|
+
export const __yak_script = /*#__PURE__*/ styled("script");
|
|
93
|
+
export const __yak_section = /*#__PURE__*/ styled("section");
|
|
94
|
+
export const __yak_select = /*#__PURE__*/ styled("select");
|
|
95
|
+
export const __yak_small = /*#__PURE__*/ styled("small");
|
|
96
|
+
export const __yak_source = /*#__PURE__*/ styled("source");
|
|
97
|
+
export const __yak_span = /*#__PURE__*/ styled("span");
|
|
98
|
+
export const __yak_strong = /*#__PURE__*/ styled("strong");
|
|
99
|
+
export const __yak_style = /*#__PURE__*/ styled("style");
|
|
100
|
+
export const __yak_sub = /*#__PURE__*/ styled("sub");
|
|
101
|
+
export const __yak_summary = /*#__PURE__*/ styled("summary");
|
|
102
|
+
export const __yak_sup = /*#__PURE__*/ styled("sup");
|
|
103
|
+
export const __yak_table = /*#__PURE__*/ styled("table");
|
|
104
|
+
export const __yak_tbody = /*#__PURE__*/ styled("tbody");
|
|
105
|
+
export const __yak_td = /*#__PURE__*/ styled("td");
|
|
106
|
+
export const __yak_textarea = /*#__PURE__*/ styled("textarea");
|
|
107
|
+
export const __yak_tfoot = /*#__PURE__*/ styled("tfoot");
|
|
108
|
+
export const __yak_th = /*#__PURE__*/ styled("th");
|
|
109
|
+
export const __yak_thead = /*#__PURE__*/ styled("thead");
|
|
110
|
+
export const __yak_time = /*#__PURE__*/ styled("time");
|
|
111
|
+
export const __yak_tr = /*#__PURE__*/ styled("tr");
|
|
112
|
+
export const __yak_track = /*#__PURE__*/ styled("track");
|
|
113
|
+
export const __yak_u = /*#__PURE__*/ styled("u");
|
|
114
|
+
export const __yak_ul = /*#__PURE__*/ styled("ul");
|
|
115
|
+
export const __yak_use = /*#__PURE__*/ styled("use");
|
|
116
|
+
export const __yak_var = /*#__PURE__*/ styled("var");
|
|
117
|
+
export const __yak_video = /*#__PURE__*/ styled("video");
|
|
118
|
+
export const __yak_wbr = /*#__PURE__*/ styled("wbr");
|
|
119
|
+
export const __yak_circle = /*#__PURE__*/ styled("circle");
|
|
120
|
+
export const __yak_clipPath = /*#__PURE__*/ styled("clipPath");
|
|
121
|
+
export const __yak_defs = /*#__PURE__*/ styled("defs");
|
|
122
|
+
export const __yak_ellipse = /*#__PURE__*/ styled("ellipse");
|
|
123
|
+
export const __yak_foreignObject = /*#__PURE__*/ styled("foreignObject");
|
|
124
|
+
export const __yak_g = /*#__PURE__*/ styled("g");
|
|
125
|
+
export const __yak_image = /*#__PURE__*/ styled("image");
|
|
126
|
+
export const __yak_line = /*#__PURE__*/ styled("line");
|
|
127
|
+
export const __yak_linearGradient = /*#__PURE__*/ styled("linearGradient");
|
|
128
|
+
export const __yak_marker = /*#__PURE__*/ styled("marker");
|
|
129
|
+
export const __yak_mask = /*#__PURE__*/ styled("mask");
|
|
130
|
+
export const __yak_path = /*#__PURE__*/ styled("path");
|
|
131
|
+
export const __yak_pattern = /*#__PURE__*/ styled("pattern");
|
|
132
|
+
export const __yak_polygon = /*#__PURE__*/ styled("polygon");
|
|
133
|
+
export const __yak_polyline = /*#__PURE__*/ styled("polyline");
|
|
134
|
+
export const __yak_radialGradient = /*#__PURE__*/ styled("radialGradient");
|
|
135
|
+
export const __yak_rect = /*#__PURE__*/ styled("rect");
|
|
136
|
+
export const __yak_stop = /*#__PURE__*/ styled("stop");
|
|
137
|
+
export const __yak_svg = /*#__PURE__*/ styled("svg");
|
|
138
|
+
export const __yak_text = /*#__PURE__*/ styled("text");
|
|
139
|
+
export const __yak_tspan = /*#__PURE__*/ styled("tspan");
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
interface WebpackConfig {
|
|
5
|
+
module?: { rules?: unknown[] };
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface Rule {
|
|
9
|
+
test?: unknown;
|
|
10
|
+
issuer?: unknown;
|
|
11
|
+
use?: unknown;
|
|
12
|
+
oneOf?: unknown;
|
|
13
|
+
rules?: unknown;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function hasAppDir(projectDir: string): boolean {
|
|
17
|
+
return (
|
|
18
|
+
// mirrors next.js's `findDir(dir, "app")`
|
|
19
|
+
// https://github.com/vercel/next.js/blob/v16.3.4/packages/next/src/lib/find-pages-dir.ts#L4-L13
|
|
20
|
+
existsSync(path.join(projectDir, "app")) || existsSync(path.join(projectDir, "src", "app"))
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Next.js (pages router) only allows global CSS imports from `_app`.
|
|
26
|
+
* Everywhere else it expects CSS Modules. Yak's co-located `*.yak.css`
|
|
27
|
+
* files are plain global CSS, because yak already hashes the class names
|
|
28
|
+
* itself, so there's no risk of leaking styles
|
|
29
|
+
*
|
|
30
|
+
* Next.js has no option to allow this, so we copy its `_app` global CSS
|
|
31
|
+
* rule without the `_app` issuer check and limit the copy to `.yak.css`.
|
|
32
|
+
* The copy goes to the start of the same `oneOf`, so it matches before
|
|
33
|
+
* Next's error rules.
|
|
34
|
+
*/
|
|
35
|
+
export function allowYakGlobalCss(webpackConfig: WebpackConfig) {
|
|
36
|
+
const rules = webpackConfig.module?.rules;
|
|
37
|
+
if (!Array.isArray(rules)) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Next.js's internal `regexCssGlobal` source
|
|
42
|
+
// https://github.com/vercel/next.js/blob/v16.3.4/packages/next/src/build/webpack/config/blocks/css/index.ts#L23
|
|
43
|
+
const nextGlobalCssRegExpSource = "(?<!\\.module)\\.css$";
|
|
44
|
+
|
|
45
|
+
const isRule = (value: unknown): value is Rule =>
|
|
46
|
+
typeof value === "object" && value !== null && !Array.isArray(value);
|
|
47
|
+
|
|
48
|
+
// Next.js sets `issuer: { and: [ctx.customAppFile] }`, where
|
|
49
|
+
// `customAppFile` is a RegExp for the path of `pages/_app`
|
|
50
|
+
// https://github.com/vercel/next.js/blob/v16.3.4/packages/next/src/build/webpack-config.ts#L2550-L2552
|
|
51
|
+
const hasAppIssuer = (rule: Rule): boolean => {
|
|
52
|
+
if (!isRule(rule.issuer)) return false;
|
|
53
|
+
const and = (rule.issuer as { and?: unknown }).and;
|
|
54
|
+
return Array.isArray(and) && and[0] instanceof RegExp && and[0].source.endsWith("_app");
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const isAppGlobalCssRule = (rule: Rule): boolean =>
|
|
58
|
+
rule.test instanceof RegExp &&
|
|
59
|
+
rule.test.source === nextGlobalCssRegExpSource &&
|
|
60
|
+
hasAppIssuer(rule) &&
|
|
61
|
+
Array.isArray(rule.use);
|
|
62
|
+
|
|
63
|
+
const findAppRule = (ruleList: unknown): { oneOf: unknown[]; appRule: Rule } | undefined => {
|
|
64
|
+
if (!Array.isArray(ruleList)) return undefined;
|
|
65
|
+
for (const rule of ruleList) {
|
|
66
|
+
if (!isRule(rule)) continue;
|
|
67
|
+
if (Array.isArray(rule.oneOf)) {
|
|
68
|
+
const appRule = rule.oneOf.find(
|
|
69
|
+
(item): item is Rule => isRule(item) && isAppGlobalCssRule(item),
|
|
70
|
+
);
|
|
71
|
+
if (appRule) return { oneOf: rule.oneOf, appRule };
|
|
72
|
+
}
|
|
73
|
+
const found = findAppRule(rule.oneOf) ?? findAppRule(rule.rules);
|
|
74
|
+
if (found) return found;
|
|
75
|
+
}
|
|
76
|
+
return undefined;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const found = findAppRule(rules);
|
|
80
|
+
if (!found) {
|
|
81
|
+
console.warn(
|
|
82
|
+
"@yak/react: could not find the next.js global-CSS rules. " +
|
|
83
|
+
"Please report this issue with your Next.js version at " +
|
|
84
|
+
"https://github.com/DigitecGalaxus/next-yak/issues/new",
|
|
85
|
+
);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
found.oneOf.unshift({
|
|
90
|
+
test: /\.yak\.css$/,
|
|
91
|
+
sideEffects: true,
|
|
92
|
+
use: [...(found.appRule.use as unknown[])],
|
|
93
|
+
});
|
|
94
|
+
}
|
package/withYak/index.ts
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { NextConfig } from "next";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { allowYakGlobalCss, hasAppDir } from "./allow-global-css.ts";
|
|
5
|
+
import {
|
|
6
|
+
buildYakPluginOptions,
|
|
7
|
+
resolveYakContext,
|
|
8
|
+
type YakConfigOptions,
|
|
9
|
+
} from "yak-internals/config";
|
|
10
|
+
|
|
11
|
+
export { buildYakPluginOptions, resolveYakContext } from "yak-internals/config";
|
|
12
|
+
export type { YakConfigOptions } from "yak-internals/config";
|
|
13
|
+
|
|
14
|
+
const currentDir = import.meta.dirname;
|
|
15
|
+
|
|
16
|
+
const addYak = (yakOptions: YakConfigOptions, nextConfig: NextConfig) => {
|
|
17
|
+
const yakPluginOptions = buildYakPluginOptions(yakOptions, currentDir);
|
|
18
|
+
|
|
19
|
+
if (process.env.TURBOPACK === "1" || process.env.TURBOPACK === "auto") {
|
|
20
|
+
addYakTurbopack(nextConfig, yakOptions, {
|
|
21
|
+
...yakPluginOptions,
|
|
22
|
+
importMode: {
|
|
23
|
+
value: "data:text/css;base64,",
|
|
24
|
+
encoding: "Base64",
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
} else {
|
|
28
|
+
addYakWebpack(nextConfig, yakOptions, {
|
|
29
|
+
...yakPluginOptions,
|
|
30
|
+
importMode: {
|
|
31
|
+
value: "./{{__BASE_NAME__}}.yak.css!=!./{{__BASE_NAME__}}?./{{__BASE_NAME__}}.yak.css",
|
|
32
|
+
encoding: "None",
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return nextConfig;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Configure Turbopack with yak loader for CSS-in-JS transformation
|
|
41
|
+
* @param nextConfig - Next.js configuration object
|
|
42
|
+
* @param yakOptions - Yak configuration options
|
|
43
|
+
* @param yakPluginOptions - Processed plugin options for yak-swc
|
|
44
|
+
*/
|
|
45
|
+
function addYakTurbopack(
|
|
46
|
+
nextConfig: NextConfig,
|
|
47
|
+
yakOptions: YakConfigOptions,
|
|
48
|
+
yakPluginOptions: {
|
|
49
|
+
minify: boolean;
|
|
50
|
+
basePath: string;
|
|
51
|
+
prefix?: string;
|
|
52
|
+
displayNames: boolean;
|
|
53
|
+
foldStatic: boolean;
|
|
54
|
+
strictCssProp: boolean;
|
|
55
|
+
importMode: {
|
|
56
|
+
value: string;
|
|
57
|
+
encoding: string;
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
) {
|
|
61
|
+
// turbopack can't handle options with undefined values, so we remove them
|
|
62
|
+
const yakLoader = removeUndefinedRecursive({
|
|
63
|
+
loader: path.join(currentDir, "../loaders/turbo-loader.js"),
|
|
64
|
+
options: {
|
|
65
|
+
yakOptions: yakOptions,
|
|
66
|
+
yakPluginOptions: yakPluginOptions,
|
|
67
|
+
},
|
|
68
|
+
}) as { loader: string; options: {} };
|
|
69
|
+
|
|
70
|
+
nextConfig.turbopack ||= {};
|
|
71
|
+
nextConfig.turbopack.rules ||= {};
|
|
72
|
+
|
|
73
|
+
const ruleKey = "*.{js,jsx,cjs,mjs,ts,tsx,cts,mts}";
|
|
74
|
+
const rule = {
|
|
75
|
+
loaders: [] as { loader: string; options: {} }[],
|
|
76
|
+
...nextConfig.turbopack.rules[ruleKey],
|
|
77
|
+
};
|
|
78
|
+
rule.loaders.push(yakLoader);
|
|
79
|
+
nextConfig.turbopack.rules[ruleKey] = rule;
|
|
80
|
+
|
|
81
|
+
// Configure resolveAlias for custom yak context (similar to webpack)
|
|
82
|
+
// This allows users to provide a custom context file that will be used
|
|
83
|
+
// instead of the default baseContext
|
|
84
|
+
const yakContext = resolveYakContext(yakOptions.contextPath, process.cwd());
|
|
85
|
+
if (yakContext) {
|
|
86
|
+
nextConfig.turbopack.resolveAlias ||= {};
|
|
87
|
+
nextConfig.turbopack.resolveAlias["@yak/react/context/baseContext"] =
|
|
88
|
+
// This is a hack around the fact that turbopack currently only supports relative paths
|
|
89
|
+
// turbopack: "server relative imports are not implemented yet"
|
|
90
|
+
// Relative is quite dangerous here as it relies on the cwd being the starting point
|
|
91
|
+
`./${path.relative(process.cwd(), yakContext)}`;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Configure Webpack with yak SWC plugin and webpack loader for CSS-in-JS transformation
|
|
97
|
+
* @param nextConfig - Next.js configuration object
|
|
98
|
+
* @param yakOptions - Yak configuration options
|
|
99
|
+
* @param yakPluginOptions - Processed plugin options for yak-swc
|
|
100
|
+
*/
|
|
101
|
+
function addYakWebpack(
|
|
102
|
+
nextConfig: NextConfig,
|
|
103
|
+
yakOptions: YakConfigOptions,
|
|
104
|
+
yakPluginOptions: {
|
|
105
|
+
minify: boolean;
|
|
106
|
+
basePath: string;
|
|
107
|
+
prefix?: string;
|
|
108
|
+
displayNames: boolean;
|
|
109
|
+
foldStatic: boolean;
|
|
110
|
+
strictCssProp: boolean;
|
|
111
|
+
importMode: {
|
|
112
|
+
value: string;
|
|
113
|
+
encoding: string;
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
) {
|
|
117
|
+
// Add SWC plugin for Webpack
|
|
118
|
+
nextConfig.experimental ||= {};
|
|
119
|
+
nextConfig.experimental.swcPlugins ||= [];
|
|
120
|
+
nextConfig.experimental.swcPlugins.push(["@yak/swc", yakPluginOptions]);
|
|
121
|
+
|
|
122
|
+
// Configure webpack loader
|
|
123
|
+
const previousConfig = nextConfig.webpack;
|
|
124
|
+
nextConfig.webpack = (webpackConfig, options) => {
|
|
125
|
+
if (previousConfig) {
|
|
126
|
+
webpackConfig = previousConfig(webpackConfig, options);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (!options.isServer && !hasAppDir(options.dir)) {
|
|
130
|
+
// Next.js restricts global CSS imports only in the client build of a pages-only project, so only patch its rules there
|
|
131
|
+
allowYakGlobalCss(webpackConfig);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
webpackConfig.module.rules.push({
|
|
135
|
+
test: /\.yak\.css$/,
|
|
136
|
+
loader: path.join(currentDir, "../loaders/webpack-loader.js"),
|
|
137
|
+
options: yakOptions,
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// With the following alias the internal @yak/react code
|
|
141
|
+
// is able to import a context which works for server components
|
|
142
|
+
const yakContext = resolveYakContext(
|
|
143
|
+
yakOptions.contextPath,
|
|
144
|
+
webpackConfig.context || process.cwd(),
|
|
145
|
+
);
|
|
146
|
+
if (yakContext) {
|
|
147
|
+
webpackConfig.resolve.alias["@yak/react/context/baseContext"] = yakContext;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return webpackConfig;
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Recursively removes undefined values from an object or array.
|
|
156
|
+
*
|
|
157
|
+
* This function deeply traverses the input object/array and creates a new structure
|
|
158
|
+
* with all undefined values filtered out. For objects, properties with undefined values
|
|
159
|
+
* are omitted. For arrays, undefined elements are removed from the result.
|
|
160
|
+
*
|
|
161
|
+
* @param obj - The object or array to process
|
|
162
|
+
* @returns A new object/array with undefined values removed, or the original value if no changes were needed
|
|
163
|
+
*/
|
|
164
|
+
function removeUndefinedRecursive<T>(obj: T): {} {
|
|
165
|
+
if (typeof obj !== "object" || obj === null) {
|
|
166
|
+
return obj as {};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (Array.isArray(obj)) {
|
|
170
|
+
const filtered: unknown[] = [];
|
|
171
|
+
for (let i = 0; i < obj.length; i++) {
|
|
172
|
+
const processed = removeUndefinedRecursive(obj[i]);
|
|
173
|
+
if (processed !== undefined) {
|
|
174
|
+
filtered.push(processed);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return filtered as {};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const newObj: Record<string, unknown> = {};
|
|
181
|
+
let hasChanges = false;
|
|
182
|
+
|
|
183
|
+
for (const key in obj) {
|
|
184
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
185
|
+
const value = removeUndefinedRecursive((obj as any)[key]);
|
|
186
|
+
if (value !== undefined) {
|
|
187
|
+
newObj[key] = value;
|
|
188
|
+
hasChanges = true;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return hasChanges ? (newObj as {}) : obj;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Wrapper to allow sync, async, and function configuration of Next.js
|
|
197
|
+
/**
|
|
198
|
+
* Add Yak to your Next.js app
|
|
199
|
+
*
|
|
200
|
+
* @usage
|
|
201
|
+
*
|
|
202
|
+
* ```ts
|
|
203
|
+
* // next.config.js
|
|
204
|
+
* const { withYak } = require("@yak/react/withYak");
|
|
205
|
+
* const nextConfig = {
|
|
206
|
+
* // your next config here
|
|
207
|
+
* };
|
|
208
|
+
* module.exports = withYak(nextConfig);
|
|
209
|
+
* ```
|
|
210
|
+
*
|
|
211
|
+
* With a custom yakConfig
|
|
212
|
+
*
|
|
213
|
+
* ```ts
|
|
214
|
+
* // next.config.js
|
|
215
|
+
* const { withYak } = require("@yak/react/withYak");
|
|
216
|
+
* const nextConfig = {
|
|
217
|
+
* // your next config here
|
|
218
|
+
* };
|
|
219
|
+
* const yakConfig = {
|
|
220
|
+
* // Optional prefix for generated CSS identifiers
|
|
221
|
+
* prefix: "my-app",
|
|
222
|
+
* // Other yak config options...
|
|
223
|
+
* };
|
|
224
|
+
* module.exports = withYak(yakConfig, nextConfig);
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
227
|
+
export const withYak: {
|
|
228
|
+
<
|
|
229
|
+
T extends
|
|
230
|
+
| Record<string, any>
|
|
231
|
+
| ((...args: any[]) => Record<string, any>)
|
|
232
|
+
| ((...args: any[]) => Promise<Record<string, any>>),
|
|
233
|
+
>(
|
|
234
|
+
yakOptions: YakConfigOptions,
|
|
235
|
+
nextConfig: T,
|
|
236
|
+
): T;
|
|
237
|
+
// no yakConfig
|
|
238
|
+
<
|
|
239
|
+
T extends
|
|
240
|
+
| Record<string, any>
|
|
241
|
+
| ((...args: any[]) => Record<string, any>)
|
|
242
|
+
| ((...args: any[]) => Promise<Record<string, any>>),
|
|
243
|
+
>(
|
|
244
|
+
nextConfig: T,
|
|
245
|
+
_?: undefined,
|
|
246
|
+
): T;
|
|
247
|
+
} = (maybeYakOptions, nextConfig) => {
|
|
248
|
+
if (nextConfig === undefined) {
|
|
249
|
+
return withYak({}, maybeYakOptions);
|
|
250
|
+
}
|
|
251
|
+
// If the second parameter is present the first parameter must be a YakConfigOptions
|
|
252
|
+
const yakOptions = maybeYakOptions as YakConfigOptions;
|
|
253
|
+
if (typeof nextConfig === "function") {
|
|
254
|
+
/**
|
|
255
|
+
* A NextConfig can be a sync or async function
|
|
256
|
+
* https://nextjs.org/docs/pages/api-reference/next-config-js
|
|
257
|
+
* @param {any[]} args
|
|
258
|
+
*/
|
|
259
|
+
return (...args) => {
|
|
260
|
+
/** Dynamic Next Configs can be async or sync */
|
|
261
|
+
const config = nextConfig(...args) as NextConfig | Promise<NextConfig>;
|
|
262
|
+
return config instanceof Promise
|
|
263
|
+
? config.then((config) => addYak(yakOptions, config))
|
|
264
|
+
: addYak(yakOptions, config);
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
return addYak(yakOptions, nextConfig);
|
|
268
|
+
};
|