Skip to content

Commit

Permalink
JSX: Fix whitespace and escaping of attribute values
Browse files Browse the repository at this point in the history
The behavior is reversed engineer from Babel since the
semantics is not documented in the JSX "spec".

Fixes #2088
  • Loading branch information
arv committed Mar 24, 2016
1 parent c58237a commit 8630c1b
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 0 deletions.
15 changes: 15 additions & 0 deletions src/codegeneration/JsxTransformer.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ import {
JSX_PLACEHOLDER,
JSX_SPREAD_ATTRIBUTE,
JSX_TEXT,
LITERAL_EXPRESSION,
} from '../syntax/trees/ParseTreeType.js';
import {
JsxText,
LiteralExpression,
LiteralPropertyName,
SpreadExpression,
} from '../syntax/trees/ParseTrees.js';
import {LiteralToken} from '../syntax/LiteralToken.js';
import {ParseTreeTransformer} from './ParseTreeTransformer.js';
import {STRING} from '../syntax/TokenType.js';
import {
Expand Down Expand Up @@ -135,6 +137,13 @@ export class JsxTransformer extends ParseTreeTransformer {
let value;
if (tree.value === null) {
value = createTrueLiteral();
} else if (tree.value.type === LITERAL_EXPRESSION) {
const {literalToken} = tree.value;
const v = literalToken.value;
const {location} = literalToken;
const lit =
new LiteralToken(STRING, normalizeAttributeValue(v), location);
value = new LiteralExpression(location, lit);
} else {
value = this.transformAny(tree.value);
}
Expand Down Expand Up @@ -202,3 +211,9 @@ function jsxIdentifierToToken(token) {
}
return createIdentifierToken(value);
}

function normalizeAttributeValue(s) {
return JSON.stringify(
s.slice(1, -1). // remove the quotes
replace(/\n\s+/g, ' '));
}
30 changes: 30 additions & 0 deletions test/feature/JSX/AttributesWhitespace.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Options: --jsx=f

// This file has trailing whitespace. Make sure your editor does not strip
// them.

function f(name, props) {
return props.b;
}

assert.equal(<a b=" c "/>, ' c ');
assert.equal(<a b=" c "/>, ' c ');
assert.equal(<a b="c "/>, 'c ');
assert.equal(<a b="c "/>, 'c ');
assert.equal(<a b="\tc\n"/>, '\\tc\\n');
assert.equal(<a b="'"/>, '\'');
assert.equal(<a b='"'/>, '"');
assert.equal(<a b="&"/>, '&');
assert.equal(<a b='
'/>, '\n');
assert.equal(<a b='
'/>, ' \n');
assert.equal(<a b='
'/>, ' ');
assert.equal(<a b='
'/>, ' ');
assert.equal(<a b='
'/>, ' ');
assert.equal(<a b=' '/>, '\t');

0 comments on commit 8630c1b

Please sign in to comment.