Skip to content
3 changes: 2 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1019,7 +1019,8 @@ Lexer.prototype = {
if (!whitespaceRe.test(str[x])) {
// if it is a JavaScript punctuator, then assume that it is
// a part of the value
return !characterParser.isPunctuator(str[x]) || quoteRe.test(str[x]);
// also make exception for spread syntax
return /^\.\.\./.test(str.slice(x)) || !characterParser.isPunctuator(str[x]) || quoteRe.test(str[x]);
}
}
}
Expand Down
29 changes: 29 additions & 0 deletions test/cases/attrs-spread.expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{"type":"tag","line":1,"col":1,"val":"div"}
{"type":"start-attributes","line":1,"col":4}
{"type":"attribute","line":1,"col":5,"name":"...attrs","val":true,"mustEscape":true}
{"type":"end-attributes","line":1,"col":13}
{"type":"newline","line":2,"col":1}
{"type":"tag","line":2,"col":1,"val":"div"}
{"type":"start-attributes","line":2,"col":4}
{"type":"attribute","line":2,"col":5,"name":"...attrs","val":"foo","mustEscape":true}
{"type":"end-attributes","line":2,"col":17}
{"type":"newline","line":3,"col":1}
{"type":"tag","line":3,"col":1,"val":"div"}
{"type":"start-attributes","line":3,"col":4}
{"type":"attribute","line":3,"col":5,"name":"a","val":"'bleh'","mustEscape":true}
{"type":"attribute","line":3,"col":15,"name":"...attrs","val":true,"mustEscape":false}
{"type":"end-attributes","line":3,"col":23}
{"type":"newline","line":4,"col":1}
{"type":"tag","line":4,"col":1,"val":"div"}
{"type":"start-attributes","line":4,"col":4}
{"type":"attribute","line":4,"col":5,"name":"a","val":"'bleh'","mustEscape":true}
{"type":"attribute","line":4,"col":14,"name":"...attrs","val":true,"mustEscape":false}
{"type":"end-attributes","line":4,"col":22}
{"type":"newline","line":5,"col":1}
{"type":"tag","line":5,"col":1,"val":"div"}
{"type":"start-attributes","line":5,"col":4}
{"type":"attribute","line":5,"col":5,"name":"a","val":true,"mustEscape":true}
{"type":"attribute","line":5,"col":7,"name":"...attrs","val":true,"mustEscape":false}
{"type":"end-attributes","line":5,"col":15}
{"type":"newline","line":6,"col":1}
{"type":"eos","line":6,"col":1}
5 changes: 5 additions & 0 deletions test/cases/attrs-spread.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
div(...attrs)
div(...attrs=foo)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a question: what is the foo? Why couldn't one just do (...foo)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thinking was that it could mean you can namespace things: e.g.

div(...data=myDataAttributes)

compiled with:

{myDataAttributes: {foo: 'foo-val', bar: 'bar-val'}}

results in:

<div data-foo="foo-val" data-bar="bar-val"></div>

Probably this is the wrong syntax for that though. I think I would prefer to support something like:

div(data=...myDataAttributes)

or

div(data...=myDataAttributes)

as I think that reads better/more clearly. Probably best to remove support for having a "value" for spread attributes. If we make sure it's a syntax-error for now, we can always add it in later.

div(a='bleh', ...attrs)
div(a='bleh' ...attrs)
div(a ...attrs)
2 changes: 1 addition & 1 deletion test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ fs.readdirSync(dir).forEach(function (testCase) {
if (/\.pug$/.test(testCase)) {
console.dir(testCase);
var expected = fs.readFileSync(dir + testCase.replace(/\.pug$/, '.expected.json'), 'utf8')
.split(/\n/).map(JSON.parse);
.trim().split(/\n/).map(JSON.parse);
var result = lex(fs.readFileSync(dir + testCase, 'utf8'), dir + testCase);
fs.writeFileSync(dir + testCase.replace(/\.pug$/, '.actual.json'),
result.map(JSON.stringify).join('\n'));
Expand Down