Skip to content

Commit

Permalink
Merge branch 'bugs/text'
Browse files Browse the repository at this point in the history
  • Loading branch information
tj committed Oct 5, 2010
2 parents 5b3bae3 + a6ed2c7 commit eacbba7
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 69 deletions.
19 changes: 15 additions & 4 deletions Readme.md
Expand Up @@ -142,6 +142,17 @@ Actually want `#{}` for some reason? escape it!

now we have `<p>#{something}</p>`

Nested tags that also contain text can optionally use a text block:

label
| Username:
input(name='user[name]')

or immediate tag text:

label Username:
input(name='user[name]')

### Comments

Single line comments currently look the same as JavaScript comments,
Expand Down Expand Up @@ -188,7 +199,7 @@ Jade instruments the compiled JavaScript to provide meaningful context for runti

Invalid indentation, got 2 expected 1.

Note: Trailing are generated on **EOS** (end-of-source) if not present.
Note: Trailing outdents are generated on **EOS** (end-of-source) if not present.

### Attributes

Expand All @@ -208,7 +219,7 @@ Boolean attributes with code will only output the attribute when `true`:

input(type="checkbox", checked: someValue)

Note: Leading / trailing whitespace is _ignore_ for attr pairs.
Note: Leading / trailing whitespace is _ignored_ for attr pairs.

### Doctypes

Expand Down Expand Up @@ -263,8 +274,8 @@ bake conditionals right into jade, we could do so with a filter named _condition
else
p Not so amazing

Not that we no longer prefix with "-" for these code blocks. An example of
how to manipulate the parse tree can be found at _./examples/parsetree.js_.
Not that we no longer prefix with "-" for these code blocks. Examples of
how to manipulate the parse tree can be found at _./examples/conditionals.js_ and _./examples/model.js_. There are several interesting use-cases for this functionality above what was shown above such as transparently aggregating / compressing assets to reduce the number of HTTP requests, transparent record error reporting, and more.

## Code

Expand Down
3 changes: 1 addition & 2 deletions examples/conditionals.js
Expand Up @@ -39,9 +39,8 @@ Visitor.prototype.visit = function(node){
Visitor.prototype.visitTag = function(node){
switch (node.name) {
case 'if':
var condition = node.block[0][0],
var condition = node.text[0],
block = node.block;
block.shift();
if ('?' == condition[condition.length-1]) {
condition = condition.slice(0, -1);
}
Expand Down
16 changes: 7 additions & 9 deletions examples/form.jade
Expand Up @@ -2,21 +2,19 @@ form(method="post")
fieldset
legend General
p
label(for="user[name]")
| Username:
label(for="user[name]") Username:
input(type="text", name="user[name]", value=user.name)
p
label(for="user[email]")
| Email:
label(for="user[email]") Email:
input(type="text", name="user[email]", value=user.email)
| Enter a valid
| email address
| such as <em>tj@vision-media.ca</em>.
.tip
| Enter a valid
| email address
| such as <em>tj@vision-media.ca</em>.
fieldset
legend Location
p
label(for="user[city]")
| City:
label(for="user[city]") City:
input(type="text", name="user[city]", value=user.city)
p
select(name="user[province]")
Expand Down
1 change: 0 additions & 1 deletion examples/form.js
Expand Up @@ -6,7 +6,6 @@
var jade = require('./../lib/jade');

var options = {
pretty: true,
locals: {
user: {
name: 'TJ',
Expand Down
1 change: 0 additions & 1 deletion examples/model.js
Expand Up @@ -9,7 +9,6 @@ var jade = require('./../lib/jade'),
nodes = jade.nodes;

var options = {
pretty: true,
locals: {
user: {
name: 'Tobi',
Expand Down
27 changes: 18 additions & 9 deletions examples/text.jade
@@ -1,10 +1,19 @@
p
| Just some random stuff
| because I dont have to much
| to write here, but my name is #{name}
| and my email is #{email} :)
| .
form
label Username:
input(type='text', name='user[name]')
p
| Just an example of some text usage.
| You can have <em>inline</em> html,
| as well as
strong tags
| .

| Spaces are fine.
| yup....
p another para
| Interpolation is also supported. The
| username is currently "#{name}".

label Email:
input(type='text', name='user[email]')
p
| Email is currently
em= email
| .
25 changes: 5 additions & 20 deletions lib/compiler.js
Expand Up @@ -18,10 +18,6 @@ var nodes = require('./nodes'),
/**
* Initialize `Compiler` with the given `node`.
*
* Options:
*
* - `pretty` prettyify output with proper indentation
*
* @param {Node} node
* @param {Object} options
* @api public
Expand All @@ -30,8 +26,6 @@ var nodes = require('./nodes'),
var Compiler = module.exports = function Compiler(node, options) {
this.options = options = options || {};
this.node = node;
this.pretty = options.pretty;
this.indents = options.indents || 0;
};

/**
Expand Down Expand Up @@ -109,11 +103,9 @@ Compiler.prototype = {
*/

visitBlock: function(block){
++this.indents;
for (var i = 0, len = block.length; i < len; ++i) {
this.visit(block[i]);
}
--this.indents;
},

/**
Expand Down Expand Up @@ -144,30 +136,23 @@ Compiler.prototype = {
visitTag: function(tag){
var name = tag.name;

// Indentation
var indents = this.pretty
? Array(this.indents).join(' ')
: '';

// Newline
var nl = this.pretty ? '\\n' : '';

if (~selfClosing.indexOf(name)) {
this.buffer(nl + indents + '<' + name);
this.buffer('<' + name);
this.visitAttributes(tag.attrs);
this.terse
? this.buffer('>')
: this.buffer('/>');
} else {
// Optimize attributes buffering
if (tag.attrs.length) {
this.buffer(nl + indents + '<' + name);
this.buffer('<' + name);
if (tag.attrs.length) this.visitAttributes(tag.attrs);
this.buffer('>');
} else {
this.buffer(nl + indents + '<' + name + '>');
this.buffer('<' + name + '>');
}
if (tag.code) this.visitCode(tag.code);
if (tag.text) this.buffer(utils.text(tag.text));
this.visit(tag.block);
this.buffer('</' + name + '>');
}
Expand Down Expand Up @@ -198,7 +183,7 @@ Compiler.prototype = {
*/

visitText: function(text){
this.buffer(utils.text(text));
this.buffer(utils.text(text, true));
},

/**
Expand Down
10 changes: 7 additions & 3 deletions lib/parser.js
Expand Up @@ -102,7 +102,11 @@ Parser.prototype = {
var block = new nodes.Block;
block.line = this.line;
while (this.peek.type !== 'eos') {
block.push(this.parseExpr());
if (this.peek.type === 'newline') {
this.advance;
} else {
block.push(this.parseExpr());
}
}
return block;
},
Expand Down Expand Up @@ -252,7 +256,7 @@ Parser.prototype = {
},

/**
* indent (text |newline)* outdent
* indent (text | newline)* outdent
*/

parseTextBlock: function(){
Expand Down Expand Up @@ -324,7 +328,7 @@ Parser.prototype = {
// (text | code)?
switch (this.peek.type) {
case 'text':
tag.block.push(this.parseText());
tag.text = this.parseText();
break;
case 'code':
tag.code = this.parseCode();
Expand Down
4 changes: 2 additions & 2 deletions lib/utils.js
Expand Up @@ -41,6 +41,6 @@ var escape = exports.escape = function(str) {
* @api private
*/

exports.text = function(node){
return interpolate(escape(node.join('\\n').trimLeft()));
exports.text = function(node, newline){
return interpolate(escape(node.join('\\n').trimLeft() + (newline ? '\\n' : '')));
};
3 changes: 1 addition & 2 deletions test/filters.test.js
Expand Up @@ -27,9 +27,8 @@ Visitor.prototype.visitTag = function(node){
switch (node.name) {
case 'if':
// First text -> line
var condition = node.block[0][0],
var condition = node.text[0],
block = node.block;
block.shift();
node = new nodes.Code('if (' + condition + ')');
node.block = block;
this.visit(node);
Expand Down
33 changes: 17 additions & 16 deletions test/jade.test.js
Expand Up @@ -74,7 +74,7 @@ module.exports = {

'test single quotes': function(assert){
assert.equal("<p>'foo'</p>", render("p 'foo'"));
assert.equal("<p>'foo'</p>", render("p\n | 'foo'"));
assert.equal("<p>'foo'\n</p>", render("p\n | 'foo'"));
assert.equal('<a href="/foo"></a>', render("- var path = 'foo';\na(href='/' + path)"));
},

Expand Down Expand Up @@ -141,7 +141,7 @@ module.exports = {
' | baz'
].join('\n');

assert.equal('<a href="#">foo bar baz</a>', render(str));
assert.equal('<a href="#">foo \nbar \nbaz\n</a>', render(str));

var str = [
'ul',
Expand All @@ -154,7 +154,7 @@ module.exports = {
var html = [
'<ul>',
'<li>one</li>',
'<ul>two',
'<ul>two\n',
'<li>three</li>',
'</ul>',
'</ul>'
Expand Down Expand Up @@ -272,7 +272,7 @@ module.exports = {

assert.equal(html, render(str));
assert.equal('<foo></foo>something<bar></bar>', render('foo\n= "something"\nbar'));
assert.equal('<foo></foo>"something"<bar></bar>', render('foo\n"something"\nbar'));
assert.equal('<foo></foo>"something"\n<bar></bar>', render('foo\n"something"\nbar'));
assert.equal('<foo></foo>something<bar></bar>else', render('foo\n= "something"\nbar\n= "else"'));
},

Expand All @@ -291,31 +291,32 @@ module.exports = {
},

'test text': function(assert){
assert.equal('foobarbaz', render('| foo\n| bar\n| baz'));
assert.equal('foo bar baz', render('| foo \n| bar \n| baz'));
assert.equal('(hey)', render('| (hey)'));
assert.equal('foo\nbar\nbaz\n', render('| foo\n| bar\n| baz'));
assert.equal('foo \nbar \nbaz\n', render('| foo \n| bar \n| baz'));
assert.equal('(hey)\n', render('| (hey)'));
},

'test tag text': function(assert){
assert.equal('some random text', render('| some random text'));
assert.equal('some random text\n', render('| some random text'));
assert.equal('<p>some random text</p>', render('p some random text'));
assert.equal('<p>(parens)</p>', render('p (parens)'));
// assert.equal('<p>(parens)</p>', render('p (parens)'));
//assert.equal('<p foo="bar">(parens)</p>', render('p(foo="bar") (parens)'));
},

'test tag text block': function(assert){
assert.equal('<p>foo bar baz</p>', render('p\n | foo \n | bar \n | baz'));
assert.equal('<label>Password:<input/></label>', render('label\n | Password:\n input'));
assert.equal('<p>foo \nbar \nbaz\n</p>', render('p\n | foo \n | bar \n | baz'));
assert.equal('<label>Password:\n<input/></label>', render('label\n | Password:\n input'));
assert.equal('<label>Password:<input/></label>', render('label Password:\n input'));
},

'test tag text interpolation': function(assert){
assert.equal('yo, jade is cool', render('| yo, #{name} is cool', { locals: { name: 'jade' }}));
assert.equal('yo, jade is cool', render('| yo, ${name} is cool', { locals: { name: 'jade' }}));
assert.equal('yo, jade is cool\n', render('| yo, #{name} is cool\n', { locals: { name: 'jade' }}));
assert.equal('yo, jade is cool\n', render('| yo, ${name} is cool\n', { locals: { name: 'jade' }}));
assert.equal('<p>yo, jade is cool</p>', render('p yo, #{name} is cool', { locals: { name: 'jade' }}));
assert.equal('<p>yo, jade is cool</p>', render('p yo, ${name} is cool', { locals: { name: 'jade' }}));
assert.equal('yo, jade is cool', render('| yo, #{name || "jade"} is cool', { locals: { name: null }}));
assert.equal('yo, \'jade\' is cool', render('| yo, #{name || "\'jade\'"} is cool', { locals: { name: null }}));
assert.equal('yo, jade is cool', render('| yo, ${name || \'jade\'} is cool', { locals: { name: null }}));
assert.equal('yo, jade is cool\n', render('| yo, #{name || "jade"} is cool', { locals: { name: null }}));
assert.equal('yo, \'jade\' is cool\n', render('| yo, #{name || "\'jade\'"} is cool', { locals: { name: null }}));
assert.equal('yo, jade is cool\n', render('| yo, ${name || \'jade\'} is cool', { locals: { name: null }}));
},

'test invalid indentation multiple': function(assert){
Expand Down

0 comments on commit eacbba7

Please sign in to comment.