-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplugin-css.ts
106 lines (93 loc) · 3 KB
/
plugin-css.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import { dirname, initCss, transformCss } from "./deps.ts";
import { join, normalize, resolve } from "./deps.ts";
import { IS_DEV } from "./stuff.ts";
export const buildCss = async (options: {
inFile?: string; // input file (e.g. src/app.css)
outFile?: string; // output file (e.g. public/app.css)
watch?: boolean | string; // watch for changes
}) => {
const {
inFile = Deno.cwd(),
outFile = "public/app.css",
watch = false,
} = options;
const doBuild = async () => {
const files = inFile.split(",").map(normalize);
const cssFiles: { path: string; file: string }[] = [];
for (const file of files) {
const maybeFolder = await Deno.stat(file);
if (!maybeFolder.isDirectory) {
throw new Error(
`Input file must be a directory (or comma separated list of directories) containing CSS files. (got ${file})`,
);
}
for await (const entry of Deno.readDir(file)) {
if (entry.isFile && entry.name.endsWith(".css")) {
cssFiles.push({
path: entry.name,
file: file,
});
}
}
}
cssFiles.sort((a, b) => {
const orderA = a.path.split(".").length;
const orderB = b.path.split(".").length;
if (orderA === orderB) {
return a.path.localeCompare(b.path);
}
return orderA - orderB;
});
let combinedCss = "";
for (const file of cssFiles) {
const filePath = join(file.file, file.path);
const cssContent = await Deno.readTextFile(filePath);
combinedCss += cssContent + "\n";
}
const outDir = dirname(outFile);
await Deno.mkdir(outDir, { recursive: true });
if (IS_DEV) {
// write as is
await Deno.writeTextFile(outFile, combinedCss);
}
if (!IS_DEV) {
// minify & optimize
const { code } = transformCss({
filename: outFile,
code: new TextEncoder().encode(combinedCss),
minify: true,
});
await Deno.writeTextFile(outFile, new TextDecoder().decode(code));
}
console.log(`Built CSS file: ${outFile}`);
};
if (!IS_DEV) {
await initCss(undefined);
}
await doBuild();
if (watch) {
const inDirs = inFile.includes(",") ? inFile.split(",").map(normalize) : [normalize(inFile)];
const watchDirs = typeof watch === "string"
? watch.split(",").map(normalize)
: inDirs;
const arePathsEqual = (path1: string, path2: string) => {
return normalize(resolve(path1)) === normalize(resolve(path2));
};
const outDir = dirname(outFile);
if (watchDirs.some((dir) => arePathsEqual(dir, outDir))) {
throw new Error(
"Input watch directory and output directories cannot be the same when using --watch, will cause infinite loop.",
);
}
const watcher = Deno.watchFs(watchDirs, { recursive: true });
for await (const event of watcher) {
if (
event.kind === "modify" ||
event.kind === "create" ||
event.kind === "remove"
) {
await doBuild();
}
}
}
};