-
-
Notifications
You must be signed in to change notification settings - Fork 16
/
index.js
112 lines (95 loc) · 3.21 KB
/
index.js
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
107
108
109
110
111
112
const fs = require("fs");
const path = require("path");
const {promisify} = require("util");
const mkdir = promisify(fs.mkdir);
const {fixClass, toElmName, toScreen} = require("./code-gen.js");
const {formats, cleanOpts} = require("./options.js");
let classes = new Map();
module.exports = (opts = {}) => {
opts = cleanOpts(opts);
return {
postcssPlugin: 'postcss-elm-tailwind',
Rule(rule) {
rule.selector
.split(" ")
.map((sel) => sel.split(","))
.reduce((arr, v) => (arr.push(...v), arr), [])
.forEach((selector) => processSelector(selector, opts));
},
OnceExit() {
const formats_ = formats(opts)
.map(data => splitByScreens(opts, classes, data))
.flat()
.map(data => {
const fileContent = data.elmBodyFn(data.elmModuleName, data.classesSet);
return writeFile(data.elmFile, fileContent);
}
);
return tap(Promise.all(formats_), (p) =>
p.then((files) => console.log("Saved", files))
);
},
}
};
module.exports.postcss = true
function splitByScreens(opts, classesSet, {elmFile, elmModuleName, elmBodyFn}) {
if (!opts.splitByScreens) {
return [{elmFile, elmModuleName, elmBodyFn, classesSet}]
}
const screens = [...opts.screens];
screens.push(null)
return screens.map(
screen => extractScreen(screen, elmFile, elmModuleName, elmBodyFn, classesSet)
)
}
let fixClassStartingWithNumber = (className) =>
className.match(/(\d+)/)
? function () {
let number = className.match(/(\d+)/)[0]
let nName = className.replace(number, '')
let firstChar = nName.charAt(0)
let multiChars = firstChar.repeat(number)
return nName.replace(firstChar, multiChars)
}()
: className
function extractScreen(screen, elmFile, elmModuleName, elmBodyFn, classesSet) {
let newFile = elmFile;
let newModule = elmModuleName;
if (screen !== null) {
let newName = fixClassStartingWithNumber(screen.toUpperCase())
newFile = newFile.replace(".elm", `/${newName}.elm`);
newModule = `${newModule}.${newName}`;
}
const newClasses = new Map();
for (let [cls, val] of classesSet) {
if (screen === val.screen) {
newClasses.set(cls, val);
}
}
return {elmFile: newFile, elmModuleName: newModule, elmBodyFn: elmBodyFn, classesSet: newClasses}
}
async function writeFile(fname, content) {
let folder = path.dirname(fname);
await mkdir(folder, {recursive: true});
return new Promise((resolve, reject) =>
fs.writeFile(fname, content, (err) => {
if (err) return reject(err);
resolve(fname);
})
);
}
function processSelector(selector, opts) {
if (!selector.startsWith(".")) {
// Keep only classes
return;
}
let cls, elm, screen;
cls = fixClass(selector);
elm = toElmName(cls, opts);
screen = toScreen(cls, opts);
classes.set(cls, {elm, screen});
}
const tap = (v, fn) => {
fn(v);
return v;
};