Created
April 29, 2021 22:43
-
-
Save LionsAd/b794e5f9d115bc985916bcf7fa944f46 to your computer and use it in GitHub Desktop.
Tailwind.css-to-JSON
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require("fs") | |
const postcss = require("postcss") | |
const selectorParser = require("postcss-selector-parser") | |
const { | |
promisify | |
} = require("util") | |
const { | |
createHash, | |
} = require('crypto') | |
| |
const asyncFs = { | |
access: promisify(fs.access), | |
readFile: promisify(fs.readFile), | |
}; | |
| |
const ALWAYS = 'keep:always'; | |
| |
function isInPseudoClass(selector) { | |
return ( | |
(selector.parent && | |
selector.parent.type === "pseudo" && | |
selector.parent.value.startsWith(":")) || | |
false | |
); | |
} | |
| |
function findSelectors(selector) { | |
// ignore the selector if it is inside a pseudo class | |
if (isInPseudoClass(selector)) { | |
return []; | |
} | |
| |
let matches = []; | |
| |
for (const selectorNode of selector.nodes) { | |
switch (selectorNode.type) { | |
case "attribute": | |
break; | |
case "class": | |
case "id": | |
case "tag": | |
matches.push(selectorNode.toString()) | |
break; | |
default: | |
continue; | |
} | |
} | |
| |
return matches; | |
} | |
| |
async function process() { | |
let rules = {}; | |
let selectors = {}; | |
| |
let content = await asyncFs.readFile("css/utils.css", "utf-8") | |
let root = postcss.parse(content) | |
let atrule = ''; | |
| |
root.walk((node) => { | |
// Store atrule for later use. | |
if (node.type == 'atrule') { | |
let nodes = node.nodes; | |
node.nodes = []; | |
atrule = node.toString(); | |
node.nodes = nodes; | |
} | |
| |
// exit if it is not a rule | |
if (node.type != "rule" || !node.selector) { | |
return; | |
} | |
| |
let rule = node.toString(); | |
let ruleHash = createHash('sha1').update(rule).digest('hex'); | |
| |
let item = {}; | |
item['rule'] = rule; | |
| |
// Check again that this has an atrule. | |
if (node.parent && node.parent.type == 'atrule') { | |
item['atrule'] = atrule; | |
} | |
| |
rules[ruleHash] = item; | |
| |
selectorParser((selectorsParsed) => { | |
selectorsParsed.walk((selector) => { | |
if (selector.type !== "selector") { | |
return; | |
} | |
| |
if (selector.toString() == '[hidden]') { | |
return; | |
} | |
| |
// Find selector matches | |
let matches = findSelectors(selector); | |
if (matches.length == 0) { | |
matches.push(ALWAYS); | |
} | |
| |
delete item['and']; | |
| |
if (matches.length > 1) { | |
item['and'] = matches; | |
matches = [matches[0]]; | |
} | |
| |
for (key in matches) { | |
let match = matches[key] | |
| |
if (!(match in selectors)) { | |
selectors[match] = []; | |
} | |
| |
selectors[match].push(item); | |
} | |
}); | |
}).processSync(node.selector); | |
}); | |
| |
console.log(JSON.stringify(selectors)); | |
} | |
| |
process(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment