stylus-source 0.15.4
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.
- data/.DS_Store +0 -0
- data/README.md +3 -0
- data/lib/.DS_Store +0 -0
- data/lib/node_modules/cssom/.idea/CSSOM.iml +9 -0
- data/lib/node_modules/cssom/.idea/dictionaries/nv.xml +3 -0
- data/lib/node_modules/cssom/.idea/encodings.xml +5 -0
- data/lib/node_modules/cssom/.idea/misc.xml +17 -0
- data/lib/node_modules/cssom/.idea/modules.xml +9 -0
- data/lib/node_modules/cssom/.idea/projectCodeStyle.xml +82 -0
- data/lib/node_modules/cssom/.idea/vcs.xml +8 -0
- data/lib/node_modules/cssom/.idea/workspace.xml +467 -0
- data/lib/node_modules/cssom/.livereload +19 -0
- data/lib/node_modules/cssom/Jakefile +37 -0
- data/lib/node_modules/cssom/README.mdown +33 -0
- data/lib/node_modules/cssom/Rakefile +23 -0
- data/lib/node_modules/cssom/docs/.livereload +19 -0
- data/lib/node_modules/cssom/docs/bar.css +3 -0
- data/lib/node_modules/cssom/docs/demo.css +0 -0
- data/lib/node_modules/cssom/docs/foo.css +4 -0
- data/lib/node_modules/cssom/docs/parse.html +170 -0
- data/lib/node_modules/cssom/docs/parse2.html +431 -0
- data/lib/node_modules/cssom/index.html +100 -0
- data/lib/node_modules/cssom/lib/CSSImportRule.js +34 -0
- data/lib/node_modules/cssom/lib/CSSMediaRule.js +38 -0
- data/lib/node_modules/cssom/lib/CSSOM.js +3 -0
- data/lib/node_modules/cssom/lib/CSSRule.js +38 -0
- data/lib/node_modules/cssom/lib/CSSStyleDeclaration.js +130 -0
- data/lib/node_modules/cssom/lib/CSSStyleRule.js +187 -0
- data/lib/node_modules/cssom/lib/CSSStyleSheet.js +85 -0
- data/lib/node_modules/cssom/lib/MediaList.js +61 -0
- data/lib/node_modules/cssom/lib/StyleSheet.js +15 -0
- data/lib/node_modules/cssom/lib/clone.js +69 -0
- data/lib/node_modules/cssom/lib/index.js +10 -0
- data/lib/node_modules/cssom/lib/parse.js +195 -0
- data/lib/node_modules/cssom/media.html +17 -0
- data/lib/node_modules/cssom/package.json +30 -0
- data/lib/node_modules/cssom/plugins/toHTML.js +32 -0
- data/lib/node_modules/cssom/server/index.html +22 -0
- data/lib/node_modules/cssom/server/index.js +21 -0
- data/lib/node_modules/cssom/shorthands.html +21 -0
- data/lib/node_modules/cssom/test/CSSStyleDeclaration.test.js +35 -0
- data/lib/node_modules/cssom/test/CSSStyleRule.test.js +12 -0
- data/lib/node_modules/cssom/test/CSSStyleSheet.test.js +16 -0
- data/lib/node_modules/cssom/test/MediaList.test.js +21 -0
- data/lib/node_modules/cssom/test/clone.test.js +38 -0
- data/lib/node_modules/cssom/test/fixtures/dummy.css +3 -0
- data/lib/node_modules/cssom/test/helper.js +97 -0
- data/lib/node_modules/cssom/test/index.html +42 -0
- data/lib/node_modules/cssom/test/parse.test.js +346 -0
- data/lib/node_modules/cssom/test/vendor/qunit.css +189 -0
- data/lib/node_modules/cssom/test/vendor/qunit.js +1341 -0
- data/lib/node_modules/growl/History.md +16 -0
- data/lib/node_modules/growl/Readme.md +74 -0
- data/lib/node_modules/growl/lib/growl.js +82 -0
- data/lib/node_modules/growl/package.json +6 -0
- data/lib/node_modules/growl/test.js +17 -0
- data/lib/stylus/colors.js +156 -0
- data/lib/stylus/convert/css.js +130 -0
- data/lib/stylus/errors.js +58 -0
- data/lib/stylus/functions/image.js +120 -0
- data/lib/stylus/functions/index.js +722 -0
- data/lib/stylus/functions/index.styl +123 -0
- data/lib/stylus/functions/url.js +98 -0
- data/lib/stylus/lexer.js +728 -0
- data/lib/stylus/middleware.js +223 -0
- data/lib/stylus/nodes/arguments.js +65 -0
- data/lib/stylus/nodes/binop.js +54 -0
- data/lib/stylus/nodes/block.js +99 -0
- data/lib/stylus/nodes/boolean.js +103 -0
- data/lib/stylus/nodes/call.js +57 -0
- data/lib/stylus/nodes/charset.js +42 -0
- data/lib/stylus/nodes/comment.js +32 -0
- data/lib/stylus/nodes/each.js +56 -0
- data/lib/stylus/nodes/expression.js +168 -0
- data/lib/stylus/nodes/fontface.js +55 -0
- data/lib/stylus/nodes/function.js +104 -0
- data/lib/stylus/nodes/group.js +79 -0
- data/lib/stylus/nodes/hsla.js +256 -0
- data/lib/stylus/nodes/ident.js +127 -0
- data/lib/stylus/nodes/if.js +55 -0
- data/lib/stylus/nodes/import.js +30 -0
- data/lib/stylus/nodes/index.js +52 -0
- data/lib/stylus/nodes/jsliteral.js +32 -0
- data/lib/stylus/nodes/keyframes.js +78 -0
- data/lib/stylus/nodes/literal.js +92 -0
- data/lib/stylus/nodes/media.js +42 -0
- data/lib/stylus/nodes/node.js +209 -0
- data/lib/stylus/nodes/null.js +72 -0
- data/lib/stylus/nodes/page.js +43 -0
- data/lib/stylus/nodes/params.js +72 -0
- data/lib/stylus/nodes/property.js +72 -0
- data/lib/stylus/nodes/return.js +44 -0
- data/lib/stylus/nodes/rgba.js +335 -0
- data/lib/stylus/nodes/root.js +50 -0
- data/lib/stylus/nodes/selector.js +57 -0
- data/lib/stylus/nodes/string.js +120 -0
- data/lib/stylus/nodes/ternary.js +51 -0
- data/lib/stylus/nodes/unaryop.js +46 -0
- data/lib/stylus/nodes/unit.js +207 -0
- data/lib/stylus/parser.js +1514 -0
- data/lib/stylus/renderer.js +157 -0
- data/lib/stylus/source.rb +7 -0
- data/lib/stylus/stack/frame.js +66 -0
- data/lib/stylus/stack/index.js +146 -0
- data/lib/stylus/stack/scope.js +53 -0
- data/lib/stylus/stylus.js +102 -0
- data/lib/stylus/token.js +53 -0
- data/lib/stylus/utils.js +237 -0
- data/lib/stylus/visitor/compiler.js +472 -0
- data/lib/stylus/visitor/evaluator.js +1070 -0
- data/lib/stylus/visitor/index.js +31 -0
- data/stylus-source.gemspec +15 -0
- metadata +158 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
|
|
2
|
+
vendors = moz webkit official
|
|
3
|
+
|
|
4
|
+
// stringify the given arg
|
|
5
|
+
|
|
6
|
+
-string(arg)
|
|
7
|
+
type(arg) + ' ' + arg
|
|
8
|
+
|
|
9
|
+
// require a color
|
|
10
|
+
|
|
11
|
+
require-color(color)
|
|
12
|
+
unless color is a 'color'
|
|
13
|
+
error('RGB or HSL value expected, got a ' + -string(color))
|
|
14
|
+
|
|
15
|
+
// require a unit
|
|
16
|
+
|
|
17
|
+
require-unit(n)
|
|
18
|
+
unless n is a 'unit'
|
|
19
|
+
error('unit expected, got a ' + -string(n))
|
|
20
|
+
|
|
21
|
+
// require a string
|
|
22
|
+
|
|
23
|
+
require-string(str)
|
|
24
|
+
unless str is a 'string' or str is a 'ident'
|
|
25
|
+
error('string expected, got a ' + -string(str))
|
|
26
|
+
|
|
27
|
+
// apply js Math function
|
|
28
|
+
|
|
29
|
+
math(n, fn)
|
|
30
|
+
require-unit(n)
|
|
31
|
+
require-string(fn)
|
|
32
|
+
-math(n, fn)
|
|
33
|
+
|
|
34
|
+
// adjust the given color's property by amount
|
|
35
|
+
|
|
36
|
+
adjust(color, prop, amount)
|
|
37
|
+
require-color(color)
|
|
38
|
+
require-string(prop)
|
|
39
|
+
require-unit(amount)
|
|
40
|
+
-adjust(color, prop, amount)
|
|
41
|
+
|
|
42
|
+
// Math functions
|
|
43
|
+
|
|
44
|
+
abs(n) { math(n, 'abs') }
|
|
45
|
+
ceil(n) { math(n, 'ceil') }
|
|
46
|
+
floor(n) { math(n, 'floor') }
|
|
47
|
+
round(n) { math(n, 'round') }
|
|
48
|
+
sin(n) { math(n, 'sin') }
|
|
49
|
+
cos(n) { math(n, 'cos') }
|
|
50
|
+
min(a, b) { a < b ? a : b }
|
|
51
|
+
max(a, b) { a > b ? a : b }
|
|
52
|
+
PI = -math-prop('PI')
|
|
53
|
+
|
|
54
|
+
// return the sum of the given numbers
|
|
55
|
+
|
|
56
|
+
sum(nums)
|
|
57
|
+
sum = 0
|
|
58
|
+
sum += n for n in nums
|
|
59
|
+
|
|
60
|
+
// return the average of the given numbers
|
|
61
|
+
|
|
62
|
+
avg(nums)
|
|
63
|
+
sum(nums) / length(nums)
|
|
64
|
+
|
|
65
|
+
// color components
|
|
66
|
+
|
|
67
|
+
alpha(color) { component(hsl(color), 'alpha') }
|
|
68
|
+
hue(color) { component(hsl(color), 'hue') }
|
|
69
|
+
saturation(color) { component(hsl(color), 'saturation') }
|
|
70
|
+
lightness(color) { component(hsl(color), 'lightness') }
|
|
71
|
+
|
|
72
|
+
// check if n is an odd number
|
|
73
|
+
|
|
74
|
+
odd(n)
|
|
75
|
+
1 == n % 2
|
|
76
|
+
|
|
77
|
+
// check if n is an even number
|
|
78
|
+
|
|
79
|
+
even(n)
|
|
80
|
+
0 == n % 2
|
|
81
|
+
|
|
82
|
+
// check if color is light
|
|
83
|
+
|
|
84
|
+
light(color)
|
|
85
|
+
lightness(color) >= 50%
|
|
86
|
+
|
|
87
|
+
// check if color is dark
|
|
88
|
+
|
|
89
|
+
dark(color)
|
|
90
|
+
lightness(color) < 50%
|
|
91
|
+
|
|
92
|
+
// desaturate color by amount
|
|
93
|
+
|
|
94
|
+
desaturate(color, amount)
|
|
95
|
+
adjust(color, 'saturation', - amount)
|
|
96
|
+
|
|
97
|
+
// saturate color by amount
|
|
98
|
+
|
|
99
|
+
saturate(color, amount)
|
|
100
|
+
adjust(color, 'saturation', amount)
|
|
101
|
+
|
|
102
|
+
// darken by the given amount
|
|
103
|
+
|
|
104
|
+
darken(color, amount)
|
|
105
|
+
adjust(color, 'lightness', - amount)
|
|
106
|
+
|
|
107
|
+
// lighten by the given amount
|
|
108
|
+
|
|
109
|
+
lighten(color, amount)
|
|
110
|
+
adjust(color, 'lightness', amount)
|
|
111
|
+
|
|
112
|
+
// return the last value in the given expr
|
|
113
|
+
|
|
114
|
+
last(expr)
|
|
115
|
+
expr[length(expr) - 1]
|
|
116
|
+
|
|
117
|
+
// join values with the given delimiter
|
|
118
|
+
|
|
119
|
+
join(delim, vals...)
|
|
120
|
+
buf = ''
|
|
121
|
+
vals = vals[0] if length(vals) == 1
|
|
122
|
+
for val, i in vals
|
|
123
|
+
buf += i ? delim + val : val
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
|
|
2
|
+
/*!
|
|
3
|
+
* Stylus - plugin - url
|
|
4
|
+
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
|
|
5
|
+
* MIT Licensed
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Module dependencies.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
var Compiler = require('../visitor/compiler')
|
|
13
|
+
, nodes = require('../nodes')
|
|
14
|
+
, parse = require('url').parse
|
|
15
|
+
, extname = require('path').extname
|
|
16
|
+
, utils = require('../utils')
|
|
17
|
+
, fs = require('fs');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Mime table.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
var mimes = {
|
|
24
|
+
'.gif': 'image/gif'
|
|
25
|
+
, '.png': 'image/png'
|
|
26
|
+
, '.jpg': 'image/jpeg'
|
|
27
|
+
, '.jpeg': 'image/jpeg'
|
|
28
|
+
, '.svg': 'image/svg+xml'
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Return a url() function with the given `options`.
|
|
33
|
+
*
|
|
34
|
+
* Options:
|
|
35
|
+
*
|
|
36
|
+
* - `limit` bytesize limit defaulting to 30Kb
|
|
37
|
+
* - `paths` image resolution path(s), merged with general lookup paths
|
|
38
|
+
*
|
|
39
|
+
* Examples:
|
|
40
|
+
*
|
|
41
|
+
* stylus(str)
|
|
42
|
+
* .set('filename', __dirname + '/css/test.styl')
|
|
43
|
+
* .define('url', stylus.url({ paths: [__dirname + '/public'] }))
|
|
44
|
+
* .render(function(err, css){ ... })
|
|
45
|
+
*
|
|
46
|
+
* @param {Object} options
|
|
47
|
+
* @return {Function}
|
|
48
|
+
* @api public
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
module.exports = function(options) {
|
|
52
|
+
options = options || {};
|
|
53
|
+
|
|
54
|
+
var sizeLimit = options.limit || 30000
|
|
55
|
+
, _paths = options.paths || [];
|
|
56
|
+
|
|
57
|
+
function url(url){
|
|
58
|
+
// Compile the url
|
|
59
|
+
var compiler = new Compiler(url);
|
|
60
|
+
compiler.isURL = true;
|
|
61
|
+
var url = url.nodes.map(function(node){
|
|
62
|
+
return compiler.visit(node);
|
|
63
|
+
}).join('');
|
|
64
|
+
|
|
65
|
+
// Parse literal
|
|
66
|
+
var url = parse(url)
|
|
67
|
+
, ext = extname(url.pathname)
|
|
68
|
+
, mime = mimes[ext]
|
|
69
|
+
, literal = new nodes.Literal('url("' + url.href + '")')
|
|
70
|
+
, paths = _paths.concat(this.paths)
|
|
71
|
+
, founds
|
|
72
|
+
, buf;
|
|
73
|
+
|
|
74
|
+
// Not supported
|
|
75
|
+
if (!mime) return literal;
|
|
76
|
+
|
|
77
|
+
// Absolute
|
|
78
|
+
if (url.protocol) return literal;
|
|
79
|
+
|
|
80
|
+
// Lookup
|
|
81
|
+
found = utils.lookup(url.pathname, paths);
|
|
82
|
+
|
|
83
|
+
// Failed to lookup
|
|
84
|
+
if (!found) return literal;
|
|
85
|
+
|
|
86
|
+
// Read data
|
|
87
|
+
buf = fs.readFileSync(found);
|
|
88
|
+
|
|
89
|
+
// To large
|
|
90
|
+
if (buf.length > sizeLimit) return literal;
|
|
91
|
+
|
|
92
|
+
// Encode
|
|
93
|
+
return new nodes.Literal('url("data:' + mime + ';base64,' + buf.toString('base64') + '")');
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
url.raw = true;
|
|
97
|
+
return url;
|
|
98
|
+
};
|
data/lib/stylus/lexer.js
ADDED
|
@@ -0,0 +1,728 @@
|
|
|
1
|
+
|
|
2
|
+
/*!
|
|
3
|
+
* Stylus - Lexer
|
|
4
|
+
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
|
|
5
|
+
* MIT Licensed
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Module dependencies.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
var Token = require('./token')
|
|
13
|
+
, nodes = require('./nodes')
|
|
14
|
+
, errors = require('./errors');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Operator aliases.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
var alias = {
|
|
21
|
+
'and': '&&'
|
|
22
|
+
, 'or': '||'
|
|
23
|
+
, 'is': '=='
|
|
24
|
+
, 'isnt': '!='
|
|
25
|
+
, 'is not': '!='
|
|
26
|
+
, ':=': '?='
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Units.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
var units = [
|
|
34
|
+
'em'
|
|
35
|
+
, 'ex'
|
|
36
|
+
, 'px'
|
|
37
|
+
, 'mm'
|
|
38
|
+
, 'cm'
|
|
39
|
+
, 'in'
|
|
40
|
+
, 'pt'
|
|
41
|
+
, 'pc'
|
|
42
|
+
, 'deg'
|
|
43
|
+
, 'rad'
|
|
44
|
+
, 'grad'
|
|
45
|
+
, 'ms'
|
|
46
|
+
, 's'
|
|
47
|
+
, 'Hz'
|
|
48
|
+
, 'kHz'
|
|
49
|
+
, 'rem'
|
|
50
|
+
, '%'].join('|');
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Unit RegExp.
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
var unit = new RegExp('^(-)?(\\d+\\.\\d+|\\d+|\\.\\d+)(' + units + ')? *');
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Initialize a new `Lexer` with the given `str` and `options`.
|
|
60
|
+
*
|
|
61
|
+
* @param {String} str
|
|
62
|
+
* @param {Object} options
|
|
63
|
+
* @api private
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
var Lexer = module.exports = function Lexer(str, options) {
|
|
67
|
+
options = options || {};
|
|
68
|
+
this.str = str.replace(/\r\n?/g, '\n');
|
|
69
|
+
this.stash = [];
|
|
70
|
+
this.indentStack = [];
|
|
71
|
+
this.indentRe = null;
|
|
72
|
+
this.lineno = 1;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Lexer prototype.
|
|
77
|
+
*/
|
|
78
|
+
|
|
79
|
+
Lexer.prototype = {
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Custom inspect.
|
|
83
|
+
*/
|
|
84
|
+
|
|
85
|
+
inspect: function(){
|
|
86
|
+
var tok
|
|
87
|
+
, tmp = this.str
|
|
88
|
+
, buf = [];
|
|
89
|
+
while ('eos' != (tok = this.next()).type) {
|
|
90
|
+
buf.push(tok.inspect());
|
|
91
|
+
}
|
|
92
|
+
this.str = tmp;
|
|
93
|
+
this.prevIndents = 0;
|
|
94
|
+
return buf.concat(tok.inspect()).join('\n');
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Lookahead `n` tokens.
|
|
99
|
+
*
|
|
100
|
+
* @param {Number} n
|
|
101
|
+
* @return {Object}
|
|
102
|
+
* @api private
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
lookahead: function(n){
|
|
106
|
+
var fetch = n - this.stash.length;
|
|
107
|
+
while (fetch-- > 0) this.stash.push(this.advance());
|
|
108
|
+
return this.stash[--n];
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Consume the given `len`.
|
|
113
|
+
*
|
|
114
|
+
* @param {Number|Array} len
|
|
115
|
+
* @api private
|
|
116
|
+
*/
|
|
117
|
+
|
|
118
|
+
skip: function(len){
|
|
119
|
+
this.str = this.str.substr(Array.isArray(len)
|
|
120
|
+
? len[0].length
|
|
121
|
+
: len);
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Fetch next token including those stashed by peek.
|
|
126
|
+
*
|
|
127
|
+
* @return {Token}
|
|
128
|
+
* @api private
|
|
129
|
+
*/
|
|
130
|
+
|
|
131
|
+
next: function() {
|
|
132
|
+
var tok = this.stashed() || this.advance();
|
|
133
|
+
switch (tok.type) {
|
|
134
|
+
case 'newline':
|
|
135
|
+
case 'indent':
|
|
136
|
+
++this.lineno;
|
|
137
|
+
break;
|
|
138
|
+
case 'outdent':
|
|
139
|
+
if ('outdent' != this.prev.type) ++this.lineno;
|
|
140
|
+
}
|
|
141
|
+
this.prev = tok;
|
|
142
|
+
tok.lineno = this.lineno;
|
|
143
|
+
return tok;
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Fetch next token.
|
|
148
|
+
*
|
|
149
|
+
* @return {Token}
|
|
150
|
+
* @api private
|
|
151
|
+
*/
|
|
152
|
+
|
|
153
|
+
advance: function() {
|
|
154
|
+
return this.eos()
|
|
155
|
+
|| this.null()
|
|
156
|
+
|| this.sep()
|
|
157
|
+
|| this.keyword()
|
|
158
|
+
|| this.urlchars()
|
|
159
|
+
|| this.atrule()
|
|
160
|
+
|| this.media()
|
|
161
|
+
|| this.comment()
|
|
162
|
+
|| this.newline()
|
|
163
|
+
|| this.escaped()
|
|
164
|
+
|| this.important()
|
|
165
|
+
|| this.literal()
|
|
166
|
+
|| this.function()
|
|
167
|
+
|| this.brace()
|
|
168
|
+
|| this.paren()
|
|
169
|
+
|| this.color()
|
|
170
|
+
|| this.string()
|
|
171
|
+
|| this.unit()
|
|
172
|
+
|| this.namedop()
|
|
173
|
+
|| this.boolean()
|
|
174
|
+
|| this.ident()
|
|
175
|
+
|| this.op()
|
|
176
|
+
|| this.space()
|
|
177
|
+
|| this.selector();
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Lookahead a single token.
|
|
182
|
+
*
|
|
183
|
+
* @return {Token}
|
|
184
|
+
* @api private
|
|
185
|
+
*/
|
|
186
|
+
|
|
187
|
+
peek: function() {
|
|
188
|
+
return this.lookahead(1);
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Return the next possibly stashed token.
|
|
193
|
+
*
|
|
194
|
+
* @return {Token}
|
|
195
|
+
* @api private
|
|
196
|
+
*/
|
|
197
|
+
|
|
198
|
+
stashed: function() {
|
|
199
|
+
return this.stash.shift();
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* EOS | trailing outdents.
|
|
204
|
+
*/
|
|
205
|
+
|
|
206
|
+
eos: function() {
|
|
207
|
+
if (this.str.length) return;
|
|
208
|
+
if (this.indentStack.length) {
|
|
209
|
+
this.indentStack.shift();
|
|
210
|
+
return new Token('outdent');
|
|
211
|
+
} else {
|
|
212
|
+
return new Token('eos');
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* url char
|
|
218
|
+
*/
|
|
219
|
+
|
|
220
|
+
urlchars: function() {
|
|
221
|
+
var captures;
|
|
222
|
+
if (!this.isURL) return;
|
|
223
|
+
if (captures = /^[\/:@.;?&=*!,<>#%0-9]+/.exec(this.str)) {
|
|
224
|
+
this.skip(captures);
|
|
225
|
+
return new Token('literal', new nodes.Literal(captures[0]));
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* ';' ' '*
|
|
231
|
+
*/
|
|
232
|
+
|
|
233
|
+
sep: function() {
|
|
234
|
+
var captures;
|
|
235
|
+
if (captures = /^; */.exec(this.str)) {
|
|
236
|
+
this.skip(captures);
|
|
237
|
+
return new Token(';');
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* ' '+
|
|
243
|
+
*/
|
|
244
|
+
|
|
245
|
+
space: function() {
|
|
246
|
+
var captures;
|
|
247
|
+
if (captures = /^( +)/.exec(this.str)) {
|
|
248
|
+
this.skip(captures);
|
|
249
|
+
return new Token('space');
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* '\\' . ' '*
|
|
255
|
+
*/
|
|
256
|
+
|
|
257
|
+
escaped: function() {
|
|
258
|
+
var captures;
|
|
259
|
+
if (captures = /^\\(.) */.exec(this.str)) {
|
|
260
|
+
var c = captures[1];
|
|
261
|
+
this.skip(captures);
|
|
262
|
+
return new Token('ident', new nodes.Literal(c));
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* '@css' ' '* '{' .* '}' ' '*
|
|
268
|
+
*/
|
|
269
|
+
|
|
270
|
+
literal: function() {
|
|
271
|
+
// HACK attack !!!
|
|
272
|
+
var captures;
|
|
273
|
+
if (captures = /^@css *\{/.exec(this.str)) {
|
|
274
|
+
this.skip(captures);
|
|
275
|
+
var c
|
|
276
|
+
, braces = 1
|
|
277
|
+
, css = '';
|
|
278
|
+
while (c = this.str[0]) {
|
|
279
|
+
this.str = this.str.substr(1);
|
|
280
|
+
switch (c) {
|
|
281
|
+
case '{': ++braces; break;
|
|
282
|
+
case '}': --braces; break;
|
|
283
|
+
}
|
|
284
|
+
css += c;
|
|
285
|
+
if (!braces) break;
|
|
286
|
+
}
|
|
287
|
+
css = css.replace(/\s*}$/, '');
|
|
288
|
+
return new Token('literal', new nodes.Literal(css));
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* '!important' ' '*
|
|
294
|
+
*/
|
|
295
|
+
|
|
296
|
+
important: function() {
|
|
297
|
+
var captures;
|
|
298
|
+
if (captures = /^!important */.exec(this.str)) {
|
|
299
|
+
this.skip(captures);
|
|
300
|
+
return new Token('ident', new nodes.Literal('!important'));
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* '{' | '}'
|
|
306
|
+
*/
|
|
307
|
+
|
|
308
|
+
brace: function() {
|
|
309
|
+
var captures;
|
|
310
|
+
if (captures = /^([{}])/.exec(this.str)) {
|
|
311
|
+
this.skip(1);
|
|
312
|
+
var brace = captures[1];
|
|
313
|
+
return new Token(brace, brace);
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* '(' | ')' ' '*
|
|
319
|
+
*/
|
|
320
|
+
|
|
321
|
+
paren: function() {
|
|
322
|
+
var captures;
|
|
323
|
+
if (captures = /^([()]) */.exec(this.str)) {
|
|
324
|
+
var paren = captures[1];
|
|
325
|
+
this.skip(captures);
|
|
326
|
+
if (')' == paren) this.isURL = false;
|
|
327
|
+
return new Token(paren, paren);
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* 'null'
|
|
333
|
+
*/
|
|
334
|
+
|
|
335
|
+
null: function() {
|
|
336
|
+
var captures;
|
|
337
|
+
if (captures = /^(null)\b */.exec(this.str)) {
|
|
338
|
+
this.skip(captures);
|
|
339
|
+
return new Token('null', nodes.null);
|
|
340
|
+
}
|
|
341
|
+
},
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* 'if'
|
|
345
|
+
* | 'else'
|
|
346
|
+
* | 'unless'
|
|
347
|
+
* | 'return'
|
|
348
|
+
* | 'for'
|
|
349
|
+
* | 'in'
|
|
350
|
+
*/
|
|
351
|
+
|
|
352
|
+
keyword: function() {
|
|
353
|
+
var captures;
|
|
354
|
+
if (captures = /^(return|if|else|unless|for|in)\b */.exec(this.str)) {
|
|
355
|
+
var keyword = captures[1];
|
|
356
|
+
this.skip(captures);
|
|
357
|
+
return new Token(keyword, keyword);
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* 'not'
|
|
363
|
+
* | 'and'
|
|
364
|
+
* | 'or'
|
|
365
|
+
* | 'is'
|
|
366
|
+
* | 'is not'
|
|
367
|
+
* | 'isnt'
|
|
368
|
+
* | 'is a'
|
|
369
|
+
* | 'is defined'
|
|
370
|
+
*/
|
|
371
|
+
|
|
372
|
+
namedop: function() {
|
|
373
|
+
var captures;
|
|
374
|
+
if (captures = /^(not|and|or|is a|is defined|isnt|is not|is)\b( *)/.exec(this.str)) {
|
|
375
|
+
var op = captures[1];
|
|
376
|
+
this.skip(captures);
|
|
377
|
+
op = alias[op] || op;
|
|
378
|
+
var tok = new Token(op, op);
|
|
379
|
+
tok.space = captures[2];
|
|
380
|
+
return tok;
|
|
381
|
+
}
|
|
382
|
+
},
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* ','
|
|
386
|
+
* | '+'
|
|
387
|
+
* | '+='
|
|
388
|
+
* | '-'
|
|
389
|
+
* | '-='
|
|
390
|
+
* | '*'
|
|
391
|
+
* | '*='
|
|
392
|
+
* | '/'
|
|
393
|
+
* | '/='
|
|
394
|
+
* | '%'
|
|
395
|
+
* | '%='
|
|
396
|
+
* | '**'
|
|
397
|
+
* | '!'
|
|
398
|
+
* | '&'
|
|
399
|
+
* | '&&'
|
|
400
|
+
* | '||'
|
|
401
|
+
* | '>'
|
|
402
|
+
* | '>='
|
|
403
|
+
* | '<'
|
|
404
|
+
* | '<='
|
|
405
|
+
* | '='
|
|
406
|
+
* | '=='
|
|
407
|
+
* | '!='
|
|
408
|
+
* | '!'
|
|
409
|
+
* | '~'
|
|
410
|
+
* | '?='
|
|
411
|
+
* | ':='
|
|
412
|
+
* | '?'
|
|
413
|
+
* | ':'
|
|
414
|
+
* | '['
|
|
415
|
+
* | ']'
|
|
416
|
+
* | '..'
|
|
417
|
+
* | '...'
|
|
418
|
+
*/
|
|
419
|
+
|
|
420
|
+
op: function() {
|
|
421
|
+
var captures;
|
|
422
|
+
if (captures = /^([.]{2,3}|&&|\|\||[!<>=?:]=|\*\*|[-+*\/%]=?|[,=?:!~<>&\[\]])( *)/.exec(this.str)) {
|
|
423
|
+
var op = captures[1];
|
|
424
|
+
this.skip(captures);
|
|
425
|
+
op = alias[op] || op;
|
|
426
|
+
var tok = new Token(op, op);
|
|
427
|
+
tok.space = captures[2];
|
|
428
|
+
return tok;
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* '@media' ([^{\n]+)
|
|
434
|
+
*/
|
|
435
|
+
|
|
436
|
+
media: function() {
|
|
437
|
+
var captures;
|
|
438
|
+
if (captures = /^@media *([^{\n]+)/.exec(this.str)) {
|
|
439
|
+
this.skip(captures);
|
|
440
|
+
return new Token('media', captures[1].trim());
|
|
441
|
+
}
|
|
442
|
+
},
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* '@' ('import' | 'keyframes' | 'charset' | 'page' | 'font-face')
|
|
446
|
+
*/
|
|
447
|
+
|
|
448
|
+
atrule: function() {
|
|
449
|
+
var captures;
|
|
450
|
+
if (captures = /^@(import|(?:-(\w+)-)?keyframes|charset|font-face|page) */.exec(this.str)) {
|
|
451
|
+
this.skip(captures);
|
|
452
|
+
var vendor = captures[2]
|
|
453
|
+
, type = captures[1];
|
|
454
|
+
if (vendor) type = 'keyframes';
|
|
455
|
+
return new Token(type, vendor);
|
|
456
|
+
}
|
|
457
|
+
},
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* '//' *
|
|
461
|
+
*/
|
|
462
|
+
|
|
463
|
+
comment: function() {
|
|
464
|
+
// Single line
|
|
465
|
+
if ('/' == this.str[0] && '/' == this.str[1]) {
|
|
466
|
+
var end = this.str.indexOf('\n');
|
|
467
|
+
if (-1 == end) end = this.str.length;
|
|
468
|
+
this.skip(end);
|
|
469
|
+
return this.advance();
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Multi-line
|
|
473
|
+
if ('/' == this.str[0] && '*' == this.str[1]) {
|
|
474
|
+
var end = this.str.indexOf('*/');
|
|
475
|
+
if (-1 == end) end = this.str.length;
|
|
476
|
+
var str = this.str.substr(0, end + 2)
|
|
477
|
+
, lines = str.split('\n').length - 1
|
|
478
|
+
, suppress = true;
|
|
479
|
+
this.lineno += lines;
|
|
480
|
+
this.skip(end + 2);
|
|
481
|
+
// output
|
|
482
|
+
if ('!' == str[2]) {
|
|
483
|
+
str = str.replace('*!', '*');
|
|
484
|
+
suppress = false;
|
|
485
|
+
}
|
|
486
|
+
return new Token('comment', new nodes.Comment(str, suppress));
|
|
487
|
+
}
|
|
488
|
+
},
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* 'true' | 'false'
|
|
492
|
+
*/
|
|
493
|
+
|
|
494
|
+
boolean: function() {
|
|
495
|
+
var captures;
|
|
496
|
+
if (captures = /^(true|false)\b( *)/.exec(this.str)) {
|
|
497
|
+
var val = nodes.Boolean('true' == captures[1]);
|
|
498
|
+
this.skip(captures);
|
|
499
|
+
var tok = new Token('boolean', val);
|
|
500
|
+
tok.space = captures[2];
|
|
501
|
+
return tok;
|
|
502
|
+
}
|
|
503
|
+
},
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* -?[a-zA-Z$] [-\w\d$]* '('
|
|
507
|
+
*/
|
|
508
|
+
|
|
509
|
+
function: function() {
|
|
510
|
+
var captures;
|
|
511
|
+
if (captures = /^(-?[a-zA-Z$][-\w\d$]*)\(( *)/.exec(this.str)) {
|
|
512
|
+
var name = captures[1];
|
|
513
|
+
this.skip(captures);
|
|
514
|
+
this.isURL = 'url' == name;
|
|
515
|
+
var tok = new Token('function', new nodes.Ident(name));
|
|
516
|
+
tok.space = captures[2];
|
|
517
|
+
return tok;
|
|
518
|
+
}
|
|
519
|
+
},
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* -?[_a-zA-Z$] [-\w\d$]*
|
|
523
|
+
*/
|
|
524
|
+
|
|
525
|
+
ident: function() {
|
|
526
|
+
var captures;
|
|
527
|
+
if (captures = /^(@)?(-?[_a-zA-Z$][-\w\d$]*)/.exec(this.str)) {
|
|
528
|
+
var at = captures[1]
|
|
529
|
+
, name = captures[2]
|
|
530
|
+
, id = new nodes.Ident(name);
|
|
531
|
+
this.skip(captures);
|
|
532
|
+
id.property = !! at;
|
|
533
|
+
return new Token('ident', id);
|
|
534
|
+
}
|
|
535
|
+
},
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* '\n' ' '+
|
|
539
|
+
*/
|
|
540
|
+
|
|
541
|
+
newline: function() {
|
|
542
|
+
var captures, re;
|
|
543
|
+
|
|
544
|
+
// we have established the indentation regexp
|
|
545
|
+
if (this.indentRe){
|
|
546
|
+
captures = this.indentRe.exec(this.str);
|
|
547
|
+
// figure out if we are using tabs or spaces
|
|
548
|
+
} else {
|
|
549
|
+
// try tabs
|
|
550
|
+
re = /^\n([\t]*) */;
|
|
551
|
+
captures = re.exec(this.str);
|
|
552
|
+
|
|
553
|
+
// nope, try spaces
|
|
554
|
+
if (captures && !captures[1].length) {
|
|
555
|
+
re = /^\n( *)/;
|
|
556
|
+
captures = re.exec(this.str);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// established
|
|
560
|
+
if (captures && captures[1].length) this.indentRe = re;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
if (captures) {
|
|
565
|
+
var tok
|
|
566
|
+
, indents = captures[1].length;
|
|
567
|
+
|
|
568
|
+
this.skip(captures);
|
|
569
|
+
if (this.str[0] === ' ' || this.str[0] === '\t') {
|
|
570
|
+
throw new errors.SyntaxError('Invalid indentation. You can use tabs or spaces to indent, but not both.');
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// Reset state
|
|
574
|
+
this.isVariable = false;
|
|
575
|
+
|
|
576
|
+
// Blank line
|
|
577
|
+
if ('\n' == this.str[0]) {
|
|
578
|
+
++this.lineno;
|
|
579
|
+
return this.advance();
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// Outdent
|
|
583
|
+
if (this.indentStack.length && indents < this.indentStack[0]) {
|
|
584
|
+
while (this.indentStack.length && this.indentStack[0] > indents) {
|
|
585
|
+
this.stash.push(new Token('outdent'));
|
|
586
|
+
this.indentStack.shift();
|
|
587
|
+
}
|
|
588
|
+
tok = this.stash.pop();
|
|
589
|
+
// Indent
|
|
590
|
+
} else if (indents && indents != this.indentStack[0]) {
|
|
591
|
+
this.indentStack.unshift(indents);
|
|
592
|
+
tok = new Token('indent');
|
|
593
|
+
// Newline
|
|
594
|
+
} else {
|
|
595
|
+
tok = new Token('newline');
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
return tok;
|
|
599
|
+
}
|
|
600
|
+
},
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* '-'? (digit+ | digit* '.' digit+) unit
|
|
604
|
+
*/
|
|
605
|
+
|
|
606
|
+
unit: function() {
|
|
607
|
+
var captures;
|
|
608
|
+
if (captures = unit.exec(this.str)) {
|
|
609
|
+
this.skip(captures);
|
|
610
|
+
var n = parseFloat(captures[2]);
|
|
611
|
+
if ('-' == captures[1]) n = -n;
|
|
612
|
+
var node = new nodes.Unit(n, captures[3]);
|
|
613
|
+
return new Token('unit', node);
|
|
614
|
+
}
|
|
615
|
+
},
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* '"' [^"]+ '"' | "'"" [^']+ "'"
|
|
619
|
+
*/
|
|
620
|
+
|
|
621
|
+
string: function() {
|
|
622
|
+
var captures;
|
|
623
|
+
if (captures = /^("[^"]*"|'[^']*') */.exec(this.str)) {
|
|
624
|
+
var str = captures[1];
|
|
625
|
+
this.skip(captures);
|
|
626
|
+
str = str.slice(1,-1).replace(/\\n/g, '\n');
|
|
627
|
+
return new Token('string', new nodes.String(str));
|
|
628
|
+
}
|
|
629
|
+
},
|
|
630
|
+
|
|
631
|
+
/**
|
|
632
|
+
* #rrggbbaa | #rrggbb | #rgba | #rgb
|
|
633
|
+
*/
|
|
634
|
+
|
|
635
|
+
color: function() {
|
|
636
|
+
return this.rrggbbaa()
|
|
637
|
+
|| this.rrggbb()
|
|
638
|
+
|| this.rgba()
|
|
639
|
+
|| this.rgb()
|
|
640
|
+
},
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* #rgb
|
|
644
|
+
*/
|
|
645
|
+
|
|
646
|
+
rgb: function() {
|
|
647
|
+
var captures;
|
|
648
|
+
if (captures = /^#([a-fA-F0-9]{3}) */.exec(this.str)) {
|
|
649
|
+
this.skip(captures);
|
|
650
|
+
var rgb = captures[1]
|
|
651
|
+
, r = parseInt(rgb[0] + rgb[0], 16)
|
|
652
|
+
, g = parseInt(rgb[1] + rgb[1], 16)
|
|
653
|
+
, b = parseInt(rgb[2] + rgb[2], 16)
|
|
654
|
+
, color = new nodes.RGBA(r, g, b, 1);
|
|
655
|
+
color.raw = captures[0];
|
|
656
|
+
return new Token('color', color);
|
|
657
|
+
}
|
|
658
|
+
},
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* #rgba
|
|
662
|
+
*/
|
|
663
|
+
|
|
664
|
+
rgba: function() {
|
|
665
|
+
var captures;
|
|
666
|
+
if (captures = /^#([a-fA-F0-9]{4}) */.exec(this.str)) {
|
|
667
|
+
this.skip(captures);
|
|
668
|
+
var rgb = captures[1]
|
|
669
|
+
, r = parseInt(rgb[0] + rgb[0], 16)
|
|
670
|
+
, g = parseInt(rgb[1] + rgb[1], 16)
|
|
671
|
+
, b = parseInt(rgb[2] + rgb[2], 16)
|
|
672
|
+
, a = parseInt(rgb[3] + rgb[3], 16)
|
|
673
|
+
, color = new nodes.RGBA(r, g, b, a/255);
|
|
674
|
+
color.raw = captures[0];
|
|
675
|
+
return new Token('color', color);
|
|
676
|
+
}
|
|
677
|
+
},
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* #rrggbb
|
|
681
|
+
*/
|
|
682
|
+
|
|
683
|
+
rrggbb: function() {
|
|
684
|
+
var captures;
|
|
685
|
+
if (captures = /^#([a-fA-F0-9]{6}) */.exec(this.str)) {
|
|
686
|
+
this.skip(captures);
|
|
687
|
+
var rgb = captures[1]
|
|
688
|
+
, r = parseInt(rgb.substr(0, 2), 16)
|
|
689
|
+
, g = parseInt(rgb.substr(2, 2), 16)
|
|
690
|
+
, b = parseInt(rgb.substr(4, 2), 16)
|
|
691
|
+
, color = new nodes.RGBA(r, g, b, 1);
|
|
692
|
+
color.raw = captures[0];
|
|
693
|
+
return new Token('color', color);
|
|
694
|
+
}
|
|
695
|
+
},
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* #rrggbbaa
|
|
699
|
+
*/
|
|
700
|
+
|
|
701
|
+
rrggbbaa: function() {
|
|
702
|
+
var captures;
|
|
703
|
+
if (captures = /^#([a-fA-F0-9]{8}) */.exec(this.str)) {
|
|
704
|
+
this.skip(captures);
|
|
705
|
+
var rgb = captures[1]
|
|
706
|
+
, r = parseInt(rgb.substr(0, 2), 16)
|
|
707
|
+
, g = parseInt(rgb.substr(2, 2), 16)
|
|
708
|
+
, b = parseInt(rgb.substr(4, 2), 16)
|
|
709
|
+
, a = parseInt(rgb.substr(6, 2), 16)
|
|
710
|
+
, color = new nodes.RGBA(r, g, b, a/255);
|
|
711
|
+
color.raw = captures[0];
|
|
712
|
+
return new Token('color', color);
|
|
713
|
+
}
|
|
714
|
+
},
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* [^\n,;]+
|
|
718
|
+
*/
|
|
719
|
+
|
|
720
|
+
selector: function() {
|
|
721
|
+
var captures;
|
|
722
|
+
if (captures = /^[^{\n,]+/.exec(this.str)) {
|
|
723
|
+
var selector = captures[0];
|
|
724
|
+
this.skip(captures);
|
|
725
|
+
return new Token('selector', selector);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
};
|