If you don't know what is AST, first read [Wikipedia/Abstract syntax tree] (http://en.wikipedia.org/wiki/Abstract_syntax_tree).
This AST format is compatible with [CSSP] (https://github.com/css/cssp).
In general it looks like this:
['stylesheet',
['atrules', ..],
['s', ' '],
['comment', 'sample'],
['ruleset',
['selector', ..]],
['block', ..]]
operator / unary — rather artificial division, in addition unary is misnamed. Utilities working with AST may need to handle both types of nodes instead of one.
raw — currently raw contains unparsed progid
IE. In the future it makes sense to parse that parts in full AST.
Node is a JavaScript-array in the following way:
['token type', <- mandatory
<contents>] <- optional
Content can be other nodes or CSS source.
In case needInfo
was true
when the style was parsed, the node includes info-object. Now it only contains the line number from which the token begins in style, but in the future there will be more information:
[{ ln: ln }, <- info-object
'token type', <- mandatory
<content>] <- optional
If you do not know in which mode was the parsing, check the type of the first element in the first node.
Style. The root node of AST.
Consists of ruleset (a set of rules with selectors), atrules (single-line at-rule), atruleb (block at-rule) and atruler (at-rule with ruleset). Also there are s (whitespace) and comment (comments).
@import "x.png"; /*sample*/ x{p:v}
↓
['stylesheet',
['atrules',
['atkeyword',
['ident', 'import']],
['s', ' '],
['string', '"x.png"']],
['s', ' '],
['comment', 'sample'],
['s', ' '],
['ruleset',
['selector',
['simpleselector',
['ident', 'x']]],
['block',
['declaration',
['property',
['ident', 'p']],
['value',
['ident', 'v']]]]]]
Comment.
/* test */
↓
['comment', ' test ']
Whitespace: space, \t
, \n
, \r
.
/*a*/ /*b*/
↓
['comment', 'a'],
['s', ' '],
['comment', 'b']
String.
'test'
"test"
↓
['string', ''test'']
['string', '"test"']
Identifiers or names.
In atkeyword:
@import ..;
↓
['atkeyword',
['ident', 'import']]
In clazz:
.abc
↓
['clazz',
['ident', 'abc']]
In dimension:
10px
↓
['dimension',
['number', '10'],
['ident', 'px']]
Number.
10
12.34
↓
['number', '10']
['number', '12.34']
Number with percent sign.
10%
↓
['percentage',
['number', '10']]
Number with dimension unit.
10px
↓
['dimension',
['number', '10'],
['ident', 'px']]
Hexadecimal number in simpleselector.
.. #FFF .. { .. }
↓
['shash', 'FFF']
Hexadecimal number in value.
.. { ..: #FFF }
↓
['vhash', 'FFF']
Class.
.abc
↓
['clazz',
['ident', 'abc']]
Namespace sign in simpleselector.
*|E { .. }
↓
['simpleselector',
['ident', '*'],
['namespace'],
['ident', 'E']]
Combinator: +
, >
, ~
.
x+y { .. }
↓
['simpleselector',
['ident', 'x'],
['combinator', '+'],
['ident', 'y']]
Operator: /
, ,
, :
, =
.
test(x,y)
↓
['funktion',
['ident', 'test'],
['functionBody',
['ident', 'x'],
['operator', ','],
['ident', 'y']]]
Unary (or arithmetical) sign: +
, -
.
nth-last-child(3n+0)
↓
['nthselector',
['ident', 'nth-last-child'],
['nth', '3n'],
['unary', '+'],
['nth', '0']]
URI.
@import url('/css/styles.css')
↓
['atrules',
['atkeyword',
['ident', 'import']],
['s', ' '],
['uri',
['string', ''/css/styles.css'']]]
Braces.
()
(1)
↓
['braces', '(', ')']
['braces', '(', ')',
['number', '1']]
Attribute selector operator: =
, ~=
, ^=
, $=
, *=
, |=
.
[a='b']
↓
['attrib',
['ident', 'a'],
['attrselector', '='],
['string', ''b'']]
Attribute selector.
[a='b']
↓
['attrib',
['ident', 'a'],
['attrselector', '='],
['string', ''b'']]
Numbers and identifiers in nthselector.
:nth-child(2n+1)
↓
['nthselector',
['ident', 'nth-child'],
['nth', '2n'],
['unary', '+'],
['nth', '1']]
:nth-
pseudo-classes.
It consists of a pseudo-class ident and content.
:nth-last-child(+3n-2)
↓
['nthselector',
['ident', 'nth-last-child'],
['unary', '+'],
['nth', '3n'],
['unary', '-'],
['nth', '2']]
Pseudo-class.
test:visited
↓
['simpleselector',
['ident', 'test'],
['pseudoc',
['ident', 'visited']]]
Pseudo-element.
p::first-line
↓
['simpleselector',
['ident', 'p'],
['pseudoe',
['ident', 'first-line']]]
simpleselector delimiter in selector: ,
.
x,y{ .. }
↓
['selector',
['simpleselector',
['ident', 'x']],
['delim'],
['simpleselector',
['ident', 'y']]]
Sets of selectors between a commas.
x, y+z { .. }
↓
['selector',
['simpleselector',
['ident', 'x']],
['delim'],
['simpleselector',
['s', ' '],
['ident', 'y'],
['combinator', '+'],
['ident', 'z'],
['s', ' ']]]
Node to store simpleselector groups.
x, y, [a=b] { .. }
↓
['selector',
['simpleselector',
['ident', 'x']],
['delim'],
['simpleselector',
['s', ' '],
['ident', 'y']],
['delim'],
['simpleselector',
['s', ' '],
['attrib',
['ident', 'a'],
['attrselector', '='],
['ident', 'b']],
['s', ' ']]]
Node to store property / value pairs.
Consists of property (property name) and value (property value).
color: red
↓
['declaration',
['property',
['ident', 'color']],
['value',
['s', ' '],
['ident', 'red']]]
Part of the style in the braces.
{ color: red }
↓
['block',
['s', ' '],
['declaration',
['property',
['ident', 'color']],
['value',
['s', ' '],
['ident', 'red'],
['s', ' ']]]]
declaration delimiter in block: ;
.
x {a: b; c: d}
↓
['block',
['declaration',
['property',
['ident', 'a']],
['value',
['s', ' '],
['ident', 'b']]],
['decldelim'],
['s', ' '],
['declaration',
['property',
['ident', 'c']],
['value',
['s', ' '],
['ident', 'd']]]]
Node to store IE filter
.
Consists of property (property name), filterv (contents) и progid (progid
itself).
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='a.png',sizingMethod='scale')
↓
['filter',
['property',
['ident', 'filter']],
['filterv',
['progid',
['raw', 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src='a.png',sizingMethod='scale')']]]]
Unparsed parts of the style. Refers to a specific browser specific extensions, usually IE filter
.
progid:DXImageTransform.Microsoft.AlphaImageLoader(src='a.png',sizingMethod='scale')
↓
['progid',
['raw', 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src='a.png',sizingMethod='scale')']]]]
Function.
Consists of ident (function name) and functionBody (function body).
color: rgb(255,0,0)
↓
['declaration',
['property',
['ident', 'color']],
['value',
['s', ' '],
['funktion',
['ident', 'rgb'],
['functionBody',
['number', '255'],
['operator', ','],
['number', '0'],
['operator', ','],
['number', '0']]]]]
Node to store expression
.
left:expression(document.body.offsetWidth+1)
↓
['declaration',
['property',
['ident', 'left']],
['value',
['functionExpression', 'document.body.offsetWidth+1']]]
!important
keyword.
a: b !important
↓
['declaration',
['property',
['ident', 'a']],
['value',
['s', ' '],
['ident', 'b'],
['s', ' '],
['important']]]
A set of rules with selectors.
Consists of selector (selector) and block (a set of rules).
x, y {p:v}
↓
['ruleset',
['selector',
['simpleselector',
['ident', 'x']],
['delim'],
['simpleselector',
['s', ' '],
['ident', 'y'],
['s', ' ']]],
['block',
['declaration',
['property',
['ident', 'p']],
['value',
['ident', 'v']]]]]
at-rule identifier.
@font-face ..
↓
['atkeyword',
['ident', 'font-face']]
Singleline at-rule.
Consists of atkeyword (at-rule identifier) and the rule.
@import url('/css/styles.css')
↓
['atrules',
['atkeyword',
['ident', 'import']],
['s', ' '],
['uri',
['string', ''/css/styles.css'']]]
Block at-rule.
Consists of atkeyword (at-rule identifier), rule and block.
@test x y {p:v}
↓
['atruleb',
['atkeyword',
['ident', 'test']],
['s', ' '],
['ident', 'x'],
['s', ' '],
['ident', 'y'],
['s', ' '],
['block',
['declaration',
['property',
['ident', 'p']],
['value',
['ident', 'v']]]]]
At-rule with ruleset.
Consists of atkeyword (at-rule identifier), atrulerq (rule) and atrulers (style).
@media x y {s{p:v}}
↓
['atruler',
['atkeyword',
['ident', 'media']],
['atrulerq',
['s', ' '],
['ident', 'x'],
['s', ' '],
['ident', 'y'],
['s', ' ']],
['atrulers',
['ruleset',
['selector',
['simpleselector',
['ident', 's']]],
['block',
['declaration',
['property',
['ident', 'p']],
['value',
['ident', 'v']]]]]]]
Node to store invalid (or unknown) parts of the style, that parser can extract and continue on.
// invalid
↓
['stylesheet',
['unknown', '// invalid']]