stylus-source 0.21.2 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. data/VERSION +1 -1
  2. data/vendor/History.md +11 -0
  3. data/vendor/Readme.md +4 -0
  4. data/vendor/bin/stylus +9 -32
  5. data/vendor/docs/bifs.md +16 -0
  6. data/vendor/docs/js.md +2 -0
  7. data/vendor/editors/Stylus.tmbundle/Syntaxes/Stylus.tmLanguage +67 -7
  8. data/vendor/lib/functions/index.styl +16 -0
  9. data/vendor/lib/lexer.js +13 -0
  10. data/vendor/lib/nodes/extend.js +41 -0
  11. data/vendor/lib/nodes/group.js +1 -0
  12. data/vendor/lib/nodes/index.js +1 -0
  13. data/vendor/lib/nodes/page.js +1 -1
  14. data/vendor/lib/parser.js +10 -0
  15. data/vendor/lib/renderer.js +13 -0
  16. data/vendor/lib/stylus.js +1 -1
  17. data/vendor/lib/utils.js +66 -0
  18. data/vendor/lib/visitor/compiler.js +65 -61
  19. data/vendor/lib/visitor/evaluator.js +10 -0
  20. data/vendor/lib/visitor/normalizer.js +226 -0
  21. data/vendor/node_modules/cssom/docs/parse.html +15 -1
  22. data/vendor/node_modules/cssom/docs/parse.html_ +268 -0
  23. data/vendor/node_modules/cssom/lib/CSSStyleDeclaration.js +18 -2
  24. data/vendor/node_modules/cssom/lib/parse.js +0 -18
  25. data/vendor/node_modules/cssom/package.json +1 -1
  26. data/vendor/node_modules/cssom/test/CSSStyleDeclaration.test.js +10 -3
  27. data/vendor/package.json +2 -2
  28. data/vendor/test/cases/bifs.keys.css +4 -0
  29. data/vendor/test/cases/bifs.keys.styl +6 -0
  30. data/vendor/test/cases/bifs.values.css +5 -0
  31. data/vendor/test/cases/bifs.values.styl +6 -0
  32. data/vendor/test/cases/css.extend.css +13 -0
  33. data/vendor/test/cases/css.extend.styl +15 -0
  34. data/vendor/test/cases/extend.complex.css +16 -0
  35. data/vendor/test/cases/extend.complex.styl +15 -0
  36. data/vendor/test/cases/extend.css +22 -0
  37. data/vendor/test/cases/extend.multiple-definitions.css +11 -0
  38. data/vendor/test/cases/extend.multiple-definitions.styl +9 -0
  39. data/vendor/test/cases/extend.styl +22 -0
  40. data/vendor/testing/foo.css +3753 -3
  41. data/vendor/testing/foo.styl +7 -0
  42. data/vendor/testing/index.html +5 -50
  43. data/vendor/testing/test.css +19 -4
  44. data/vendor/testing/test.styl +19 -12
  45. metadata +18 -2
@@ -583,6 +583,16 @@ Evaluator.prototype.visitIf = function(node){
583
583
  return ret || nodes.null;
584
584
  };
585
585
 
586
+ /**
587
+ * Visit Extend.
588
+ */
589
+
590
+ Evaluator.prototype.visitExtend = function(extend){
591
+ var selector = extend.selector;
592
+ this.currentBlock.node.extends.push(selector);
593
+ return nodes.null;
594
+ };
595
+
586
596
  /**
587
597
  * Visit Import.
588
598
  */
@@ -0,0 +1,226 @@
1
+
2
+ /*!
3
+ * Stylus - Normalizer
4
+ * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
5
+ * MIT Licensed
6
+ */
7
+
8
+ /**
9
+ * Module dependencies.
10
+ */
11
+
12
+ var Visitor = require('./')
13
+ , nodes = require('../nodes')
14
+ , utils = require('../utils')
15
+ , fs = require('fs');
16
+
17
+ /**
18
+ * Initialize a new `Normalizer` with the given `root` Node.
19
+ *
20
+ * This visitor implements the first stage of the duel-stage
21
+ * compiler, tasked with stripping the "garbage" from
22
+ * the evaluated nodes, ditching null rules, resolving
23
+ * ruleset selectors etc. This step performs the logic
24
+ * necessary to facilitate the "@extend" functionality,
25
+ * as these must be resolved _before_ buffering output.
26
+ *
27
+ * @param {Node} root
28
+ * @api public
29
+ */
30
+
31
+ var Normalizer = module.exports = function Normalizer(root, options) {
32
+ options = options || {};
33
+ Visitor.call(this, root);
34
+ this.stack = [];
35
+ this.extends = {};
36
+ this.map = {};
37
+ };
38
+
39
+ /**
40
+ * Inherit from `Visitor.prototype`.
41
+ */
42
+
43
+ Normalizer.prototype.__proto__ = Visitor.prototype;
44
+
45
+ /**
46
+ * Normalize the node tree.
47
+ *
48
+ * @return {Node}
49
+ * @api private
50
+ */
51
+
52
+ Normalizer.prototype.normalize = function(){
53
+ return this.visit(this.root);
54
+ };
55
+
56
+ /**
57
+ * Visit Root.
58
+ */
59
+
60
+ Normalizer.prototype.visitRoot = function(block){
61
+ var ret = new nodes.Root
62
+ , node;
63
+
64
+ for (var i = 0, len = block.nodes.length; i < len; ++i) {
65
+ node = block.nodes[i];
66
+ switch (node.nodeName) {
67
+ case 'null':
68
+ case 'expression':
69
+ case 'function':
70
+ case 'jsliteral':
71
+ case 'unit':
72
+ continue;
73
+ default:
74
+ ret.push(this.visit(node));
75
+ }
76
+ }
77
+
78
+ return ret;
79
+ };
80
+
81
+ /**
82
+ * Visit Block.
83
+ */
84
+
85
+ Normalizer.prototype.visitBlock = function(block){
86
+ var ret = new nodes.Block
87
+ , node;
88
+
89
+ if (block.hasProperties) {
90
+ for (var i = 0, len = block.nodes.length; i < len; ++i) {
91
+ this.last = len - 1 == i;
92
+ node = block.nodes[i];
93
+ switch (node.nodeName) {
94
+ case 'null':
95
+ case 'expression':
96
+ case 'function':
97
+ case 'jsliteral':
98
+ case 'group':
99
+ case 'unit':
100
+ continue;
101
+ default:
102
+ ret.push(this.visit(node));
103
+ }
104
+ }
105
+ }
106
+
107
+ // nesting
108
+ for (var i = 0, len = block.nodes.length; i < len; ++i) {
109
+ node = block.nodes[i];
110
+ ret.push(this.visit(node));
111
+ }
112
+
113
+ return block;
114
+ };
115
+
116
+ /**
117
+ * Visit Group.
118
+ */
119
+
120
+ Normalizer.prototype.visitGroup = function(group){
121
+ // TODO: clean this mess up
122
+ var stack = this.stack
123
+ , map = this.map
124
+ , self = this;
125
+
126
+ stack.push(group.nodes);
127
+
128
+ if (group.block.hasProperties) {
129
+ var selectors = this.compileSelectors(stack);
130
+
131
+ // map for extension lookup
132
+ selectors.forEach(function(selector){
133
+ map[selector] = map[selector] || [];
134
+ map[selector].push(group);
135
+ });
136
+
137
+ // extensions
138
+ this.extend(group, selectors);
139
+ }
140
+
141
+ group.block = this.visit(group.block);
142
+ stack.pop();
143
+ return group;
144
+ };
145
+
146
+ /**
147
+ * Apply `group` extensions.
148
+ *
149
+ * @param {Group} group
150
+ * @param {Array} selectors
151
+ * @api private
152
+ */
153
+
154
+ Normalizer.prototype.extend = function(group, selectors){
155
+ var map = this.map
156
+ , self = this;
157
+
158
+ group.extends.forEach(function(extend){
159
+ var groups = map[extend];
160
+ if (!groups) throw new Error('Failed to @extend "' + extend + '"');
161
+ selectors.forEach(function(selector){
162
+ var node = new nodes.Selector;
163
+ node.val = selector;
164
+ groups.forEach(function(group){
165
+ self.extend(group, selectors);
166
+ group.push(node);
167
+ });
168
+ });
169
+ });
170
+ };
171
+
172
+ /**
173
+ * Compile selector strings in `arr` from the bottom-up
174
+ * to produce the selector combinations. For example
175
+ * the following Stylus:
176
+ *
177
+ * ul
178
+ * li
179
+ * p
180
+ * a
181
+ * color: red
182
+ *
183
+ * Would return:
184
+ *
185
+ * [ 'ul li a', 'ul p a' ]
186
+ *
187
+ * @param {Array} arr
188
+ * @return {Array}
189
+ * @api private
190
+ */
191
+
192
+ Normalizer.prototype.compileSelectors = function(arr){
193
+ // TODO: remove this duplication
194
+ var stack = this.stack
195
+ , self = this
196
+ , selectors = []
197
+ , buf = [];
198
+
199
+ function compile(arr, i) {
200
+ if (i) {
201
+ arr[i].forEach(function(selector){
202
+ buf.unshift(selector.val);
203
+ compile(arr, i - 1);
204
+ buf.shift();
205
+ });
206
+ } else {
207
+ arr[0].forEach(function(selector){
208
+ var str = selector.val.trim();
209
+ if (buf.length) {
210
+ for (var i = 0, len = buf.length; i < len; ++i) {
211
+ if (~buf[i].indexOf('&')) {
212
+ str = buf[i].replace(/&/g, str).trim();
213
+ } else {
214
+ str += ' ' + buf[i].trim();
215
+ }
216
+ }
217
+ }
218
+ selectors.push(str.trimRight());
219
+ });
220
+ }
221
+ }
222
+
223
+ compile(arr, arr.length - 1);
224
+
225
+ return selectors;
226
+ };
@@ -173,7 +173,21 @@ function buildPath(level) {
173
173
  function stringifyObjectKey(key) {
174
174
  return /^[a-zA-Z_$][A-Za-z0-9_$]*$/.test(key) ?
175
175
  key :
176
- JSON.stringify(key);
176
+ '"' + escapeDoubleQuotes(key) + '"';
177
+ }
178
+
179
+
180
+ /**
181
+ * @param {string} string
182
+ * @return {string}
183
+ * @see http://stackoverflow.com/questions/7382115/escape-quotes-in-a-string-with-backslash
184
+ */
185
+ function escapeDoubleQuotes(string) {
186
+ return string.replace(/(\\*)(")/g, function(all, backslashes, quote) {
187
+ return backslashes.length % 2 ?
188
+ all :
189
+ backslashes + '\\' + quote;
190
+ });
177
191
  }
178
192
 
179
193
 
@@ -0,0 +1,268 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>CSSOM.js parse method</title>
6
+ <script>
7
+ var exports = {};
8
+ function require(){
9
+ return exports;
10
+ }
11
+ </script>
12
+ <script src="../lib/CSSStyleDeclaration.js"></script>
13
+ <script src="../lib/CSSRule.js"></script>
14
+ <script src="../lib/CSSStyleRule.js"></script>
15
+ <script src="../lib/CSSImportRule.js"></script>
16
+ <script src="../lib/MediaList.js"></script>
17
+ <script src="../lib/CSSMediaRule.js"></script>
18
+ <script src="../lib/StyleSheet.js"></script>
19
+ <script src="../lib/CSSStyleSheet.js"></script>
20
+ <script src="../lib/parse.js"></script>
21
+ <script>
22
+ window.CSSOM = exports;
23
+ </script>
24
+ <style type="text/css">
25
+ html, body {
26
+ background: #333;
27
+ color: #EEE;
28
+ font: 12px sans-serif;
29
+ margin: 0;
30
+ height: 100%;
31
+ }
32
+ body {
33
+ padding-bottom: 1.7em;
34
+ -webkit-box-sizing: border-box;
35
+ -moz-box-sizing: border-box;
36
+ box-sizing: border-box;
37
+ }
38
+ table {
39
+ width: 100%;
40
+ table-layout: fixed;
41
+ margin: 0 auto;
42
+ }
43
+ td {
44
+ vertical-align: top;
45
+ }
46
+ h1 {
47
+ font: normal 1em sans-serif;
48
+ display: inline;
49
+ }
50
+ #labels {
51
+ color: #FFE992;
52
+ width: 66%;
53
+ }
54
+ #labels td {
55
+ width: 50%;
56
+ text-align: center;
57
+ }
58
+ #labels td::before {
59
+ content: '↱ ';
60
+ color: #998e62;
61
+ position: relative;
62
+ top: .4em;
63
+ }
64
+ #labels td::after {
65
+ content: ' ↴';
66
+ color: #998e62;
67
+ position: relative;
68
+ top: .4em;
69
+ }
70
+ #content {
71
+ width: 100%;
72
+ height: 100%;
73
+ }
74
+ #content td {
75
+ width: 33%;
76
+ }
77
+ #content td + td {
78
+ padding-left: 1%;
79
+ }
80
+ #output span {
81
+ color: #666;
82
+ }
83
+ .style-cell textarea {
84
+ width: 99%;
85
+ height: 100%;
86
+ font: 12px monospace;
87
+ white-space: pre-wrap;
88
+ }
89
+ .serialized-cell {
90
+ border-left: 1px solid #363636;
91
+ }
92
+ #message {
93
+ visibility: hidden;
94
+ }
95
+ .error #message {
96
+ visibility: visible;
97
+ position: absolute;
98
+ top: 0;
99
+ left: 34%;
100
+ padding: 1em;
101
+ background: black;
102
+ color: #e34343;
103
+ font-size: 24px;
104
+ }
105
+ </style>
106
+ </head>
107
+ <body>
108
+ <table id="labels">
109
+ <tr><td><h1>CSSOM.parse</h1></td><td>.toString</td></tr>
110
+ </table>
111
+ <table id="content">
112
+ <tr>
113
+ <td class="style-cell">
114
+ <textarea id="style" spellcheck="false" rows="40">img {
115
+ border: none
116
+ }</textarea></td>
117
+ <td class="output-cell"><pre id="output"></pre></td>
118
+ <td class="serialized-cell"><pre id="serialized"></pre></td>
119
+ </tr>
120
+ </table>
121
+ <div id="message"></div>
122
+ <script defer>
123
+ /**
124
+ * @param {number} depth
125
+ * @return {string}
126
+ */
127
+ function makeIndent(depth) {
128
+ var INDENT = ' ';
129
+ if (depth == 1) {
130
+ return INDENT;
131
+ } else if (depth < 1) {
132
+ return '';
133
+ }
134
+
135
+ if (depth in makeIndent.cache) {
136
+ return makeIndent.cache[depth];
137
+ } else {
138
+ var result = INDENT;
139
+ for (var i = depth; --i;) {
140
+ result += INDENT;
141
+ }
142
+ makeIndent.cache[depth] = result;
143
+ return result;
144
+ }
145
+ }
146
+ makeIndent.cache = {};
147
+
148
+
149
+ /**
150
+ * buildPath(2) -> '../..'
151
+ * @param {number} level
152
+ * @return {string}
153
+ */
154
+ function buildPath(level) {
155
+ if (level == 0) {
156
+ return '.';
157
+ } else {
158
+ var result = '..';
159
+ for (var i = 1; i < level; i++) {
160
+ result += '/..';
161
+ }
162
+ return result;
163
+ }
164
+ }
165
+
166
+
167
+ /**
168
+ * stringifyObjectKey('color') -> 'color'
169
+ * stringifyObjectKey('background-color') -> '"background-color"'
170
+ * @param {string} key
171
+ * @return {string}
172
+ */
173
+ function stringifyObjectKey(key) {
174
+ return /^[a-zA-Z_$][A-Za-z0-9_$]*$/.test(key) ?
175
+ key :
176
+ JSON.stringify(key);
177
+ }
178
+
179
+
180
+ /**
181
+ * @param {Object} object
182
+ * @param {number} [depth]
183
+ * @param {Array} [stack]
184
+ * @return {string}
185
+ */
186
+ function inspect(object, depth, stack) {
187
+ depth ? depth++ : (depth = 1);
188
+ stack = stack || (stack = []);
189
+
190
+ switch (typeof object) {
191
+ case 'object':
192
+ var level = stack.indexOf(object);
193
+ if (level != -1) {
194
+ return buildPath(level);
195
+ }
196
+ stack = [object].concat(stack);
197
+
198
+ var properties = [];
199
+ var indent = makeIndent(depth);
200
+ for (var key in object) {
201
+ if (object.hasOwnProperty(key)) {
202
+ properties.push(indent + stringifyObjectKey(key) + '<span>: </span>' + inspect(object[key], depth, stack));
203
+ }
204
+ }
205
+ var indentInside = makeIndent(depth - 1);
206
+ return '<span>{</span>\n' + properties.join('<span>,</span>\n') + '\n' + indentInside + '<span>}</span>';
207
+
208
+ case 'string':
209
+ return '"' + object + '"';
210
+
211
+ default:
212
+ return object.toString();
213
+ }
214
+ }
215
+
216
+
217
+
218
+ var errors = [];
219
+ if (!("__defineGetter__" in {})) {
220
+ errors.push("Object.prototype.__defineGetter__ isn’t supported");
221
+ }
222
+ if (errors.length) {
223
+ document.getElementById("message").innerHTML = errors.join("<br>");
224
+ document.body.className = "error";
225
+ throw errors.join("\n\n");
226
+ }
227
+
228
+ var style = document.getElementById("style");
229
+ var output = document.getElementById("output");
230
+ var serialized = document.getElementById("serialized");
231
+
232
+ function outputUpdated(){
233
+ var value = style.value;
234
+ if (value != style.prevValue) {
235
+ var css = CSSOM.parse(value);
236
+ output.innerHTML = inspect(css);
237
+ serialized.innerHTML = css.toString();
238
+ style.prevValue = value;
239
+ }
240
+ }
241
+
242
+ function hashChanged(){
243
+ var hash = location.hash;
244
+ var splitted = hash.split("=");
245
+ if (splitted.length < 2) {
246
+ return;
247
+ }
248
+ var name = splitted[0];
249
+ var value = splitted[1];
250
+ if (name == "#css") {
251
+ style.value = decodeURIComponent(value);
252
+ outputUpdated();
253
+ }
254
+ }
255
+
256
+ hashChanged();
257
+ outputUpdated();
258
+
259
+ window.onhashchange = hashChanged;
260
+ style.onkeyup = style.onpaste = function changed(){
261
+ outputUpdated();
262
+ };
263
+ style.onchange = function updateLocation(){
264
+ location.hash = "css=" + encodeURIComponent(style.value);
265
+ };
266
+ </script>
267
+ </body>
268
+ </html>
@@ -23,7 +23,7 @@ CSSOM.CSSStyleDeclaration.prototype = {
23
23
  *
24
24
  * @param {string} name
25
25
  * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-getPropertyValue
26
- * @return {string} the value of the property if it has been explicitly set for this declaration block.
26
+ * @return {string} the value of the property if it has been explicitly set for this declaration block.
27
27
  * Returns the empty string if the property has not been set.
28
28
  */
29
29
  getPropertyValue: function(name) {
@@ -120,11 +120,27 @@ CSSOM.CSSStyleDeclaration.prototype = {
120
120
  properties[i] = name + ": " + value + priority + ";";
121
121
  }
122
122
  return properties.join(" ")
123
- }
123
+ },
124
124
 
125
+ set cssText(cssText){
126
+ var i, name;
127
+ for (i = this.length; i--;) {
128
+ name = this[i];
129
+ this[name] = "";
130
+ }
131
+ Array.prototype.splice.call(this, 0, this.length);
132
+
133
+ var dummyRule = CSSOM.parse('#bogus{' + cssText + '}').cssRules[0].style;
134
+ var length = dummyRule.length;
135
+ for (i = 0; i < length; ++i) {
136
+ name = dummyRule[i];
137
+ this.setProperty(dummyRule[i], dummyRule.getPropertyValue(name), dummyRule.getPropertyPriority(name));
138
+ }
139
+ }
125
140
  };
126
141
 
127
142
 
128
143
  //.CommonJS
129
144
  exports.CSSStyleDeclaration = CSSOM.CSSStyleDeclaration;
145
+ CSSOM.parse = require('./parse').parse; // Cannot be included sooner due to the mutual dependency between parse.js and CSSStyleDeclaration.js
130
146
  ///CommonJS
@@ -211,15 +211,6 @@ CSSOM.parse = function parse(token, options) {
211
211
  case ";":
212
212
  switch (state) {
213
213
  case "value":
214
- // Hack for AssetGraph: Start a new CSSStyleRule if a property gets redefined.
215
- // Temporary workaround until https://github.com/NV/CSSOM/issues/16 gets resolved
216
- if (styleRule.style.getPropertyValue(name)) {
217
- styleRule.__ends = i;
218
- currentScope.cssRules.push(styleRule);
219
- styleRule = new CSSOM.CSSStyleRule;
220
- styleRule.selectorText = currentScope.cssRules[currentScope.cssRules.length - 1].selectorText;
221
- styleRule.__starts = i;
222
- }
223
214
  styleRule.style.setProperty(name, buffer.trim(), priority);
224
215
  priority = "";
225
216
  buffer = "";
@@ -246,15 +237,6 @@ CSSOM.parse = function parse(token, options) {
246
237
  case "}":
247
238
  switch (state) {
248
239
  case "value":
249
- // Hack for AssetGraph: Start a new CSSStyleRule if a property gets redefined.
250
- // Temporary workaround until https://github.com/NV/CSSOM/issues/16 gets resolved
251
- if (styleRule.style.getPropertyValue(name)) {
252
- styleRule.__ends = i;
253
- currentScope.cssRules.push(styleRule);
254
- styleRule = new CSSOM.CSSStyleRule;
255
- styleRule.selectorText = currentScope.cssRules[currentScope.cssRules.length - 1].selectorText;
256
- styleRule.__starts = i;
257
- }
258
240
  styleRule.style.setProperty(name, buffer.trim(), priority);
259
241
  priority = "";
260
242
  case "before-name":
@@ -2,7 +2,7 @@
2
2
  "name": "cssom",
3
3
  "description": "CSS Object Model implementation and CSS parser",
4
4
  "keywords": ["CSS", "CSSOM", "parser", "styleSheet"],
5
- "version": "0.2.0",
5
+ "version": "0.2.1",
6
6
  "homepage": "https://github.com/NV/CSSOM",
7
7
  "author": "Nikita Vasilyev <me@elv1s.ru>",
8
8
  "repository": {
@@ -22,14 +22,21 @@ test("CSSStyleDeclaration", function(){
22
22
  equal(d.getPropertyValue("color"), "purple");
23
23
  equal(d.getPropertyValue("width"), "128px");
24
24
  equal(d.getPropertyValue("position"), "");
25
-
25
+
26
26
  strictEqual(d.getPropertyPriority("color"), "");
27
27
  strictEqual(d.getPropertyPriority("width"), "important");
28
28
  strictEqual(d.getPropertyPriority("position"), "");
29
-
29
+
30
30
  d.setProperty("color", "green");
31
31
  d.removeProperty("width");
32
-
32
+
33
33
  equal(d.cssText, "color: green;");
34
34
 
35
35
  });
36
+
37
+ test("CSSStyleDeclaration#cssText", function(){
38
+ var d = new CSSOM.CSSStyleDeclaration;
39
+ var cssText = "color: pink; outline: 2px solid red;";
40
+ d.cssText = cssText;
41
+ strictEqual(d.cssText, cssText);
42
+ });
data/vendor/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  { "name": "stylus"
2
2
  , "description": "Robust, expressive, and feature-rich CSS superset"
3
- , "version": "0.21.2"
3
+ , "version": "0.22.0"
4
4
  , "author": "TJ Holowaychuk <tj@vision-media.ca>"
5
5
  , "keywords": ["css", "parser", "style", "stylesheets", "jade", "language"]
6
6
  , "repository": "git://github.com/learnboost/stylus"
@@ -9,7 +9,7 @@
9
9
  , "bin": { "stylus": "./bin/stylus" }
10
10
  , "scripts" : { "prepublish" : "npm prune" }
11
11
  , "dependencies": {
12
- "cssom": "0.2.0"
12
+ "cssom": "0.2.1"
13
13
  , "growl": "1.1.0"
14
14
  , "mkdirp": "0.0.7"
15
15
  }
@@ -0,0 +1,4 @@
1
+ body {
2
+ foo: one 1 two 2 three 3;
3
+ foo: one two three;
4
+ }
@@ -0,0 +1,6 @@
1
+
2
+ list = (one 1) (two 2) (three 3)
3
+
4
+ body
5
+ foo: list
6
+ foo: keys(list)
@@ -0,0 +1,5 @@
1
+
2
+ body {
3
+ foo: one 1 two 2 three 3;
4
+ foo: 1 2 3;
5
+ }
@@ -0,0 +1,6 @@
1
+
2
+ list = (one 1) (two 2) (three 3)
3
+
4
+ body
5
+ foo: list
6
+ foo: values(list)
@@ -0,0 +1,13 @@
1
+ .message,
2
+ .warning,
3
+ .error {
4
+ margin: 5px;
5
+ padding: 20px;
6
+ font-weight: bold;
7
+ }
8
+ .warning {
9
+ color: #ff0;
10
+ }
11
+ .error {
12
+ color: #f00;
13
+ }