1- import postcss from "postcss" ;
1+ import postcss , { type CssSyntaxError } from "postcss" ;
22import tailwindcss from "tailwindcss" ;
33import autoprefixer from "autoprefixer" ;
44import { NextApiRequest , NextApiResponse } from "next" ;
@@ -8,52 +8,69 @@ interface RequestBody {
88 classes : string ;
99}
1010
11+ const processor = postcss ( [
12+ tailwindcss ( {
13+ config : { content : [ "./*.none" ] , corePlugins : { preflight : false } } ,
14+ } ) ,
15+ autoprefixer ,
16+ ] ) ;
17+
18+ const beautifyOptions : Parameters < typeof cssbeautify > [ 1 ] = {
19+ indent : " " ,
20+ openbrace : "end-of-line" ,
21+ autosemicolon : true ,
22+ } ;
23+
1124export default async function handler (
1225 req : NextApiRequest ,
1326 res : NextApiResponse
1427) : Promise < void > {
15- const { classes } : RequestBody = req . body ;
16-
17- const css = `
18- @tailwind base;
19- @tailwind components;
20- @tailwind utilities;
21- .generated {
22- @apply ${ classes } ;
23- }
24- ` ;
25-
26- try {
27- const result = await postcss ( [
28- tailwindcss ( {
29- config : { content : [ "./*.none" ] , corePlugins : { preflight : false } } ,
30- } ) ,
31- autoprefixer ,
32- ] )
33- . process ( css , { from : undefined } )
34- . then ( ( result ) => {
35- let css = result . css ;
36-
37- // Find ".generated" text and extract everything after it.
38- const generatedIndex = css . indexOf ( ".generated" ) ;
39- if ( generatedIndex !== - 1 ) {
40- css = css . substring ( generatedIndex ) ;
41- } else {
42- css = "no: result;" ;
43- }
28+ const body : RequestBody = req . body ;
29+ const classes : string [ ] = body . classes . split ( " " ) ;
30+ const customClasses : string [ ] = [ ] ;
31+ let doneProcessing = false ;
32+
33+ do {
34+ try {
35+ const css = `.generated { @apply ${ classes . join ( " " ) } ; }` ;
36+
37+ let result = await processor
38+ . process ( css , { from : undefined } )
39+ . then ( ( result ) => result . css ) ;
4440
45- // Format the CSS using cssbeautify
46- css = cssbeautify ( css , {
47- indent : " " ,
48- openbrace : "end-of-line" ,
49- autosemicolon : true ,
50- } ) ;
41+ if ( customClasses . length ) {
42+ const classes = customClasses . join ( ", ." ) ;
43+ result = `.${ classes } {\n /* Custom classes not found in Tailwind CSS */} ${ result } ` ;
44+ }
5145
52- return css . trim ( ) ;
53- } ) ;
46+ result = cssbeautify ( result , beautifyOptions ) ;
5447
55- res . status ( 200 ) . send ( result ) ;
56- } catch ( error ) {
57- res . status ( 500 ) . send ( error . toString ( ) ) ;
58- }
48+ res . status ( 200 ) . send ( result ) ;
49+ doneProcessing = true ;
50+
51+ //
52+ } catch ( error ) {
53+ if ( error ?. name === "CssSyntaxError" ) {
54+ const cssError = error as CssSyntaxError ;
55+ const customClass = cssError . reason . match (
56+ / ` ( [ ^ ` ] + ) ` c l a s s d o e s n o t e x i s t /
57+ ) ?. [ 1 ] ;
58+
59+ if ( customClass ) {
60+ customClasses . push ( customClass ) ;
61+ classes . splice ( classes . indexOf ( customClass ) , 1 ) ;
62+
63+ //
64+ } else {
65+ res . status ( 500 ) . send ( error . toString ( ) ) ;
66+ doneProcessing = true ;
67+ }
68+
69+ //
70+ } else {
71+ res . status ( 500 ) . send ( error . toString ( ) ) ;
72+ doneProcessing = true ;
73+ }
74+ }
75+ } while ( ! doneProcessing ) ;
5976}
0 commit comments