@seyuna/postcss 1.0.0-canary.27 → 1.0.0-canary.29
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/CHANGELOG.md +14 -0
- package/README.md +171 -135
- package/dist/at-rules/config.d.ts +6 -0
- package/dist/at-rules/config.js +71 -0
- package/dist/at-rules/import.js +6 -11
- package/dist/at-rules/index.js +2 -0
- package/dist/config.d.ts +2 -2
- package/dist/config.js +29 -74
- package/dist/types.d.ts +0 -2
- package/package.json +1 -1
- package/src/at-rules/config.ts +78 -0
- package/src/at-rules/import.ts +6 -12
- package/src/at-rules/index.ts +2 -0
- package/src/config.ts +45 -86
- package/src/types.ts +0 -2
- package/tests/plugin.test.ts +138 -76
package/tests/plugin.test.ts
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
import { describe, it, expect } from
|
|
2
|
-
import postcss from
|
|
3
|
-
import plugin from
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import postcss from "postcss";
|
|
3
|
+
import plugin from "../src/index";
|
|
4
4
|
|
|
5
5
|
const mockConfig = {
|
|
6
6
|
ui: {
|
|
7
7
|
theme: {
|
|
8
8
|
hues: {
|
|
9
9
|
primary: "200",
|
|
10
|
-
secondary: "100"
|
|
10
|
+
secondary: "100",
|
|
11
11
|
},
|
|
12
12
|
colors: {
|
|
13
13
|
white: { lightness: 1, chroma: 0, hue: 0 },
|
|
14
|
-
black: { lightness: 0, chroma: 0, hue: 0 }
|
|
14
|
+
black: { lightness: 0, chroma: 0, hue: 0 },
|
|
15
15
|
},
|
|
16
16
|
light: {
|
|
17
17
|
lightness: 0.66,
|
|
18
18
|
colors: {
|
|
19
|
-
surface: { lightness: 1, chroma: 0, hue: 0 }
|
|
20
|
-
}
|
|
19
|
+
surface: { lightness: 1, chroma: 0, hue: 0 },
|
|
20
|
+
},
|
|
21
21
|
},
|
|
22
22
|
dark: {
|
|
23
23
|
lightness: 0.66,
|
|
24
24
|
colors: {
|
|
25
|
-
surface: { lightness: 0, chroma: 0, hue: 0 }
|
|
26
|
-
}
|
|
25
|
+
surface: { lightness: 0, chroma: 0, hue: 0 },
|
|
26
|
+
},
|
|
27
27
|
},
|
|
28
28
|
breakpoints: {
|
|
29
|
-
tablet: "48rem"
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
29
|
+
tablet: "48rem",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
33
|
};
|
|
34
34
|
|
|
35
35
|
async function run(input: string, opts: any = {}) {
|
|
@@ -37,134 +37,196 @@ async function run(input: string, opts: any = {}) {
|
|
|
37
37
|
return postcss([plugin(mergedOpts)]).process(input, { from: undefined });
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
describe(
|
|
41
|
-
it(
|
|
42
|
-
const input =
|
|
43
|
-
const output =
|
|
40
|
+
describe("Seyuna PostCSS Plugin", () => {
|
|
41
|
+
it("processes SeyunaStandardColor() function", async () => {
|
|
42
|
+
const input = ".test { color: SeyunaStandardColor(primary); }";
|
|
43
|
+
const output =
|
|
44
|
+
".test { color: oklch(var(--lightness) var(--chroma) var(--primary-hue) / 1)";
|
|
44
45
|
const result = await run(input);
|
|
45
46
|
expect(result.css).toContain(output);
|
|
46
47
|
});
|
|
47
48
|
|
|
48
|
-
it(
|
|
49
|
-
const input =
|
|
50
|
-
const output =
|
|
49
|
+
it("processes SeyunaStandardColor() with alpha", async () => {
|
|
50
|
+
const input = ".test { color: SeyunaStandardColor(primary, 0.5); }";
|
|
51
|
+
const output =
|
|
52
|
+
".test { color: oklch(var(--lightness) var(--chroma) var(--primary-hue) / 0.5)";
|
|
51
53
|
const result = await run(input);
|
|
52
54
|
expect(result.css).toContain(output);
|
|
53
55
|
});
|
|
54
56
|
|
|
55
|
-
it(
|
|
56
|
-
const input =
|
|
57
|
-
const output =
|
|
57
|
+
it("processes SeyunaAlpha() function with color name", async () => {
|
|
58
|
+
const input = ".test { color: SeyunaAlpha(primary, 0.5); }";
|
|
59
|
+
const output =
|
|
60
|
+
"color: oklch(var(--lightness) var(--chroma) var(--primary-hue) / 0.5)";
|
|
58
61
|
const result = await run(input);
|
|
59
62
|
expect(result.css).toContain(output);
|
|
60
63
|
});
|
|
61
64
|
|
|
62
|
-
it(
|
|
63
|
-
const input =
|
|
64
|
-
const output =
|
|
65
|
+
it("processes SeyunaLighten() function with color name", async () => {
|
|
66
|
+
const input = ".test { color: SeyunaLighten(primary, 0.1); }";
|
|
67
|
+
const output =
|
|
68
|
+
"color: oklch(calc(var(--lightness) + 0.1) var(--chroma) var(--primary-hue) / 1)";
|
|
65
69
|
const result = await run(input);
|
|
66
70
|
expect(result.css).toContain(output);
|
|
67
71
|
});
|
|
68
72
|
|
|
69
|
-
it(
|
|
70
|
-
const input =
|
|
71
|
-
const output =
|
|
73
|
+
it("processes SeyunaDarken() function with color name", async () => {
|
|
74
|
+
const input = ".test { color: SeyunaDarken(primary, 0.1); }";
|
|
75
|
+
const output =
|
|
76
|
+
"color: oklch(calc(var(--lightness) - 0.1) var(--chroma) var(--primary-hue) / 1)";
|
|
72
77
|
const result = await run(input);
|
|
73
78
|
expect(result.css).toContain(output);
|
|
74
79
|
});
|
|
75
80
|
|
|
76
|
-
it(
|
|
81
|
+
it("processes SeyunaTheme() function", async () => {
|
|
77
82
|
// We pass the config via opts for testing
|
|
78
|
-
const input =
|
|
83
|
+
const input =
|
|
84
|
+
".test { border-radius: SeyunaTheme(ui.theme.breakpoints.tablet); }";
|
|
79
85
|
const result = await run(input, { config: mockConfig });
|
|
80
|
-
expect(result.css).toContain(
|
|
86
|
+
expect(result.css).toContain(".test { border-radius: 48rem");
|
|
81
87
|
});
|
|
82
88
|
|
|
83
|
-
it(
|
|
84
|
-
const input =
|
|
89
|
+
it("processes @xs container at-rule", async () => {
|
|
90
|
+
const input = "@xs { .box { color: red; } }";
|
|
85
91
|
const result = await run(input);
|
|
86
|
-
expect(result.css).toContain(
|
|
87
|
-
expect(result.css).toContain(
|
|
92
|
+
expect(result.css).toContain("@container (min-width: 20rem)");
|
|
93
|
+
expect(result.css).toContain(".box { color: red");
|
|
88
94
|
});
|
|
89
95
|
|
|
90
|
-
it(
|
|
91
|
-
const input =
|
|
96
|
+
it("processes @light at-rule", async () => {
|
|
97
|
+
const input = "@light { .test { color: black; } }";
|
|
92
98
|
const result = await run(input);
|
|
93
|
-
expect(result.css).toContain(
|
|
99
|
+
expect(result.css).toContain("@media (prefers-color-scheme: light)");
|
|
94
100
|
expect(result.css).toContain('[data-mode="system"] &');
|
|
95
101
|
expect(result.css).toContain('[data-mode="light"] &');
|
|
96
102
|
});
|
|
97
103
|
|
|
98
|
-
it(
|
|
99
|
-
const input =
|
|
100
|
-
const output =
|
|
104
|
+
it("processes SeyunaAlpha() with standard color", async () => {
|
|
105
|
+
const input = ".test { color: SeyunaAlpha(primary, 0.5); }";
|
|
106
|
+
const output =
|
|
107
|
+
"color: oklch(var(--lightness) var(--chroma) var(--primary-hue) / 0.5)";
|
|
101
108
|
const result = await run(input, { config: mockConfig });
|
|
102
109
|
expect(result.css).toContain(output);
|
|
103
110
|
});
|
|
104
111
|
|
|
105
|
-
it(
|
|
106
|
-
const input =
|
|
107
|
-
const output =
|
|
112
|
+
it("processes SeyunaAlpha() with fixed color", async () => {
|
|
113
|
+
const input = ".test { color: SeyunaAlpha(surface, 0.5); }";
|
|
114
|
+
const output =
|
|
115
|
+
"color: oklch(var(--surface-lightness) var(--surface-chroma) var(--surface-hue) / 0.5)";
|
|
108
116
|
const result = await run(input, { config: mockConfig });
|
|
109
117
|
expect(result.css).toContain(output);
|
|
110
118
|
});
|
|
111
119
|
|
|
112
|
-
it(
|
|
113
|
-
const input =
|
|
114
|
-
const output =
|
|
120
|
+
it("processes SeyunaContrast() with fixed color", async () => {
|
|
121
|
+
const input = ".test { color: SeyunaContrast(surface); }";
|
|
122
|
+
const output =
|
|
123
|
+
"color: oklch(calc((var(--surface-lightness) - 0.6) * -1000) 0 0)";
|
|
115
124
|
const result = await run(input, { config: mockConfig });
|
|
116
125
|
expect(result.css).toContain(output);
|
|
117
126
|
});
|
|
118
127
|
|
|
119
|
-
it(
|
|
120
|
-
const input =
|
|
121
|
-
const output =
|
|
128
|
+
it("processes SeyunaContrast() with standard color", async () => {
|
|
129
|
+
const input = ".test { color: SeyunaContrast(primary); }";
|
|
130
|
+
const output = "color: oklch(calc((var(--lightness) - 0.6) * -1000) 0 0)";
|
|
122
131
|
const result = await run(input, { config: mockConfig });
|
|
123
132
|
expect(result.css).toContain(output);
|
|
124
133
|
});
|
|
125
134
|
|
|
126
|
-
it(
|
|
127
|
-
const input =
|
|
128
|
-
await expect(
|
|
129
|
-
|
|
135
|
+
it("throws error for unknown standard color in strict mode", async () => {
|
|
136
|
+
const input = ".test { color: SeyunaStandardColor(unknown); }";
|
|
137
|
+
await expect(
|
|
138
|
+
run(input, { config: mockConfig, strict: true }),
|
|
139
|
+
).rejects.toThrow(/Standard color 'unknown' not found/);
|
|
130
140
|
});
|
|
131
141
|
|
|
132
|
-
it(
|
|
133
|
-
const input =
|
|
134
|
-
await expect(
|
|
135
|
-
|
|
142
|
+
it("throws error for unknown fixed color in strict mode", async () => {
|
|
143
|
+
const input = ".test { color: SeyunaFixedColor(unknown); }";
|
|
144
|
+
await expect(
|
|
145
|
+
run(input, { config: mockConfig, strict: true }),
|
|
146
|
+
).rejects.toThrow(/Fixed color 'unknown' not found/);
|
|
136
147
|
});
|
|
137
148
|
|
|
138
|
-
it(
|
|
139
|
-
const input =
|
|
140
|
-
await expect(
|
|
141
|
-
|
|
149
|
+
it("throws error for unknown color in SeyunaAlpha() in strict mode", async () => {
|
|
150
|
+
const input = ".test { color: SeyunaAlpha(unknown, 0.5); }";
|
|
151
|
+
await expect(
|
|
152
|
+
run(input, { config: mockConfig, strict: true }),
|
|
153
|
+
).rejects.toThrow(/Color 'unknown' not found in seyuna.json/);
|
|
142
154
|
});
|
|
143
155
|
|
|
144
156
|
it('processes @import "seyuna"', async () => {
|
|
145
157
|
const input = '@import "seyuna";';
|
|
146
158
|
const result = await run(input, { config: mockConfig });
|
|
147
|
-
|
|
159
|
+
|
|
148
160
|
// Check for root variables (hues)
|
|
149
|
-
expect(result.css).toContain(
|
|
150
|
-
expect(result.css).toContain(
|
|
151
|
-
expect(result.css).toContain(
|
|
152
|
-
expect(result.css).toContain(
|
|
153
|
-
|
|
161
|
+
expect(result.css).toContain(":root");
|
|
162
|
+
expect(result.css).toContain("--primary-hue: 200");
|
|
163
|
+
expect(result.css).toContain("--secondary-hue: 100");
|
|
164
|
+
expect(result.css).not.toContain("--alpha-hue");
|
|
165
|
+
|
|
154
166
|
// Check for mode selectors
|
|
155
167
|
expect(result.css).toContain('[data-mode="light"]');
|
|
156
168
|
expect(result.css).toContain('[data-mode="dark"]');
|
|
157
|
-
expect(result.css).toContain(
|
|
158
|
-
|
|
169
|
+
expect(result.css).toContain("--lightness: 0.66");
|
|
170
|
+
|
|
159
171
|
// Check for system preference media queries
|
|
160
|
-
expect(result.css).toContain(
|
|
161
|
-
expect(result.css).toContain(
|
|
172
|
+
expect(result.css).toContain("@media (prefers-color-scheme: light)");
|
|
173
|
+
expect(result.css).toContain("@media (prefers-color-scheme: dark)");
|
|
162
174
|
|
|
163
175
|
// Check for base styles (reset)
|
|
164
|
-
expect(result.css).toContain(
|
|
165
|
-
expect(result.css).toContain(
|
|
176
|
+
expect(result.css).toContain("@layer reset");
|
|
177
|
+
expect(result.css).toContain("-webkit-text-size-adjust: none");
|
|
166
178
|
|
|
167
179
|
// Check for palette colors
|
|
168
|
-
expect(result.css).toContain(
|
|
180
|
+
expect(result.css).toContain("--surface-lightness: 1");
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('configures via @config "seyuna"', async () => {
|
|
184
|
+
const input = `
|
|
185
|
+
@config "seyuna" {
|
|
186
|
+
--hue-custom: 123;
|
|
187
|
+
--color-brand: 0.5 0.2 100;
|
|
188
|
+
--light-lightness: 0.8;
|
|
189
|
+
}
|
|
190
|
+
@import "seyuna";
|
|
191
|
+
.test {
|
|
192
|
+
color: SeyunaStandardColor(custom);
|
|
193
|
+
background: SeyunaFixedColor(brand);
|
|
194
|
+
}
|
|
195
|
+
`;
|
|
196
|
+
const result = await postcss([plugin({ config: undefined })]).process(
|
|
197
|
+
input,
|
|
198
|
+
{ from: undefined },
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
expect(result.css).not.toContain("@config");
|
|
202
|
+
expect(result.css).toContain("--custom-hue: 123");
|
|
203
|
+
expect(result.css).toContain(
|
|
204
|
+
"color: oklch(var(--lightness) var(--chroma) var(--custom-hue) / 1)",
|
|
205
|
+
);
|
|
206
|
+
expect(result.css).toContain(
|
|
207
|
+
"background: oklch(var(--brand-lightness) var(--brand-chroma) var(--brand-hue) / 1)",
|
|
208
|
+
);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it("overrides fixed colors in mode blocks", async () => {
|
|
212
|
+
const input = `
|
|
213
|
+
@config "seyuna" {
|
|
214
|
+
--color-brand: 0.5 0.2 100;
|
|
215
|
+
--light-color-brand: 1 0 100;
|
|
216
|
+
}
|
|
217
|
+
@import "seyuna";
|
|
218
|
+
`;
|
|
219
|
+
const result = await postcss([plugin({ config: undefined })]).process(
|
|
220
|
+
input,
|
|
221
|
+
{ from: undefined },
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
// Global :root should have the original
|
|
225
|
+
expect(result.css).toContain(":root");
|
|
226
|
+
expect(result.css).toContain("--brand-lightness: 0.5");
|
|
227
|
+
|
|
228
|
+
// Light mode should have the override
|
|
229
|
+
expect(result.css).toContain('[data-mode="light"]');
|
|
230
|
+
expect(result.css).toContain("--brand-lightness: 1");
|
|
169
231
|
});
|
|
170
232
|
});
|