Skip to content

Commit 3c2a362

Browse files
committed
Extract custom classes into a separate block
This is done by checking the error repeatedly for custom classes and moving them to another array until no more error is presented. Also: Refactor API code to simplify some constants and to remove unneeded parts like @tailwind directives and finding `.generated` text.
1 parent 94023f2 commit 3c2a362

File tree

1 file changed

+59
-42
lines changed

1 file changed

+59
-42
lines changed

pages/api/generate-css.ts

Lines changed: 59 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import postcss from "postcss";
1+
import postcss, { type CssSyntaxError } from "postcss";
22
import tailwindcss from "tailwindcss";
33
import autoprefixer from "autoprefixer";
44
import { 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+
1124
export 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+
/`([^`]+)` class does not exist/
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

Comments
 (0)