Skip to content

Instantly share code, notes, and snippets.

@rndme
Last active May 11, 2026 20:12
Show Gist options
  • Select an option

  • Save rndme/3aa9a8f2f14feb828b4b2ab31bbfb349 to your computer and use it in GitHub Desktop.

Select an option

Save rndme/3aa9a8f2f14feb828b4b2ab31bbfb349 to your computer and use it in GitHub Desktop.
.parse(css) and then .stringify(theParsedObject) back into CSS
// not ready for production, issues with pseudo selectors in nested rules parsing as props...
let JSCN = {
parse: function parse(str) { // css to object
var sheet = {}, // holds all the selectors and rules
rule = {}, // current rule
float = "", // accumulates chars before determining what to do with them
quoteMode = 0, // [none, single, double] quote mode
sel = "", // current selector
prop = "", // current property
isInRule = false, // true when cursor between { and }
heap = [sheet]; // for nested rules, [deep > shallow]
function addPair() { // move prop:val pair to rule object
if (prop) rule[prop] = float.trim();
float = "";
prop = "";
}
for (var i = 0; i < str.length; i++) { // parse char by char
var it = str[i];
if (it === '"') {
if (str[i - 1] !== '\\') quoteMode = [2, 1, 0][quoteMode];
float += '"';
continue;
} //end if "
if (it === "'") {
if (str[i - 1] !== '\\') quoteMode = [1, 0, 2][quoteMode];
float += "'";
continue;
} //end if '
if (it === ":") {
if (!quoteMode && isInRule) {
prop = float.trim();
float = "";
} else {
float += ":";
}
continue;
} //end if :
if (it === ";") {
if (!quoteMode) {
addPair();
} else {
float += ";";
}
continue;
} //end if ;
if (it === "{") {
if (!quoteMode) {
sel = float.trim();
float = "";
rule = heap.at(-1)[sel] || {};
heap.at(-1)[sel] = rule;
isInRule = true;
heap.push(rule);
prop = "";
} else {
float += "{";
}
continue;
} //end if {
if (it === "}") {
if (!quoteMode) {
addPair();
heap.pop();
isInRule = false;
rule = heap.at(-1)[sel] || {};
sel = "";
} else {
float += "}";
}
continue;
} //end if }
float += it;
}
addPair();
return sheet;
}, //end parse()
stringify: function stringify(objRules, blnCompress, _depth = 1) { // object to css
var [LINE, TAB, SPACE] = blnCompress ? ["", "", ""] : ["\n", "\t", " "];
return Object.entries(objRules).map(([sel, rule]) => {
return sel + SPACE + "{" + LINE + TAB.repeat(_depth) +
Object.entries(rule).map(([prop, val]) => {
if (typeof val === "object") return stringify({ [prop]: val}, blnCompress, _depth + 1);
return `${prop}:${SPACE}${val};`;
}).join(LINE + TAB.repeat(_depth)) +
LINE + TAB.repeat(_depth - 1) + "}";
}).join(LINE).trim();
} // end stringify()
};// end JSCN
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment