1
0
Fork 0
mirror of https://github.com/jashkenas/coffeescript.git synced 2022-11-09 12:23:24 -05:00

[CS2] CSX spread attributes: <div {props…} /> (#4607)

* CSX spread attributes: <div {props...} />

* whitespace cleanup

* Style

* valid CSX attributes

* added comments; cleanup

* Fixed allowed CSX properties.

* Cleanup

* Typo

* Improved RegEx

* Reworked CSX attributes

* small fix for CSX attribute validation

* cleanup

* tests

* fix nested assignement; remove unused variable

* cleanup; improve tests

* fix esoteric case; improve tracking nested splats in CSX tag
This commit is contained in:
zdenko 2017-08-03 06:00:39 +02:00 committed by Geoffrey Booth
parent a118ec7cc9
commit cbf035fca9
7 changed files with 351 additions and 420 deletions

View file

@ -1670,7 +1670,7 @@
}
compileCSX(o) {
var attributes, content, fragments, tag;
var attr, attrProps, attributes, content, fragments, j, len1, obj, ref1, tag;
[attributes, content] = this.args;
attributes.base.csx = true;
if (content != null) {
@ -1678,7 +1678,23 @@
}
fragments = [this.makeCode('<')];
fragments.push(...(tag = this.variable.compileToFragments(o, LEVEL_ACCESS)));
fragments.push(...attributes.compileToFragments(o, LEVEL_PAREN));
if (attributes.base instanceof Arr) {
ref1 = attributes.base.objects;
for (j = 0, len1 = ref1.length; j < len1; j++) {
obj = ref1[j];
attr = obj.base;
attrProps = (attr != null ? attr.properties : void 0) || [];
// Catch invalid CSX attributes: <div {a:"b", props} {props} "value" />
if (!(attr instanceof Obj || attr instanceof IdentifierLiteral) || (attr instanceof Obj && !attr.generated && (attrProps.length > 1 || !(attrProps[0] instanceof Splat)))) {
obj.error("Unexpected token. Allowed CSX attributes are: id=\"val\", src={source}, {props...} or attribute.");
}
if (obj.base instanceof Obj) {
obj.base.csx = true;
}
fragments.push(this.makeCode(' '));
fragments.push(...obj.compileToFragments(o, LEVEL_PAREN));
}
}
if (content) {
fragments.push(this.makeCode('>'));
fragments.push(...content.compileNode(o, LEVEL_LIST));
@ -2109,12 +2125,16 @@
}
}
}
if (this.hasSplat()) {
if (this.hasSplat() && !this.csx) {
// Object spread properties. https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md
return this.compileSpread(o);
}
idt = o.indent += TAB;
lastNode = this.lastNode(this.properties);
if (this.csx) {
// CSX attributes <div id="val" attr={aaa} {props...} />
return this.compileCSXAttributes(o);
}
// If this object is the left-hand side of an assignment, all its children
// are too.
if (this.lhs) {
@ -2136,7 +2156,7 @@
ref1 = this.properties;
for (l = 0, len3 = ref1.length; l < len3; l++) {
prop = ref1[l];
if (prop instanceof Assign && prop.context === 'object' && !this.csx) {
if (prop instanceof Assign && prop.context === 'object') {
isCompact = false;
}
}
@ -2144,7 +2164,7 @@
answer.push(this.makeCode(isCompact ? '' : '\n'));
for (i = q = 0, len4 = props.length; q < len4; i = ++q) {
prop = props[i];
join = i === props.length - 1 ? '' : isCompact && this.csx ? ' ' : isCompact ? ', ' : prop === lastNode || this.csx ? '\n' : ',\n';
join = i === props.length - 1 ? '' : isCompact ? ', ' : prop === lastNode ? '\n' : ',\n';
indent = isCompact ? '' : idt;
key = prop instanceof Assign && prop.context === 'object' ? prop.variable : prop instanceof Assign ? (!this.lhs ? prop.operatorToken.error(`unexpected ${prop.operatorToken.value}`) : void 0, prop.variable) : prop;
if (key instanceof Value && key.hasProperties()) {
@ -2168,21 +2188,13 @@
if (indent) {
answer.push(this.makeCode(indent));
}
if (this.csx) {
prop.csx = true;
}
if (this.csx && i === 0) {
answer.push(this.makeCode(' '));
}
answer.push(...prop.compileToFragments(o, LEVEL_TOP));
if (join) {
answer.push(this.makeCode(join));
}
}
answer.push(this.makeCode(isCompact ? '' : `\n${this.tab}`));
if (!this.csx) {
answer = this.wrapInBraces(answer);
}
answer = this.wrapInBraces(answer);
if (this.front) {
return this.wrapInParentheses(answer);
} else {
@ -2256,6 +2268,27 @@
return (new Call(new Literal('Object.assign'), slices)).compileToFragments(o);
}
compileCSXAttributes(o) {
var answer, i, j, join, len1, prop, props;
props = this.properties;
answer = [];
for (i = j = 0, len1 = props.length; j < len1; i = ++j) {
prop = props[i];
prop.csx = true;
join = i === props.length - 1 ? '' : ' ';
if (prop instanceof Splat) {
prop = new Literal(`{${prop.compile(o)}}`);
}
answer.push(...prop.compileToFragments(o, LEVEL_TOP));
answer.push(this.makeCode(join));
}
if (this.front) {
return this.wrapInParentheses(answer);
} else {
return answer;
}
}
};
Obj.prototype.children = ['properties'];