|
1 | 1 | import { extractThemeCSS } from './extract-theme-css';
|
2 | 2 |
|
| 3 | +function generateStringInAllPossibleOrders(str: string): string[] { |
| 4 | + const result: string[] = []; |
| 5 | + |
| 6 | + // Split the string into parts based on spaces |
| 7 | + const parts = str.split(' '); |
| 8 | + |
| 9 | + // Recursive function to generate permutations |
| 10 | + function permute(arr: string[], m: string[] = []) { |
| 11 | + if (arr.length === 0) { |
| 12 | + result.push(m.join(' ')); |
| 13 | + } else { |
| 14 | + for (let i = 0; i < arr.length; i++) { |
| 15 | + const curr = arr.slice(); |
| 16 | + const next = curr.splice(i, 1); |
| 17 | + permute(curr, m.concat(next)); |
| 18 | + } |
| 19 | + } |
| 20 | + } |
| 21 | + |
| 22 | + permute(parts); |
| 23 | + |
| 24 | + return result; |
| 25 | +} |
| 26 | + |
3 | 27 | describe('Extract theme from css', () => {
|
4 |
| - test(`GIVEN primary color is "cyan-600", |
5 |
| - border-radius is 0, |
6 |
| - base color is "neutral" |
7 |
| - and style is "simple" |
| 28 | + test(`GIVEN theme string is 'simple base-neutral primary-cyan-600 border-radius-0' |
8 | 29 | THEN generate the right css variables`, () => {
|
9 | 30 | const inputThemeString = 'simple base-neutral primary-cyan-600 border-radius-0';
|
10 | 31 |
|
@@ -79,12 +100,94 @@ describe('Extract theme from css', () => {
|
79 | 100 | }"
|
80 | 101 | `);
|
81 | 102 | });
|
| 103 | + |
| 104 | + test(`GIVEN primary color is "cyan-600", |
| 105 | + border-radius is 0, |
| 106 | + base color is "neutral", |
| 107 | + and style is "simple", |
| 108 | + in whatever order, |
| 109 | + THEN generate the right css variables`, () => { |
| 110 | + const output = ` |
| 111 | + "@layer base { |
| 112 | + :root { |
| 113 | + --background: 0 0% 100%; |
| 114 | + --foreground: 0 0% 9%; |
| 115 | + --muted: 0 0% 96.1%; |
| 116 | + --muted-foreground: 0 0% 45.1%; |
| 117 | + --popover: 0 0% 100%; |
| 118 | + --popover-foreground: 0 0% 9%; |
| 119 | + --card: 0 0% 100%; |
| 120 | + --card-foreground: 0 0% 9%; |
| 121 | + --border: 0 0% 89.8%; |
| 122 | + --input: 0 0% 89.8%; |
| 123 | + --primary: 191.6 91.4% 36.5%; |
| 124 | + --primary-foreground: 0 0% 100%; |
| 125 | + --secondary: 0 0% 83.1%; |
| 126 | + --secondary-foreground: 0 0% 9%; |
| 127 | + --accent: 0 0% 96.1%; |
| 128 | + --accent-foreground: 0 0% 9%; |
| 129 | + --alert: 0 84.2% 60.2%; |
| 130 | + --alert-foreground: 0 0% 98%; |
| 131 | + --ring: 0 0% 9%; |
| 132 | + --border-width: 0px; |
| 133 | + --border-radius: 0; |
| 134 | + --shadow-base: 0 1px 2px 0 rgba(0, 0, 0, 0.01); |
| 135 | + --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); |
| 136 | + --shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.1), 0 1px 5px 0px rgba(0, 0, 0, 0.1); |
| 137 | + --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1); |
| 138 | + --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1); |
| 139 | + --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1); |
| 140 | + --shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 1); |
| 141 | + --shadow-inner: inset 0 2px 4px 0 rgba(0, 0, 0, 0.01); |
| 142 | + --transform-press: scale(0.95); |
| 143 | + } |
| 144 | + .dark { |
| 145 | + --background: 0 0% 9%; |
| 146 | + --foreground: 0 0% 98%; |
| 147 | + --muted: 0 0% 14.9%; |
| 148 | + --muted-foreground: 0 0% 63.9%; |
| 149 | + --popover: 0 0% 9%; |
| 150 | + --popover-foreground: 0 0% 98%; |
| 151 | + --card: 0 0% 9%; |
| 152 | + --card-foreground: 0 0% 98%; |
| 153 | + --border: 0 0% 14.9%; |
| 154 | + --input: 0 0% 14.9%; |
| 155 | + --primary: 191.6 91.4% 36.5%; |
| 156 | + --primary-foreground: 0 0% 100%; |
| 157 | + --secondary: 0 0% 25.1%; |
| 158 | + --secondary-foreground: 0 0% 98%; |
| 159 | + --accent: 0 0% 14.9%; |
| 160 | + --accent-foreground: 0 0% 98%; |
| 161 | + --alert: 0 84.2% 60.2%; |
| 162 | + --alert-foreground: 0 0% 98%; |
| 163 | + --ring: 0 0% 83.1%; |
| 164 | + --border-width: 0px; |
| 165 | + --border-radius: 0; |
| 166 | + --shadow-base: 0 1px 2px 0 rgba(0, 0, 0, 0.01); |
| 167 | + --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); |
| 168 | + --shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.1), 0 1px 5px 0px rgba(0, 0, 0, 0.1); |
| 169 | + --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1); |
| 170 | + --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1); |
| 171 | + --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1); |
| 172 | + --shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 1); |
| 173 | + --shadow-inner: inset 0 2px 4px 0 rgba(0, 0, 0, 0.01); |
| 174 | + --transform-press: scale(0.95); |
| 175 | + } |
| 176 | + }" |
| 177 | + `; |
| 178 | + |
| 179 | + const themeStringInEveryOrder = generateStringInAllPossibleOrders( |
| 180 | + 'simple base-neutral primary-cyan-600 border-radius-0', |
| 181 | + ); |
| 182 | + |
| 183 | + themeStringInEveryOrder.forEach((themeString) => { |
| 184 | + const theme = extractThemeCSS(themeString, exampleRootCssContent); |
| 185 | + expect(theme).toMatchInlineSnapshot(output); |
| 186 | + }); |
| 187 | + }); |
82 | 188 | });
|
83 | 189 |
|
84 |
| -test(`GIVEN primary color is "cyan-600", |
85 |
| - border-radius is 0, |
86 |
| - base color is "neutral" |
87 |
| - and style is "simple" |
| 190 | +test(`GIVEN theme string is 'brutalist base-stone primary-pink-700 border-radius-dot-75' |
88 | 191 | THEN generate the right css variables`, () => {
|
89 | 192 | const inputThemeString = 'brutalist base-stone primary-pink-700 border-radius-dot-75';
|
90 | 193 |
|
@@ -160,6 +263,91 @@ test(`GIVEN primary color is "cyan-600",
|
160 | 263 | `);
|
161 | 264 | });
|
162 | 265 |
|
| 266 | +test(`GIVEN primary color is "pink-700", |
| 267 | + border-radius is 0.75, |
| 268 | + base color is "stone", |
| 269 | + and style is "brutalist", |
| 270 | + in whatever order, |
| 271 | + THEN generate the right css variables`, () => { |
| 272 | + const output = ` |
| 273 | + "@layer base { |
| 274 | + :root { |
| 275 | + --background: 0 0% 100%; |
| 276 | + --foreground: 24 9.8% 10%; |
| 277 | + --muted: 60 4.8% 95.9%; |
| 278 | + --muted-foreground: 25 5.3% 44.7%; |
| 279 | + --popover: 0 0% 100%; |
| 280 | + --popover-foreground: 24 9.8% 10%; |
| 281 | + --card: 0 0% 100%; |
| 282 | + --card-foreground: 24 9.8% 10%; |
| 283 | + --border: 0 0% 0%; |
| 284 | + --input: 0 0% 0%; |
| 285 | + --primary: 335.1 77.6% 42%; |
| 286 | + --primary-foreground: 0 0% 100%; |
| 287 | + --secondary: 24 5.7% 82.9%; |
| 288 | + --secondary-foreground: 24 9.8% 10%; |
| 289 | + --accent: 60 4.8% 95.9%; |
| 290 | + --accent-foreground: 24 9.8% 10%; |
| 291 | + --alert: 0 84.2% 60.2%; |
| 292 | + --alert-foreground: 60 9.1% 97.8%; |
| 293 | + --ring: 0 0% 0%; |
| 294 | + --border-width: 2px; |
| 295 | + --border-radius: 0.75rem; |
| 296 | + --shadow-base: 0px 0px 0px 0 rgba(0, 0, 0, 1); |
| 297 | + --shadow-sm: 4px 4px 0px 0 rgba(0, 0, 0, 1); |
| 298 | + --shadow: 5px 5px 0px 0px rgba(0, 0, 0, 1); |
| 299 | + --shadow-md: 6px 6px 0px 0px rgba(0, 0, 0, 1); |
| 300 | + --shadow-lg: 8px 8px 0px 0px rgba(0, 0, 0, 1); |
| 301 | + --shadow-xl: 11px 11px 0px 0px rgba(0, 0, 0, 1); |
| 302 | + --shadow-2xl: 13px 13px 0px 0px rgba(0, 0, 0, 1); |
| 303 | + --shadow-inner: inset 2px 2px 0px 0px rgba(0, 0, 0, 0); |
| 304 | + --transform-press: translate(4px, 4px); |
| 305 | + } |
| 306 | + .dark { |
| 307 | + --background: 24 9.8% 10%; |
| 308 | + --foreground: 60 9.1% 97.8%; |
| 309 | + --muted: 12 6.5% 15.1%; |
| 310 | + --muted-foreground: 24 5.4% 63.9%; |
| 311 | + --popover: 24 9.8% 10%; |
| 312 | + --popover-foreground: 60 9.1% 97.8%; |
| 313 | + --card: 24 9.8% 10%; |
| 314 | + --card-foreground: 60 9.1% 97.8%; |
| 315 | + --border: 0 0% 0%; |
| 316 | + --input: 0 0% 0%; |
| 317 | + --primary: 335.1 77.6% 42%; |
| 318 | + --primary-foreground: 0 0% 100%; |
| 319 | + --secondary: 30 6.3% 25.1%; |
| 320 | + --secondary-foreground: 60 9.1% 97.8%; |
| 321 | + --accent: 12 6.5% 15.1%; |
| 322 | + --accent-foreground: 60 9.1% 97.8%; |
| 323 | + --alert: 0 84.2% 60.2%; |
| 324 | + --alert-foreground: 0 0% 98%; |
| 325 | + --ring: 0 0% 0%; |
| 326 | + --border-width: 3px; |
| 327 | + --border-radius: 0.75rem; |
| 328 | + --shadow-base: 0px 0px 0px 0 rgba(0, 0, 0, 1); |
| 329 | + --shadow-sm: 4px 4px 0px 0 rgba(0, 0, 0, 1); |
| 330 | + --shadow: 5px 5px 0px 0px rgba(0, 0, 0, 1); |
| 331 | + --shadow-md: 6px 6px 0px 0px rgba(0, 0, 0, 1); |
| 332 | + --shadow-lg: 8px 8px 0px 0px rgba(0, 0, 0, 1); |
| 333 | + --shadow-xl: 11px 11px 0px 0px rgba(0, 0, 0, 1); |
| 334 | + --shadow-2xl: 13px 13px 0px 0px rgba(0, 0, 0, 1); |
| 335 | + --shadow-inner: inset 0 2px 4px 0 rgba(0, 0, 0, 0.01); |
| 336 | + --transform-press: translate(4px, 4px); |
| 337 | + } |
| 338 | + }" |
| 339 | + `; |
| 340 | + |
| 341 | + const themeStringInEveryOrder = generateStringInAllPossibleOrders( |
| 342 | + 'brutalist base-stone primary-pink-700 border-radius-dot-75', |
| 343 | + ); |
| 344 | + |
| 345 | + themeStringInEveryOrder.forEach((themeString) => { |
| 346 | + const theme = extractThemeCSS(themeString, exampleRootCssContent); |
| 347 | + expect(theme).toMatchInlineSnapshot(output); |
| 348 | + }); |
| 349 | +}); |
| 350 | + |
163 | 351 | const exampleRootCssContent = `
|
164 | 352 |
|
165 | 353 | @layer base {
|
|
0 commit comments