Skip to content

Commit 00c141e

Browse files
committed
Basic implementation
1 parent 3c05a6b commit 00c141e

File tree

5 files changed

+1510
-1
lines changed

5 files changed

+1510
-1
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/node_modules

package.json

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
{
22
"name": "cascada",
3-
"version": "0.0.0"
3+
"version": "0.0.1",
4+
"main": "packages/cascada/index.js",
5+
"scripts": {
6+
"test": "mocha"
7+
},
8+
"devDependencies": {
9+
"mocha": "^2.2.5"
10+
}
411
}

packages/cascada/index.js

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
const inspect = require('util').inspect;
2+
const css = require('../parse-css');
3+
4+
module.exports.parse = function parse(source) {
5+
return acceptStylesheet(
6+
css.parseAStylesheet(source)
7+
);
8+
};
9+
10+
function acceptStylesheet(node) {
11+
return {
12+
type: 'StyleSheet',
13+
rules: acceptRules(node.value)
14+
};
15+
}
16+
17+
function acceptRules(nodes) {
18+
return nodes.map(acceptRule);
19+
}
20+
21+
function acceptRule(node) {
22+
switch (node.type) {
23+
case 'QUALIFIED-RULE': return acceptStyleRule(node);
24+
case 'AT-RULE': return acceptAtRule(node);
25+
default: throw new Error("Unknown rule type: " + node.type);
26+
}
27+
}
28+
29+
function acceptStyleRule(node) {
30+
return {
31+
type: 'StyleRule',
32+
selectors: [ acceptSelector(node.prelude) ],
33+
body: acceptDeclarations(node.value.value, acceptStyleDeclaration)
34+
}
35+
}
36+
37+
function acceptSelector(tokens) {
38+
return tokens.map(function(token) {
39+
return token.toSource();
40+
}).join('').trimRight();
41+
}
42+
43+
function acceptDeclarations(tokens, acceptor) {
44+
var nodes = css.consumeAListOfDeclarations(
45+
new css.TokenStream(tokens)
46+
);
47+
48+
return nodes.map(function(node) {
49+
return acceptor(node);
50+
});
51+
}
52+
53+
function acceptStyleDeclaration(node) {
54+
switch (node.type) {
55+
case 'DECLARATION': return acceptStylePropertyDeclaration(node);
56+
case 'AT-RULE': return acceptAtRule(node);
57+
default: throw new Error("Unknown style declaration type: " + node.type);
58+
}
59+
}
60+
61+
function acceptStylePropertyDeclaration(node) {
62+
return {
63+
type: 'StylePropertyDeclaration',
64+
important: node.important,
65+
name: node.name,
66+
value: acceptContextualValue(node.name, node.value)
67+
};
68+
}
69+
70+
function acceptContextualValue(name, parts) {
71+
parts = trimWhitespaceTokens(parts);
72+
73+
if (name[0] === '-' && name[1] === '-') {
74+
return acceptCustomPropertyValue(name, parts);
75+
} else {
76+
return acceptStyleValue(name, parts);
77+
}
78+
}
79+
80+
function acceptCustomPropertyValue(name, parts) {
81+
if (parts[0].type === 'BLOCK') {
82+
return acceptMixin(parts);
83+
} else {
84+
return acceptStyleValue(name, parts);
85+
}
86+
}
87+
88+
function acceptMixin(parts) {
89+
var block = parts[0];
90+
91+
return {
92+
type: 'Mixin',
93+
body: acceptDeclarations(block.value, acceptMixinStyleDeclaration)
94+
};
95+
}
96+
97+
function acceptStyleValue(name, parts) {
98+
return printValue(parts);
99+
}
100+
101+
function printValue(parts) {
102+
return parts.map(function(part) {
103+
if (part.tokenType) {
104+
return part.toSource();
105+
} else if (part.type === 'FUNCTION') {
106+
return part.name + '(' + printValue(part.value) + ')';
107+
} else {
108+
throw new Error("Unsupported value part: " + JSON.stringify(part.toJSON()));
109+
}
110+
}).join('');
111+
}
112+
113+
function acceptStyleValueParts(name, parts) {
114+
return parts.map(acceptStyleValuePart);
115+
}
116+
117+
function acceptStyleValuePart(node) {
118+
if (node.tokenType) {
119+
return node;
120+
}
121+
122+
switch (node.type) {
123+
case 'FUNCTION': return acceptFunction(node);
124+
default: throw new Error("Unknown style part: " + node.tokenType + " " + node.type + " " + node)
125+
}
126+
}
127+
128+
function acceptFunction(node) {
129+
throw new Error("Functions in property values (e.g. calc and color) are not yet supported.");
130+
}
131+
132+
function acceptMixinStyleDeclaration(node) {
133+
switch (node.type) {
134+
case 'DECLARATION': return acceptStylePropertyDeclaration(node);
135+
default: throw new Error("Unknown style declaration type: " + node.type);
136+
}
137+
}
138+
139+
140+
function acceptAtRule(node) {
141+
return {
142+
type: 'AtRule',
143+
name: node.name,
144+
prelude: node.prelude,
145+
value: node.value
146+
};
147+
}
148+
149+
function trimWhitespaceTokens(tokens) {
150+
var startIndex = 0;
151+
var endIndex = tokens.length;
152+
153+
while (tokens[startIndex].tokenType === 'WHITESPACE') { startIndex++; }
154+
while (tokens[endIndex-1].tokenType === 'WHITESPACE') { endIndex--; }
155+
156+
return tokens.slice(startIndex, endIndex);
157+
}

0 commit comments

Comments
 (0)