jade-js-source 0.15.4 → 0.16.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/jade_js/jade.js +283 -72
- data/lib/jade_js/runtime.js +123 -0
- data/lib/jade_js/source.rb +3 -0
- metadata +4 -5
data/lib/jade_js/jade.js
CHANGED
@@ -135,7 +135,7 @@ Compiler.prototype = {
|
|
135
135
|
|
136
136
|
setDoctype: function(name){
|
137
137
|
var doctype = doctypes[(name || 'default').toLowerCase()];
|
138
|
-
|
138
|
+
doctype = doctype || '<!DOCTYPE ' + name + '>';
|
139
139
|
this.doctype = doctype;
|
140
140
|
this.terse = '5' == name || 'html' == name;
|
141
141
|
this.xml = 0 == this.doctype.indexOf('<?xml');
|
@@ -162,18 +162,6 @@ Compiler.prototype = {
|
|
162
162
|
}
|
163
163
|
},
|
164
164
|
|
165
|
-
/**
|
166
|
-
* Buffer the given `node`'s lineno.
|
167
|
-
*
|
168
|
-
* @param {Node} node
|
169
|
-
* @api public
|
170
|
-
*/
|
171
|
-
|
172
|
-
line: function(node){
|
173
|
-
if (false === node.instrumentLineNumber) return;
|
174
|
-
this.buf.push('__.lineno = ' + node.line + ';');
|
175
|
-
},
|
176
|
-
|
177
165
|
/**
|
178
166
|
* Visit `node`.
|
179
167
|
*
|
@@ -182,8 +170,26 @@ Compiler.prototype = {
|
|
182
170
|
*/
|
183
171
|
|
184
172
|
visit: function(node){
|
185
|
-
|
186
|
-
|
173
|
+
var debug = this.debug;
|
174
|
+
|
175
|
+
if (debug) {
|
176
|
+
this.buf.push('__.unshift({ lineno: ' + node.line
|
177
|
+
+ ', filename: ' + (node.filename
|
178
|
+
? '"' + node.filename + '"'
|
179
|
+
: '__[0].filename')
|
180
|
+
+ ' });');
|
181
|
+
}
|
182
|
+
|
183
|
+
// Massive hack to fix our context
|
184
|
+
// stack for - else[ if] etc
|
185
|
+
if (false === node.debug && this.debug) {
|
186
|
+
this.buf.pop();
|
187
|
+
this.buf.pop();
|
188
|
+
}
|
189
|
+
|
190
|
+
this.visitNode(node);
|
191
|
+
|
192
|
+
if (debug) this.buf.push('__.shift();');
|
187
193
|
},
|
188
194
|
|
189
195
|
/**
|
@@ -516,7 +522,6 @@ require.register("doctypes.js", function(module, exports, require){
|
|
516
522
|
|
517
523
|
module.exports = {
|
518
524
|
'5': '<!DOCTYPE html>'
|
519
|
-
, 'html': '<!DOCTYPE html>'
|
520
525
|
, 'xml': '<?xml version="1.0" encoding="utf-8" ?>'
|
521
526
|
, 'default': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
|
522
527
|
, 'transitional': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
|
@@ -553,7 +558,7 @@ module.exports = {
|
|
553
558
|
sass: function(str){
|
554
559
|
str = str.replace(/\\n/g, '\n');
|
555
560
|
var sass = require('sass').render(str).replace(/\n/g, '\\n');
|
556
|
-
return '<style>' + sass + '</style>';
|
561
|
+
return '<style type="text/css">' + sass + '</style>';
|
557
562
|
},
|
558
563
|
|
559
564
|
/**
|
@@ -568,11 +573,11 @@ module.exports = {
|
|
568
573
|
if (err) throw err;
|
569
574
|
ret = css.replace(/\n/g, '\\n');
|
570
575
|
});
|
571
|
-
return '<style>' + ret + '</style>';
|
576
|
+
return '<style type="text/css">' + ret + '</style>';
|
572
577
|
},
|
573
578
|
|
574
579
|
/**
|
575
|
-
* Transform
|
580
|
+
* Transform less to css, wrapped in style tags.
|
576
581
|
*/
|
577
582
|
|
578
583
|
less: function(str){
|
@@ -580,7 +585,7 @@ module.exports = {
|
|
580
585
|
str = str.replace(/\\n/g, '\n');
|
581
586
|
require('less').render(str, function(err, css){
|
582
587
|
if (err) throw err;
|
583
|
-
ret = '<style>' + css.replace(/\n/g, '\\n') + '</style>';
|
588
|
+
ret = '<style type="text/css">' + css.replace(/\n/g, '\\n') + '</style>';
|
584
589
|
});
|
585
590
|
return ret;
|
586
591
|
},
|
@@ -621,6 +626,7 @@ module.exports = {
|
|
621
626
|
return '<script type="text/javascript">\\n' + js + '</script>';
|
622
627
|
}
|
623
628
|
};
|
629
|
+
|
624
630
|
}); // module: filters.js
|
625
631
|
|
626
632
|
require.register("inline-tags.js", function(module, exports, require){
|
@@ -667,6 +673,7 @@ require.register("jade.js", function(module, exports, require){
|
|
667
673
|
*/
|
668
674
|
|
669
675
|
var Parser = require('./parser')
|
676
|
+
, Lexer = require('./lexer')
|
670
677
|
, Compiler = require('./compiler')
|
671
678
|
, runtime = require('./runtime')
|
672
679
|
|
@@ -674,13 +681,7 @@ var Parser = require('./parser')
|
|
674
681
|
* Library version.
|
675
682
|
*/
|
676
683
|
|
677
|
-
exports.version = '0.
|
678
|
-
|
679
|
-
/**
|
680
|
-
* Intermediate JavaScript cache.
|
681
|
-
*/
|
682
|
-
|
683
|
-
var cache = exports.cache = {};
|
684
|
+
exports.version = '0.16.1';
|
684
685
|
|
685
686
|
/**
|
686
687
|
* Expose self closing tags.
|
@@ -718,6 +719,12 @@ exports.Compiler = Compiler;
|
|
718
719
|
|
719
720
|
exports.Parser = Parser;
|
720
721
|
|
722
|
+
/**
|
723
|
+
* Expose `Lexer`.
|
724
|
+
*/
|
725
|
+
|
726
|
+
exports.Lexer = Lexer;
|
727
|
+
|
721
728
|
/**
|
722
729
|
* Nodes.
|
723
730
|
*/
|
@@ -730,6 +737,12 @@ exports.nodes = require('./nodes');
|
|
730
737
|
|
731
738
|
exports.runtime = runtime;
|
732
739
|
|
740
|
+
/**
|
741
|
+
* Template function cache.
|
742
|
+
*/
|
743
|
+
|
744
|
+
exports.cache = {};
|
745
|
+
|
733
746
|
/**
|
734
747
|
* Parse the given `str` of jade and return a function body.
|
735
748
|
*
|
@@ -740,11 +753,9 @@ exports.runtime = runtime;
|
|
740
753
|
*/
|
741
754
|
|
742
755
|
function parse(str, options){
|
743
|
-
var filename = options.filename;
|
744
|
-
|
745
756
|
try {
|
746
757
|
// Parse
|
747
|
-
var parser = new Parser(str, filename, options);
|
758
|
+
var parser = new Parser(str, options.filename, options);
|
748
759
|
|
749
760
|
// Compile
|
750
761
|
var compiler = new (options.compiler || Compiler)(parser.parse(), options)
|
@@ -752,23 +763,18 @@ function parse(str, options){
|
|
752
763
|
|
753
764
|
// Debug compiler
|
754
765
|
if (options.debug) {
|
755
|
-
console.
|
766
|
+
console.error('\nCompiled Function:\n\n\033[90m%s\033[0m', js.replace(/^/gm, ' '));
|
756
767
|
}
|
757
768
|
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
+
|
762
|
-
|
763
|
-
|
764
|
-
+ 'return buf.join("");';
|
765
|
-
|
766
|
-
} catch (err) {
|
767
|
-
process.compile(js, filename || 'Jade');
|
768
|
-
return;
|
769
|
-
}
|
769
|
+
return ''
|
770
|
+
+ 'var buf = [];\n'
|
771
|
+
+ (options.self
|
772
|
+
? 'var self = locals || {};\n' + js
|
773
|
+
: 'with (locals || {}) {\n' + js + '\n}\n')
|
774
|
+
+ 'return buf.join("");';
|
770
775
|
} catch (err) {
|
771
|
-
|
776
|
+
parser = parser.context();
|
777
|
+
runtime.rethrow(err, parser.filename, parser.lexer.lineno);
|
772
778
|
}
|
773
779
|
}
|
774
780
|
|
@@ -789,7 +795,6 @@ function parse(str, options){
|
|
789
795
|
|
790
796
|
exports.compile = function(str, options){
|
791
797
|
var options = options || {}
|
792
|
-
, input = JSON.stringify(str)
|
793
798
|
, client = options.client
|
794
799
|
, filename = options.filename
|
795
800
|
? JSON.stringify(options.filename)
|
@@ -798,11 +803,11 @@ exports.compile = function(str, options){
|
|
798
803
|
|
799
804
|
if (options.compileDebug !== false) {
|
800
805
|
fn = [
|
801
|
-
'var __ = { lineno: 1,
|
806
|
+
'var __ = [{ lineno: 1, filename: ' + filename + ' }];'
|
802
807
|
, 'try {'
|
803
808
|
, parse(String(str), options || {})
|
804
809
|
, '} catch (err) {'
|
805
|
-
, ' rethrow(err, __.
|
810
|
+
, ' rethrow(err, __[0].filename, __[0].lineno);'
|
806
811
|
, '}'
|
807
812
|
].join('\n');
|
808
813
|
} else {
|
@@ -822,6 +827,42 @@ exports.compile = function(str, options){
|
|
822
827
|
};
|
823
828
|
};
|
824
829
|
|
830
|
+
/**
|
831
|
+
* Render the given `str` of jade and invoke
|
832
|
+
* the callback `fn(err, str)`.
|
833
|
+
*
|
834
|
+
* Options:
|
835
|
+
*
|
836
|
+
* - `cache` enable template caching
|
837
|
+
* - `filename` filename required for `include` / `extends` and caching
|
838
|
+
*
|
839
|
+
* @param {String} str
|
840
|
+
* @param {Object|Function} options or fn
|
841
|
+
* @param {Function} fn
|
842
|
+
* @api public
|
843
|
+
*/
|
844
|
+
|
845
|
+
exports.render = function(str, options, fn){
|
846
|
+
// swap args
|
847
|
+
if ('function' == typeof options) {
|
848
|
+
fn = options, options = {};
|
849
|
+
}
|
850
|
+
|
851
|
+
// cache requires .filename
|
852
|
+
if (options.cache && !options.filename) {
|
853
|
+
return fn(new Error('the "filename" option is required for caching'));
|
854
|
+
}
|
855
|
+
|
856
|
+
try {
|
857
|
+
var path = options.filename;
|
858
|
+
var tmpl = options.cache
|
859
|
+
? exports.cache[path] || (exports.cache[path] = exports.compile(str, options))
|
860
|
+
: exports.compile(str, options);
|
861
|
+
fn(null, tmpl(options));
|
862
|
+
} catch (err) {
|
863
|
+
fn(err);
|
864
|
+
}
|
865
|
+
};
|
825
866
|
}); // module: jade.js
|
826
867
|
|
827
868
|
require.register("lexer.js", function(module, exports, require){
|
@@ -1018,7 +1059,7 @@ Lexer.prototype = {
|
|
1018
1059
|
if (':' == name[name.length - 1]) {
|
1019
1060
|
name = name.slice(0, -1);
|
1020
1061
|
tok = this.tok('tag', name);
|
1021
|
-
this.
|
1062
|
+
this.defer(this.tok(':'));
|
1022
1063
|
while (' ' == this.input[0]) this.input = this.input.substr(1);
|
1023
1064
|
} else {
|
1024
1065
|
tok = this.tok('tag', name);
|
@@ -1040,7 +1081,7 @@ Lexer.prototype = {
|
|
1040
1081
|
*/
|
1041
1082
|
|
1042
1083
|
doctype: function() {
|
1043
|
-
return this.scan(/^(?:!!!|doctype) *(
|
1084
|
+
return this.scan(/^(?:!!!|doctype) *([^\n]+)?/, 'doctype');
|
1044
1085
|
},
|
1045
1086
|
|
1046
1087
|
/**
|
@@ -1067,6 +1108,22 @@ Lexer.prototype = {
|
|
1067
1108
|
return this.scan(/^(?:\| ?)?([^\n]+)/, 'text');
|
1068
1109
|
},
|
1069
1110
|
|
1111
|
+
/**
|
1112
|
+
* Extends.
|
1113
|
+
*/
|
1114
|
+
|
1115
|
+
extends: function() {
|
1116
|
+
return this.scan(/^extends +([^\n]+)/, 'extends');
|
1117
|
+
},
|
1118
|
+
|
1119
|
+
/**
|
1120
|
+
* Block.
|
1121
|
+
*/
|
1122
|
+
|
1123
|
+
block: function() {
|
1124
|
+
return this.scan(/^block +([^\n]+)/, 'block');
|
1125
|
+
},
|
1126
|
+
|
1070
1127
|
/**
|
1071
1128
|
* Include.
|
1072
1129
|
*/
|
@@ -1075,6 +1132,20 @@ Lexer.prototype = {
|
|
1075
1132
|
return this.scan(/^include +([^\n]+)/, 'include');
|
1076
1133
|
},
|
1077
1134
|
|
1135
|
+
/**
|
1136
|
+
* Assignment.
|
1137
|
+
*/
|
1138
|
+
|
1139
|
+
assignment: function() {
|
1140
|
+
var captures;
|
1141
|
+
if (captures = /^(\w+) += *([^\n]+)/.exec(this.input)) {
|
1142
|
+
this.consume(captures[0].length);
|
1143
|
+
var name = captures[1]
|
1144
|
+
, val = captures[2];
|
1145
|
+
return this.tok('code', 'var ' + name + ' = (' + val + ')');
|
1146
|
+
}
|
1147
|
+
},
|
1148
|
+
|
1078
1149
|
/**
|
1079
1150
|
* Mixin.
|
1080
1151
|
*/
|
@@ -1111,6 +1182,18 @@ Lexer.prototype = {
|
|
1111
1182
|
}
|
1112
1183
|
},
|
1113
1184
|
|
1185
|
+
/**
|
1186
|
+
* While.
|
1187
|
+
*/
|
1188
|
+
|
1189
|
+
while: function() {
|
1190
|
+
var captures;
|
1191
|
+
if (captures = /^while +([^\n]+)/.exec(this.input)) {
|
1192
|
+
this.consume(captures[0].length);
|
1193
|
+
return this.tok('code', 'while (' + captures[1] + ')');
|
1194
|
+
}
|
1195
|
+
},
|
1196
|
+
|
1114
1197
|
/**
|
1115
1198
|
* Each.
|
1116
1199
|
*/
|
@@ -1120,7 +1203,7 @@ Lexer.prototype = {
|
|
1120
1203
|
if (captures = /^(?:- *)?(?:each|for) +(\w+)(?: *, *(\w+))? * in *([^\n]+)/.exec(this.input)) {
|
1121
1204
|
this.consume(captures[0].length);
|
1122
1205
|
var tok = this.tok('each', captures[1]);
|
1123
|
-
tok.key = captures[2] || 'index';
|
1206
|
+
tok.key = captures[2] || '$index';
|
1124
1207
|
tok.code = captures[3];
|
1125
1208
|
return tok;
|
1126
1209
|
}
|
@@ -1215,11 +1298,13 @@ Lexer.prototype = {
|
|
1215
1298
|
}
|
1216
1299
|
break;
|
1217
1300
|
case '(':
|
1218
|
-
if ('val' == state()
|
1301
|
+
if ('val' == state()
|
1302
|
+
|| 'expr' == state()) states.push('expr');
|
1219
1303
|
val += c;
|
1220
1304
|
break;
|
1221
1305
|
case ')':
|
1222
|
-
if ('expr' == state()
|
1306
|
+
if ('expr' == state()
|
1307
|
+
|| 'val' == state()) states.pop();
|
1223
1308
|
val += c;
|
1224
1309
|
break;
|
1225
1310
|
case '{':
|
@@ -1390,10 +1475,14 @@ Lexer.prototype = {
|
|
1390
1475
|
|| this.eos()
|
1391
1476
|
|| this.pipelessText()
|
1392
1477
|
|| this.doctype()
|
1478
|
+
|| this.extends()
|
1479
|
+
|| this.block()
|
1393
1480
|
|| this.include()
|
1394
1481
|
|| this.mixin()
|
1395
1482
|
|| this.conditional()
|
1396
1483
|
|| this.each()
|
1484
|
+
|| this.while()
|
1485
|
+
|| this.assignment()
|
1397
1486
|
|| this.tag()
|
1398
1487
|
|| this.filter()
|
1399
1488
|
|| this.code()
|
@@ -1481,6 +1570,18 @@ Block.prototype = new Node;
|
|
1481
1570
|
Block.prototype.constructor = Block;
|
1482
1571
|
|
1483
1572
|
|
1573
|
+
/**
|
1574
|
+
* Replace the nodes in `other` with the nodes
|
1575
|
+
* in `this` block.
|
1576
|
+
*
|
1577
|
+
* @param {Block} other
|
1578
|
+
* @api private
|
1579
|
+
*/
|
1580
|
+
|
1581
|
+
Block.prototype.replace = function(other){
|
1582
|
+
other.nodes = this.nodes;
|
1583
|
+
};
|
1584
|
+
|
1484
1585
|
/**
|
1485
1586
|
* Pust the given `node`.
|
1486
1587
|
*
|
@@ -1493,6 +1594,17 @@ Block.prototype.push = function(node){
|
|
1493
1594
|
return this.nodes.push(node);
|
1494
1595
|
};
|
1495
1596
|
|
1597
|
+
/**
|
1598
|
+
* Check if this block is empty.
|
1599
|
+
*
|
1600
|
+
* @return {Boolean}
|
1601
|
+
* @api public
|
1602
|
+
*/
|
1603
|
+
|
1604
|
+
Block.prototype.isEmpty = function(){
|
1605
|
+
return 0 == this.nodes.length;
|
1606
|
+
};
|
1607
|
+
|
1496
1608
|
/**
|
1497
1609
|
* Unshift the given `node`.
|
1498
1610
|
*
|
@@ -1505,6 +1617,25 @@ Block.prototype.unshift = function(node){
|
|
1505
1617
|
return this.nodes.unshift(node);
|
1506
1618
|
};
|
1507
1619
|
|
1620
|
+
/**
|
1621
|
+
* Return the "last" block.
|
1622
|
+
*
|
1623
|
+
* @return {Block}
|
1624
|
+
* @api private
|
1625
|
+
*/
|
1626
|
+
|
1627
|
+
Block.prototype.lastBlock = function(){
|
1628
|
+
var last = this
|
1629
|
+
, node;
|
1630
|
+
for (var i = 0, len = this.nodes.length; i < len; ++i) {
|
1631
|
+
node = this.nodes[i];
|
1632
|
+
if (node.nodes) last = node.lastBlock();
|
1633
|
+
else if (node.block && !node.block.isEmpty()) last = node.block.lastBlock();
|
1634
|
+
}
|
1635
|
+
return last;
|
1636
|
+
};
|
1637
|
+
|
1638
|
+
|
1508
1639
|
}); // module: nodes/block.js
|
1509
1640
|
|
1510
1641
|
require.register("nodes/code.js", function(module, exports, require){
|
@@ -1535,7 +1666,7 @@ var Code = module.exports = function Code(val, buffer, escape) {
|
|
1535
1666
|
this.val = val;
|
1536
1667
|
this.buffer = buffer;
|
1537
1668
|
this.escape = escape;
|
1538
|
-
if (/^ *else
|
1669
|
+
if (val.match(/^ *else/)) this.debug = false;
|
1539
1670
|
};
|
1540
1671
|
|
1541
1672
|
/**
|
@@ -1975,6 +2106,9 @@ var Parser = exports = module.exports = function Parser(str, filename, options){
|
|
1975
2106
|
this.input = str;
|
1976
2107
|
this.lexer = new Lexer(str, options);
|
1977
2108
|
this.filename = filename;
|
2109
|
+
this.blocks = {};
|
2110
|
+
this.options = options;
|
2111
|
+
this.contexts = [this];
|
1978
2112
|
};
|
1979
2113
|
|
1980
2114
|
/**
|
@@ -1988,7 +2122,20 @@ var textOnly = exports.textOnly = ['code', 'script', 'textarea', 'style', 'title
|
|
1988
2122
|
*/
|
1989
2123
|
|
1990
2124
|
Parser.prototype = {
|
1991
|
-
|
2125
|
+
|
2126
|
+
/**
|
2127
|
+
* Push `parser` onto the context stack,
|
2128
|
+
* or pop and return a `Parser`.
|
2129
|
+
*/
|
2130
|
+
|
2131
|
+
context: function(parser){
|
2132
|
+
if (parser) {
|
2133
|
+
this.contexts.push(parser);
|
2134
|
+
} else {
|
2135
|
+
return this.contexts.pop();
|
2136
|
+
}
|
2137
|
+
},
|
2138
|
+
|
1992
2139
|
/**
|
1993
2140
|
* Return the next token object.
|
1994
2141
|
*
|
@@ -2053,8 +2200,9 @@ Parser.prototype = {
|
|
2053
2200
|
*/
|
2054
2201
|
|
2055
2202
|
parse: function(){
|
2056
|
-
var block = new nodes.Block;
|
2203
|
+
var block = new nodes.Block, parser;
|
2057
2204
|
block.line = this.line();
|
2205
|
+
|
2058
2206
|
while ('eos' != this.peek().type) {
|
2059
2207
|
if ('newline' == this.peek().type) {
|
2060
2208
|
this.advance();
|
@@ -2062,6 +2210,14 @@ Parser.prototype = {
|
|
2062
2210
|
block.push(this.parseExpr());
|
2063
2211
|
}
|
2064
2212
|
}
|
2213
|
+
|
2214
|
+
if (parser = this.extending) {
|
2215
|
+
this.context(parser);
|
2216
|
+
var ast = parser.parse();
|
2217
|
+
this.context();
|
2218
|
+
return ast;
|
2219
|
+
}
|
2220
|
+
|
2065
2221
|
return block;
|
2066
2222
|
},
|
2067
2223
|
|
@@ -2113,6 +2269,10 @@ Parser.prototype = {
|
|
2113
2269
|
return this.parseTag();
|
2114
2270
|
case 'mixin':
|
2115
2271
|
return this.parseMixin();
|
2272
|
+
case 'block':
|
2273
|
+
return this.parseBlock();
|
2274
|
+
case 'extends':
|
2275
|
+
return this.parseExtends();
|
2116
2276
|
case 'include':
|
2117
2277
|
return this.parseInclude();
|
2118
2278
|
case 'doctype':
|
@@ -2163,7 +2323,7 @@ Parser.prototype = {
|
|
2163
2323
|
block = 'indent' == this.lookahead(i).type;
|
2164
2324
|
if (block) {
|
2165
2325
|
this.skip(i-1);
|
2166
|
-
node.block = this.
|
2326
|
+
node.block = this.block();
|
2167
2327
|
}
|
2168
2328
|
return node;
|
2169
2329
|
},
|
@@ -2177,7 +2337,7 @@ Parser.prototype = {
|
|
2177
2337
|
, node;
|
2178
2338
|
|
2179
2339
|
if ('indent' == this.peek().type) {
|
2180
|
-
node = new nodes.BlockComment(tok.val, this.
|
2340
|
+
node = new nodes.BlockComment(tok.val, this.block(), tok.buffer);
|
2181
2341
|
} else {
|
2182
2342
|
node = new nodes.Comment(tok.val, tok.buffer);
|
2183
2343
|
}
|
@@ -2225,7 +2385,7 @@ Parser.prototype = {
|
|
2225
2385
|
, attrs = this.accept('attrs');
|
2226
2386
|
|
2227
2387
|
this.expect(':');
|
2228
|
-
block = this.
|
2388
|
+
block = this.block();
|
2229
2389
|
|
2230
2390
|
var node = new nodes.Filter(tok.val, block, attrs && attrs.attrs);
|
2231
2391
|
node.line = this.line();
|
@@ -2238,16 +2398,16 @@ Parser.prototype = {
|
|
2238
2398
|
|
2239
2399
|
parseEach: function(){
|
2240
2400
|
var tok = this.expect('each')
|
2241
|
-
, node = new nodes.Each(tok.code, tok.val, tok.key, this.
|
2401
|
+
, node = new nodes.Each(tok.code, tok.val, tok.key, this.block());
|
2242
2402
|
node.line = this.line();
|
2243
2403
|
return node;
|
2244
2404
|
},
|
2245
2405
|
|
2246
2406
|
/**
|
2247
|
-
*
|
2407
|
+
* 'extends' name
|
2248
2408
|
*/
|
2249
2409
|
|
2250
|
-
|
2410
|
+
parseExtends: function(){
|
2251
2411
|
var path = require('path')
|
2252
2412
|
, fs = require('fs')
|
2253
2413
|
, dirname = path.dirname
|
@@ -2255,11 +2415,52 @@ Parser.prototype = {
|
|
2255
2415
|
, join = path.join;
|
2256
2416
|
|
2257
2417
|
if (!this.filename)
|
2258
|
-
throw new Error('the "filename" option is required to
|
2418
|
+
throw new Error('the "filename" option is required to extend templates');
|
2419
|
+
|
2420
|
+
var path = name = this.expect('extends').val.trim()
|
2421
|
+
, dir = dirname(this.filename);
|
2422
|
+
|
2423
|
+
var path = join(dir, path + '.jade')
|
2424
|
+
, str = fs.readFileSync(path, 'utf8')
|
2425
|
+
, parser = new Parser(str, path, this.options);
|
2426
|
+
|
2427
|
+
parser.blocks = this.blocks;
|
2428
|
+
parser.contexts = this.contexts;
|
2429
|
+
this.extending = parser;
|
2430
|
+
|
2431
|
+
// TODO: null node
|
2432
|
+
return new nodes.Literal('');
|
2433
|
+
},
|
2434
|
+
|
2435
|
+
/**
|
2436
|
+
* 'block' name block
|
2437
|
+
*/
|
2438
|
+
|
2439
|
+
parseBlock: function(){
|
2440
|
+
var name = this.expect('block').val.trim();
|
2441
|
+
var block = 'indent' == this.peek().type
|
2442
|
+
? this.block()
|
2443
|
+
: new nodes.Block(new nodes.Literal(''));
|
2444
|
+
return this.blocks[name] = this.blocks[name] || block;
|
2445
|
+
},
|
2446
|
+
|
2447
|
+
/**
|
2448
|
+
* include block?
|
2449
|
+
*/
|
2450
|
+
|
2451
|
+
parseInclude: function(){
|
2452
|
+
var path = require('path')
|
2453
|
+
, fs = require('fs')
|
2454
|
+
, dirname = path.dirname
|
2455
|
+
, basename = path.basename
|
2456
|
+
, join = path.join;
|
2259
2457
|
|
2260
2458
|
var path = name = this.expect('include').val.trim()
|
2261
2459
|
, dir = dirname(this.filename);
|
2262
2460
|
|
2461
|
+
if (!this.filename)
|
2462
|
+
throw new Error('the "filename" option is required to use includes');
|
2463
|
+
|
2263
2464
|
// non-jade
|
2264
2465
|
if (~basename(path).indexOf('.')) {
|
2265
2466
|
var path = join(dir, path)
|
@@ -2269,8 +2470,16 @@ Parser.prototype = {
|
|
2269
2470
|
|
2270
2471
|
var path = join(dir, path + '.jade')
|
2271
2472
|
, str = fs.readFileSync(path, 'utf8')
|
2272
|
-
|
2273
|
-
|
2473
|
+
, parser = new Parser(str, path, this.options);
|
2474
|
+
|
2475
|
+
this.context(parser);
|
2476
|
+
var ast = parser.parse();
|
2477
|
+
this.context();
|
2478
|
+
ast.filename = path;
|
2479
|
+
|
2480
|
+
if ('indent' == this.peek().type) {
|
2481
|
+
ast.lastBlock().push(this.block());
|
2482
|
+
}
|
2274
2483
|
|
2275
2484
|
return ast;
|
2276
2485
|
},
|
@@ -2284,7 +2493,7 @@ Parser.prototype = {
|
|
2284
2493
|
, name = tok.val
|
2285
2494
|
, args = tok.args;
|
2286
2495
|
var block = 'indent' == this.peek().type
|
2287
|
-
? this.
|
2496
|
+
? this.block()
|
2288
2497
|
: null;
|
2289
2498
|
return new nodes.Mixin(name, args, block);
|
2290
2499
|
},
|
@@ -2326,7 +2535,7 @@ Parser.prototype = {
|
|
2326
2535
|
* indent expr* outdent
|
2327
2536
|
*/
|
2328
2537
|
|
2329
|
-
|
2538
|
+
block: function(){
|
2330
2539
|
var block = new nodes.Block;
|
2331
2540
|
block.line = this.line();
|
2332
2541
|
this.expect('indent');
|
@@ -2425,7 +2634,7 @@ Parser.prototype = {
|
|
2425
2634
|
tag.block = this.parseTextBlock();
|
2426
2635
|
this.lexer.pipeless = false;
|
2427
2636
|
} else {
|
2428
|
-
var block = this.
|
2637
|
+
var block = this.block();
|
2429
2638
|
if (tag.block) {
|
2430
2639
|
for (var i = 0, len = block.nodes.length; i < len; ++i) {
|
2431
2640
|
tag.block.push(block.nodes[i]);
|
@@ -2456,7 +2665,7 @@ require.register("runtime.js", function(module, exports, require){
|
|
2456
2665
|
|
2457
2666
|
if (!Array.isArray) {
|
2458
2667
|
Array.isArray = function(arr){
|
2459
|
-
return '[object Array]' == toString.call(arr);
|
2668
|
+
return '[object Array]' == Object.prototype.toString.call(arr);
|
2460
2669
|
};
|
2461
2670
|
}
|
2462
2671
|
|
@@ -2469,7 +2678,7 @@ if (!Object.keys) {
|
|
2469
2678
|
var arr = [];
|
2470
2679
|
for (var key in obj) {
|
2471
2680
|
if (obj.hasOwnProperty(key)) {
|
2472
|
-
arr.push(
|
2681
|
+
arr.push(key);
|
2473
2682
|
}
|
2474
2683
|
}
|
2475
2684
|
return arr;
|
@@ -2529,17 +2738,19 @@ exports.escape = function escape(html){
|
|
2529
2738
|
|
2530
2739
|
/**
|
2531
2740
|
* Re-throw the given `err` in context to the
|
2532
|
-
*
|
2741
|
+
* the jade in `filename` at the given `lineno`.
|
2533
2742
|
*
|
2534
2743
|
* @param {Error} err
|
2535
|
-
* @param {String} str
|
2536
2744
|
* @param {String} filename
|
2537
2745
|
* @param {String} lineno
|
2538
2746
|
* @api private
|
2539
2747
|
*/
|
2540
2748
|
|
2541
|
-
exports.rethrow = function rethrow(err,
|
2749
|
+
exports.rethrow = function rethrow(err, filename, lineno){
|
2750
|
+
if (!filename) throw err;
|
2751
|
+
|
2542
2752
|
var context = 3
|
2753
|
+
, str = require('fs').readFileSync(filename, 'utf8')
|
2543
2754
|
, lines = str.split('\n')
|
2544
2755
|
, start = Math.max(lineno - context, 0)
|
2545
2756
|
, end = Math.min(lines.length, lineno + context);
|
@@ -0,0 +1,123 @@
|
|
1
|
+
|
2
|
+
var jade = (function(exports){
|
3
|
+
/*!
|
4
|
+
* Jade - runtime
|
5
|
+
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
6
|
+
* MIT Licensed
|
7
|
+
*/
|
8
|
+
|
9
|
+
/**
|
10
|
+
* Lame Array.isArray() polyfill for now.
|
11
|
+
*/
|
12
|
+
|
13
|
+
if (!Array.isArray) {
|
14
|
+
Array.isArray = function(arr){
|
15
|
+
return '[object Array]' == Object.prototype.toString.call(arr);
|
16
|
+
};
|
17
|
+
}
|
18
|
+
|
19
|
+
/**
|
20
|
+
* Lame Object.keys() polyfill for now.
|
21
|
+
*/
|
22
|
+
|
23
|
+
if (!Object.keys) {
|
24
|
+
Object.keys = function(obj){
|
25
|
+
var arr = [];
|
26
|
+
for (var key in obj) {
|
27
|
+
if (obj.hasOwnProperty(key)) {
|
28
|
+
arr.push(key);
|
29
|
+
}
|
30
|
+
}
|
31
|
+
return arr;
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
/**
|
36
|
+
* Render the given attributes object.
|
37
|
+
*
|
38
|
+
* @param {Object} obj
|
39
|
+
* @return {String}
|
40
|
+
* @api private
|
41
|
+
*/
|
42
|
+
|
43
|
+
exports.attrs = function attrs(obj){
|
44
|
+
var buf = []
|
45
|
+
, terse = obj.terse;
|
46
|
+
delete obj.terse;
|
47
|
+
var keys = Object.keys(obj)
|
48
|
+
, len = keys.length;
|
49
|
+
if (len) {
|
50
|
+
buf.push('');
|
51
|
+
for (var i = 0; i < len; ++i) {
|
52
|
+
var key = keys[i]
|
53
|
+
, val = obj[key];
|
54
|
+
if ('boolean' == typeof val || null == val) {
|
55
|
+
if (val) {
|
56
|
+
terse
|
57
|
+
? buf.push(key)
|
58
|
+
: buf.push(key + '="' + key + '"');
|
59
|
+
}
|
60
|
+
} else if ('class' == key && Array.isArray(val)) {
|
61
|
+
buf.push(key + '="' + exports.escape(val.join(' ')) + '"');
|
62
|
+
} else {
|
63
|
+
buf.push(key + '="' + exports.escape(val) + '"');
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
return buf.join(' ');
|
68
|
+
};
|
69
|
+
|
70
|
+
/**
|
71
|
+
* Escape the given string of `html`.
|
72
|
+
*
|
73
|
+
* @param {String} html
|
74
|
+
* @return {String}
|
75
|
+
* @api private
|
76
|
+
*/
|
77
|
+
|
78
|
+
exports.escape = function escape(html){
|
79
|
+
return String(html)
|
80
|
+
.replace(/&(?!\w+;)/g, '&')
|
81
|
+
.replace(/</g, '<')
|
82
|
+
.replace(/>/g, '>')
|
83
|
+
.replace(/"/g, '"');
|
84
|
+
};
|
85
|
+
|
86
|
+
/**
|
87
|
+
* Re-throw the given `err` in context to the
|
88
|
+
* the jade in `filename` at the given `lineno`.
|
89
|
+
*
|
90
|
+
* @param {Error} err
|
91
|
+
* @param {String} filename
|
92
|
+
* @param {String} lineno
|
93
|
+
* @api private
|
94
|
+
*/
|
95
|
+
|
96
|
+
exports.rethrow = function rethrow(err, filename, lineno){
|
97
|
+
if (!filename) throw err;
|
98
|
+
|
99
|
+
var context = 3
|
100
|
+
, str = require('fs').readFileSync(filename, 'utf8')
|
101
|
+
, lines = str.split('\n')
|
102
|
+
, start = Math.max(lineno - context, 0)
|
103
|
+
, end = Math.min(lines.length, lineno + context);
|
104
|
+
|
105
|
+
// Error context
|
106
|
+
var context = lines.slice(start, end).map(function(line, i){
|
107
|
+
var curr = i + start + 1;
|
108
|
+
return (curr == lineno ? ' > ' : ' ')
|
109
|
+
+ curr
|
110
|
+
+ '| '
|
111
|
+
+ line;
|
112
|
+
}).join('\n');
|
113
|
+
|
114
|
+
// Alter exception message
|
115
|
+
err.path = filename;
|
116
|
+
err.message = (filename || 'Jade') + ':' + lineno
|
117
|
+
+ '\n' + context + '\n\n' + err.message;
|
118
|
+
throw err;
|
119
|
+
};
|
120
|
+
|
121
|
+
return exports;
|
122
|
+
|
123
|
+
})({});
|
data/lib/jade_js/source.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jade-js-source
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,8 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2011-
|
14
|
-
default_executable:
|
13
|
+
date: 2011-10-07 00:00:00.000000000Z
|
15
14
|
dependencies: []
|
16
15
|
description: ! " Jade is a high performance template engine heavily influenced
|
17
16
|
by Haml \n and implemented with JavaScript for node.\n"
|
@@ -21,8 +20,8 @@ extensions: []
|
|
21
20
|
extra_rdoc_files: []
|
22
21
|
files:
|
23
22
|
- lib/jade_js/jade.js
|
23
|
+
- lib/jade_js/runtime.js
|
24
24
|
- lib/jade_js/source.rb
|
25
|
-
has_rdoc: true
|
26
25
|
homepage: https://github.com/visionmedia/jade
|
27
26
|
licenses: []
|
28
27
|
post_install_message:
|
@@ -43,7 +42,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
43
42
|
version: '0'
|
44
43
|
requirements: []
|
45
44
|
rubyforge_project: jade-js-source
|
46
|
-
rubygems_version: 1.
|
45
|
+
rubygems_version: 1.8.10
|
47
46
|
signing_key:
|
48
47
|
specification_version: 3
|
49
48
|
summary: Jade - template engine
|