jade-js-source 0.15.4 → 0.16.2
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/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
|