CSS Parser For JavaScript?
Solution 1:
Update: I previously mentioned JSCSSP, which is buggy seems to be abandoned. Obviously enough, the css module on NPM is the best:
css = require 'css'
input = '''
body {
font-family: sans-serif;
}
#thing.foo p.bar {
font-weight: bold;
}
'''
obj = css.parse input
sheet = obj.stylesheet
for rule in sheet.rules
rule.selectors = ('#XXX ' + s for s in rule.selectors)
console.log css.stringify(obj)
Output:
#XXX body {
font-family: sans-serif;
}
#XXX #thing.foo p.bar {
font-weight: bold;
}
Solution 2:
Also worth mentioning is LESS. While it is primarily a (fantastic) extension to CSS, the LESS parser does give you access to the AST.
A pure CSS stylesheet is also a valid LESS stylesheet, so you can start with what you have now and ease in to LESS' extensions.
Solution 3:
Here is our open source CSS parser css.js
Here is a simple parsing example :
<script type="text/javascript">
var cssString = ' .someSelector { margin:40px 10px; padding:5px}';
//initialize parser object
var parser = new cssjs();
//parse css string
var parsed = parser.parseCSS(cssString);
console.log(parsed);
</script>
To stringify parsed data structure into CSS string after editing
var newCSSString = parser.getCSSForEditor(parsed);
Main features of our CSS parser is :
- It is lightweight.
- It outputs easy to understand javascript object. No complex AST.
- It is battle tested(and unit tested also) and constantly used in our products(JotForm Form Designer).
- It supports media queries, keyframes and font-face rules.
- It preserves comments while parsing.
Solution 4:
Solution 5:
Edit
I ended up using this library which was light enough for my implementation (provided in Kemal Dağ
's answer). Other options were too heavy for the client-side implementation I was after.
https://github.com/jotform/css.js
Original Content
a paid nerd
's original answer worked great until I hit media queries.
I had to add some recursion and this is what I ended up with.
Forgive me for the TypeScript.
TypeScript Implementation
private scopeCSS(css: string): CSS.Stylesheet {
let ast: CSS.Stylesheet = CSS.parse(css);
let stylesheet: CSS.StyleRules|undefined = ast.stylesheet;
if (stylesheet) {
let rules: Array<CSS.Rule|CSS.Media> = stylesheet.rules;
let prefix = `[data-id='sticky-container-${this.parent.id}']`;
// Append our container scope to rules
// Recursive rule appender
let ruleAppend = (rules: Array<CSS.Rule|CSS.Media>) => {
rules.forEach(rule => {
let cssRule = <CSS.Rule>rule;
let mediaRule = <CSS.Media>rule;
if (cssRule.selectors !== undefined) {
cssRule.selectors = cssRule.selectors.map(selector => `${prefix} ${selector}`);
}
if (mediaRule.rules !== undefined) {
ruleAppend(mediaRule.rules);
}
});
};
ruleAppend(rules);
}
return ast;
}
Babel'ized Vanilla JS Implementation
function scopeCSS(css, prefix) {
var ast = CSS.parse(css);
var stylesheet = ast.stylesheet;
if (stylesheet) {
var rules = stylesheet.rules;
// Append our container scope to rules
// Recursive rule appender
var ruleAppend = function(rules) {
rules.forEach(function(rule) {
if (rule.selectors !== undefined) {
rule.selectors = rule.selectors.map(function(selector) {
return prefix + " " + selector;
});
}
if (rule.rules !== undefined) {
ruleAppend(rule.rules);
}
});
};
ruleAppend(rules);
}
return ast;
}
Post a Comment for "CSS Parser For JavaScript?"