AST: "CSX" -> "JSX" (#5188)
* updated grammar * restore JSXIdentifier::astType()
This commit is contained in:
parent
0c2d3673d3
commit
28a1a1d304
|
@ -162,13 +162,13 @@
|
||||||
function() {
|
function() {
|
||||||
return new IdentifierLiteral($1);
|
return new IdentifierLiteral($1);
|
||||||
}),
|
}),
|
||||||
o('CSX_TAG',
|
o('JSX_TAG',
|
||||||
function() {
|
function() {
|
||||||
var ref,
|
var ref,
|
||||||
ref1,
|
ref1,
|
||||||
ref2,
|
ref2,
|
||||||
ref3;
|
ref3;
|
||||||
return new CSXTag($1.toString(),
|
return new JSXTag($1.toString(),
|
||||||
{
|
{
|
||||||
tagNameLocationData: $1.tagNameToken[2],
|
tagNameLocationData: $1.tagNameToken[2],
|
||||||
closingTagOpeningBracketLocationData: (ref = $1.closingTagOpeningBracketToken) != null ? ref[2] : void 0,
|
closingTagOpeningBracketLocationData: (ref = $1.closingTagOpeningBracketToken) != null ? ref[2] : void 0,
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
// where locationData is {first_line, first_column, last_line, last_column, last_line_exclusive, last_column_exclusive}, which is a
|
// where locationData is {first_line, first_column, last_line, last_column, last_line_exclusive, last_column_exclusive}, which is a
|
||||||
// format that can be fed directly into [Jison](https://github.com/zaach/jison). These
|
// format that can be fed directly into [Jison](https://github.com/zaach/jison). These
|
||||||
// are read by jison in the `parser.lexer` function defined in coffeescript.coffee.
|
// are read by jison in the `parser.lexer` function defined in coffeescript.coffee.
|
||||||
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARABLE_LEFT_SIDE, COMPARE, COMPOUND_ASSIGN, CSX_ATTRIBUTE, CSX_FRAGMENT_IDENTIFIER, CSX_IDENTIFIER, CSX_INTERPOLATION, HERECOMMENT_ILLEGAL, HEREDOC_DOUBLE, HEREDOC_INDENT, HEREDOC_SINGLE, HEREGEX, HERE_JSTOKEN, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, INSIDE_CSX, INVERSES, JSTOKEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, Lexer, MATH, MULTI_DENT, NOT_REGEX, NUMBER, OPERATOR, POSSIBLY_DIVISION, REGEX, REGEX_FLAGS, REGEX_ILLEGAL, REGEX_INVALID_ESCAPE, RELATION, RESERVED, Rewriter, SHIFT, STRICT_PROSCRIBED, STRING_DOUBLE, STRING_INVALID_ESCAPE, STRING_SINGLE, STRING_START, TRAILING_SPACES, UNARY, UNARY_MATH, UNFINISHED, VALID_FLAGS, WHITESPACE, addTokenData, attachCommentsToNode, compact, count, invertLiterate, isForFrom, isUnassignable, key, locationDataToString, merge, repeat, replaceUnicodeCodePointEscapes, starts, throwSyntaxError,
|
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARABLE_LEFT_SIDE, COMPARE, COMPOUND_ASSIGN, HERECOMMENT_ILLEGAL, HEREDOC_DOUBLE, HEREDOC_INDENT, HEREDOC_SINGLE, HEREGEX, HERE_JSTOKEN, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, INSIDE_JSX, INVERSES, JSTOKEN, JSX_ATTRIBUTE, JSX_FRAGMENT_IDENTIFIER, JSX_IDENTIFIER, JSX_INTERPOLATION, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, Lexer, MATH, MULTI_DENT, NOT_REGEX, NUMBER, OPERATOR, POSSIBLY_DIVISION, REGEX, REGEX_FLAGS, REGEX_ILLEGAL, REGEX_INVALID_ESCAPE, RELATION, RESERVED, Rewriter, SHIFT, STRICT_PROSCRIBED, STRING_DOUBLE, STRING_INVALID_ESCAPE, STRING_SINGLE, STRING_START, TRAILING_SPACES, UNARY, UNARY_MATH, UNFINISHED, VALID_FLAGS, WHITESPACE, addTokenData, attachCommentsToNode, compact, count, invertLiterate, isForFrom, isUnassignable, key, locationDataToString, merge, repeat, replaceUnicodeCodePointEscapes, starts, throwSyntaxError,
|
||||||
indexOf = [].indexOf,
|
indexOf = [].indexOf,
|
||||||
slice = [].slice;
|
slice = [].slice;
|
||||||
|
|
||||||
|
@ -58,8 +58,8 @@
|
||||||
this.seenExport = false; // Used to recognize `EXPORT FROM? AS?` tokens.
|
this.seenExport = false; // Used to recognize `EXPORT FROM? AS?` tokens.
|
||||||
this.importSpecifierList = false; // Used to identify when in an `IMPORT {...} FROM? ...`.
|
this.importSpecifierList = false; // Used to identify when in an `IMPORT {...} FROM? ...`.
|
||||||
this.exportSpecifierList = false; // Used to identify when in an `EXPORT {...} FROM? ...`.
|
this.exportSpecifierList = false; // Used to identify when in an `EXPORT {...} FROM? ...`.
|
||||||
this.csxDepth = 0; // Used to optimize CSX checks, how deep in CSX we are.
|
this.jsxDepth = 0; // Used to optimize JSX checks, how deep in JSX we are.
|
||||||
this.csxObjAttribute = {}; // Used to detect if CSX attributes is wrapped in {} (<div {props...} />).
|
this.jsxObjAttribute = {}; // Used to detect if JSX attributes is wrapped in {} (<div {props...} />).
|
||||||
this.chunkLine = opts.line || 0; // The start line for the current @chunk.
|
this.chunkLine = opts.line || 0; // The start line for the current @chunk.
|
||||||
this.chunkColumn = opts.column || 0; // The start column of the current @chunk.
|
this.chunkColumn = opts.column || 0; // The start column of the current @chunk.
|
||||||
this.chunkOffset = opts.offset || 0; // The start offset for the current @chunk.
|
this.chunkOffset = opts.offset || 0; // The start offset for the current @chunk.
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
// `@literalToken` is the fallback catch-all.
|
// `@literalToken` is the fallback catch-all.
|
||||||
i = 0;
|
i = 0;
|
||||||
while (this.chunk = code.slice(i)) {
|
while (this.chunk = code.slice(i)) {
|
||||||
consumed = this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.stringToken() || this.numberToken() || this.csxToken() || this.regexToken() || this.jsToken() || this.literalToken();
|
consumed = this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.stringToken() || this.numberToken() || this.jsxToken() || this.regexToken() || this.jsToken() || this.literalToken();
|
||||||
// Update position.
|
// Update position.
|
||||||
[this.chunkLine, this.chunkColumn, this.chunkOffset] = this.getLineAndColumnFromChunk(consumed);
|
[this.chunkLine, this.chunkColumn, this.chunkOffset] = this.getLineAndColumnFromChunk(consumed);
|
||||||
i += consumed;
|
i += consumed;
|
||||||
|
@ -119,9 +119,9 @@
|
||||||
// referenced as property names here, so you can still do `jQuery.is()` even
|
// referenced as property names here, so you can still do `jQuery.is()` even
|
||||||
// though `is` means `===` otherwise.
|
// though `is` means `===` otherwise.
|
||||||
identifierToken() {
|
identifierToken() {
|
||||||
var alias, colon, colonOffset, colonToken, id, idLength, inCSXTag, input, match, poppedToken, prev, prevprev, ref, ref1, ref10, ref11, ref12, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, regExSuper, regex, sup, tag, tagToken, tokenData;
|
var alias, colon, colonOffset, colonToken, id, idLength, inJSXTag, input, match, poppedToken, prev, prevprev, ref, ref1, ref10, ref11, ref12, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, regExSuper, regex, sup, tag, tagToken, tokenData;
|
||||||
inCSXTag = this.atCSXTag();
|
inJSXTag = this.atJSXTag();
|
||||||
regex = inCSXTag ? CSX_ATTRIBUTE : IDENTIFIER;
|
regex = inJSXTag ? JSX_ATTRIBUTE : IDENTIFIER;
|
||||||
if (!(match = regex.exec(this.chunk))) {
|
if (!(match = regex.exec(this.chunk))) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -263,16 +263,16 @@
|
||||||
[tagToken[2].first_line, tagToken[2].first_column, tagToken[2].range[0]] = [poppedToken[2].first_line, poppedToken[2].first_column, poppedToken[2].range[0]];
|
[tagToken[2].first_line, tagToken[2].first_column, tagToken[2].range[0]] = [poppedToken[2].first_line, poppedToken[2].first_column, poppedToken[2].range[0]];
|
||||||
}
|
}
|
||||||
if (colon) {
|
if (colon) {
|
||||||
colonOffset = input.lastIndexOf(inCSXTag ? '=' : ':');
|
colonOffset = input.lastIndexOf(inJSXTag ? '=' : ':');
|
||||||
colonToken = this.token(':', ':', {
|
colonToken = this.token(':', ':', {
|
||||||
offset: colonOffset,
|
offset: colonOffset,
|
||||||
length: colon.length
|
length: colon.length
|
||||||
});
|
});
|
||||||
if (inCSXTag) { // used by rewriter
|
if (inJSXTag) { // used by rewriter
|
||||||
colonToken.csxColon = true;
|
colonToken.jsxColon = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inCSXTag && tag === 'IDENTIFIER' && prev[0] !== ':') {
|
if (inJSXTag && tag === 'IDENTIFIER' && prev[0] !== ':') {
|
||||||
this.token(',', ',', {
|
this.token(',', ',', {
|
||||||
length: 0,
|
length: 0,
|
||||||
origin: tagToken
|
origin: tagToken
|
||||||
|
@ -386,7 +386,7 @@
|
||||||
delimiter: quote
|
delimiter: quote
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
if (this.atCSXTag()) {
|
if (this.atJSXTag()) {
|
||||||
this.token(',', ',', {
|
this.token(',', ',', {
|
||||||
length: 0,
|
length: 0,
|
||||||
origin: this.prev
|
origin: this.prev
|
||||||
|
@ -771,16 +771,15 @@
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CSX is like JSX but for CoffeeScript.
|
jsxToken() {
|
||||||
csxToken() {
|
var afterTag, end, endToken, firstChar, fullId, fullTagName, id, input, j, jsxTag, len, match, offset, openingTagToken, prev, prevChar, properties, property, ref, tagToken, token, tokens;
|
||||||
var afterTag, csxTag, end, endToken, firstChar, fullId, fullTagName, id, input, j, len, match, offset, openingTagToken, prev, prevChar, properties, property, ref, tagToken, token, tokens;
|
|
||||||
firstChar = this.chunk[0];
|
firstChar = this.chunk[0];
|
||||||
// Check the previous token to detect if attribute is spread.
|
// Check the previous token to detect if attribute is spread.
|
||||||
prevChar = this.tokens.length > 0 ? this.tokens[this.tokens.length - 1][0] : '';
|
prevChar = this.tokens.length > 0 ? this.tokens[this.tokens.length - 1][0] : '';
|
||||||
if (firstChar === '<') {
|
if (firstChar === '<') {
|
||||||
match = CSX_IDENTIFIER.exec(this.chunk.slice(1)) || CSX_FRAGMENT_IDENTIFIER.exec(this.chunk.slice(1));
|
match = JSX_IDENTIFIER.exec(this.chunk.slice(1)) || JSX_FRAGMENT_IDENTIFIER.exec(this.chunk.slice(1));
|
||||||
// Not the right hand side of an unspaced comparison (i.e. `a<b`).
|
// Not the right hand side of an unspaced comparison (i.e. `a<b`).
|
||||||
if (!(match && (this.csxDepth > 0 || !(prev = this.prev()) || prev.spaced || (ref = prev[0], indexOf.call(COMPARABLE_LEFT_SIDE, ref) < 0)))) {
|
if (!(match && (this.jsxDepth > 0 || !(prev = this.prev()) || prev.spaced || (ref = prev[0], indexOf.call(COMPARABLE_LEFT_SIDE, ref) < 0)))) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
[input, id] = match;
|
[input, id] = match;
|
||||||
|
@ -790,7 +789,7 @@
|
||||||
} else {
|
} else {
|
||||||
properties = [];
|
properties = [];
|
||||||
}
|
}
|
||||||
tagToken = this.token('CSX_TAG', id, {
|
tagToken = this.token('JSX_TAG', id, {
|
||||||
length: id.length + 1,
|
length: id.length + 1,
|
||||||
data: {
|
data: {
|
||||||
openingBracketToken: this.makeToken('<', '<'),
|
openingBracketToken: this.makeToken('<', '<'),
|
||||||
|
@ -819,9 +818,9 @@
|
||||||
name: id,
|
name: id,
|
||||||
properties
|
properties
|
||||||
});
|
});
|
||||||
this.csxDepth++;
|
this.jsxDepth++;
|
||||||
return fullId.length + 1;
|
return fullId.length + 1;
|
||||||
} else if (csxTag = this.atCSXTag()) {
|
} else if (jsxTag = this.atJSXTag()) {
|
||||||
if (this.chunk.slice(0, 2) === '/>') { // Self-closing tag.
|
if (this.chunk.slice(0, 2) === '/>') { // Self-closing tag.
|
||||||
this.pair('/>');
|
this.pair('/>');
|
||||||
this.token(']', ']', {
|
this.token(']', ']', {
|
||||||
|
@ -838,15 +837,15 @@
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.csxDepth--;
|
this.jsxDepth--;
|
||||||
return 2;
|
return 2;
|
||||||
} else if (firstChar === '{') {
|
} else if (firstChar === '{') {
|
||||||
if (prevChar === ':') {
|
if (prevChar === ':') {
|
||||||
token = this.token('(', '(');
|
token = this.token('(', '(');
|
||||||
this.csxObjAttribute[this.csxDepth] = false;
|
this.jsxObjAttribute[this.jsxDepth] = false;
|
||||||
} else {
|
} else {
|
||||||
token = this.token('{', '{');
|
token = this.token('{', '{');
|
||||||
this.csxObjAttribute[this.csxDepth] = true;
|
this.jsxObjAttribute[this.jsxDepth] = true;
|
||||||
}
|
}
|
||||||
this.ends.push({
|
this.ends.push({
|
||||||
tag: '}',
|
tag: '}',
|
||||||
|
@ -870,7 +869,7 @@
|
||||||
({
|
({
|
||||||
tokens,
|
tokens,
|
||||||
index: end
|
index: end
|
||||||
} = this.matchWithInterpolations(INSIDE_CSX, '>', '</', CSX_INTERPOLATION));
|
} = this.matchWithInterpolations(INSIDE_JSX, '>', '</', JSX_INTERPOLATION));
|
||||||
this.mergeInterpolationTokens(tokens, {
|
this.mergeInterpolationTokens(tokens, {
|
||||||
endOffset: end
|
endOffset: end
|
||||||
}, (value) => {
|
}, (value) => {
|
||||||
|
@ -878,10 +877,10 @@
|
||||||
delimiter: '>'
|
delimiter: '>'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
match = CSX_IDENTIFIER.exec(this.chunk.slice(end)) || CSX_FRAGMENT_IDENTIFIER.exec(this.chunk.slice(end));
|
match = JSX_IDENTIFIER.exec(this.chunk.slice(end)) || JSX_FRAGMENT_IDENTIFIER.exec(this.chunk.slice(end));
|
||||||
if (!match || match[1] !== `${csxTag.name}${((function() {
|
if (!match || match[1] !== `${jsxTag.name}${((function() {
|
||||||
var k, len1, ref1, results;
|
var k, len1, ref1, results;
|
||||||
ref1 = csxTag.properties;
|
ref1 = jsxTag.properties;
|
||||||
results = [];
|
results = [];
|
||||||
for (k = 0, len1 = ref1.length; k < len1; k++) {
|
for (k = 0, len1 = ref1.length; k < len1; k++) {
|
||||||
property = ref1[k];
|
property = ref1[k];
|
||||||
|
@ -889,7 +888,7 @@
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
})()).join('')}`) {
|
})()).join('')}`) {
|
||||||
this.error(`expected corresponding CSX closing tag for ${csxTag.name}`, csxTag.origin.data.tagNameToken[2]);
|
this.error(`expected corresponding JSX closing tag for ${jsxTag.name}`, jsxTag.origin.data.tagNameToken[2]);
|
||||||
}
|
}
|
||||||
[, fullTagName] = match;
|
[, fullTagName] = match;
|
||||||
afterTag = end + fullTagName.length;
|
afterTag = end + fullTagName.length;
|
||||||
|
@ -922,17 +921,17 @@
|
||||||
});
|
});
|
||||||
// make the closing tag location data more easily accessible to the grammar
|
// make the closing tag location data more easily accessible to the grammar
|
||||||
addTokenData(openingTagToken, endToken.data);
|
addTokenData(openingTagToken, endToken.data);
|
||||||
this.csxDepth--;
|
this.jsxDepth--;
|
||||||
return afterTag + 1;
|
return afterTag + 1;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else if (this.atCSXTag(1)) {
|
} else if (this.atJSXTag(1)) {
|
||||||
if (firstChar === '}') {
|
if (firstChar === '}') {
|
||||||
this.pair(firstChar);
|
this.pair(firstChar);
|
||||||
if (this.csxObjAttribute[this.csxDepth]) {
|
if (this.jsxObjAttribute[this.jsxDepth]) {
|
||||||
this.token('}', '}');
|
this.token('}', '}');
|
||||||
this.csxObjAttribute[this.csxDepth] = false;
|
this.jsxObjAttribute[this.jsxDepth] = false;
|
||||||
} else {
|
} else {
|
||||||
this.token(')', ')');
|
this.token(')', ')');
|
||||||
}
|
}
|
||||||
|
@ -946,9 +945,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
atCSXTag(depth = 0) {
|
atJSXTag(depth = 0) {
|
||||||
var i, last, ref;
|
var i, last, ref;
|
||||||
if (this.csxDepth === 0) {
|
if (this.jsxDepth === 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
i = this.ends.length - 1;
|
i = this.ends.length - 1;
|
||||||
|
@ -1132,9 +1131,9 @@
|
||||||
// `#{` if interpolations are desired).
|
// `#{` if interpolations are desired).
|
||||||
// - `delimiter` is the delimiter of the token. Examples are `'`, `"`, `'''`,
|
// - `delimiter` is the delimiter of the token. Examples are `'`, `"`, `'''`,
|
||||||
// `"""` and `///`.
|
// `"""` and `///`.
|
||||||
// - `closingDelimiter` is different from `delimiter` only in CSX
|
// - `closingDelimiter` is different from `delimiter` only in JSX
|
||||||
// - `interpolators` matches the start of an interpolation, for CSX it's both
|
// - `interpolators` matches the start of an interpolation, for JSX it's both
|
||||||
// `{` and `<` (i.e. nested CSX tag)
|
// `{` and `<` (i.e. nested JSX tag)
|
||||||
|
|
||||||
// This method allows us to have strings within interpolations within strings,
|
// This method allows us to have strings within interpolations within strings,
|
||||||
// ad infinitum.
|
// ad infinitum.
|
||||||
|
@ -1600,13 +1599,13 @@
|
||||||
// Token matching regexes.
|
// Token matching regexes.
|
||||||
IDENTIFIER = /^(?!\d)((?:(?!\s)[$\w\x7f-\uffff])+)([^\n\S]*:(?!:))?/; // Is this a property name?
|
IDENTIFIER = /^(?!\d)((?:(?!\s)[$\w\x7f-\uffff])+)([^\n\S]*:(?!:))?/; // Is this a property name?
|
||||||
|
|
||||||
CSX_IDENTIFIER = /^(?![\d<])((?:(?!\s)[\.\-$\w\x7f-\uffff])+)/; // Must not start with `<`.
|
JSX_IDENTIFIER = /^(?![\d<])((?:(?!\s)[\.\-$\w\x7f-\uffff])+)/; // Must not start with `<`.
|
||||||
// Like `IDENTIFIER`, but includes `-`s and `.`s.
|
// Like `IDENTIFIER`, but includes `-`s and `.`s.
|
||||||
|
|
||||||
// Fragment: <></>
|
// Fragment: <></>
|
||||||
CSX_FRAGMENT_IDENTIFIER = /^()>/; // Ends immediately with `>`.
|
JSX_FRAGMENT_IDENTIFIER = /^()>/; // Ends immediately with `>`.
|
||||||
|
|
||||||
CSX_ATTRIBUTE = /^(?!\d)((?:(?!\s)[\-$\w\x7f-\uffff])+)([^\S]*=(?!=))?/; // Like `IDENTIFIER`, but includes `-`s.
|
JSX_ATTRIBUTE = /^(?!\d)((?:(?!\s)[\-$\w\x7f-\uffff])+)([^\S]*=(?!=))?/; // Like `IDENTIFIER`, but includes `-`s.
|
||||||
// Is this an attribute with a value?
|
// Is this an attribute with a value?
|
||||||
|
|
||||||
NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i; // binary
|
NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i; // binary
|
||||||
|
@ -1645,11 +1644,11 @@
|
||||||
|
|
||||||
HEREDOC_DOUBLE = /^(?:[^\\"#]|\\[\s\S]|"(?!"")|\#(?!\{))*/;
|
HEREDOC_DOUBLE = /^(?:[^\\"#]|\\[\s\S]|"(?!"")|\#(?!\{))*/;
|
||||||
|
|
||||||
INSIDE_CSX = /^(?:[^\{<])*/; // Start of CoffeeScript interpolation. // Similar to `HEREDOC_DOUBLE` but there is no escaping.
|
INSIDE_JSX = /^(?:[^\{<])*/; // Start of CoffeeScript interpolation. // Similar to `HEREDOC_DOUBLE` but there is no escaping.
|
||||||
// Maybe CSX tag (`<` not allowed even if bare).
|
// Maybe JSX tag (`<` not allowed even if bare).
|
||||||
|
|
||||||
CSX_INTERPOLATION = /^(?:\{|<(?!\/))/; // CoffeeScript interpolation.
|
JSX_INTERPOLATION = /^(?:\{|<(?!\/))/; // CoffeeScript interpolation.
|
||||||
// CSX opening tag.
|
// JSX opening tag.
|
||||||
|
|
||||||
HEREDOC_INDENT = /\n+([^\n\S]*)(?=\S)/g;
|
HEREDOC_INDENT = /\n+([^\n\S]*)(?=\S)/g;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// nodes are created as the result of actions in the [grammar](grammar.html),
|
// nodes are created as the result of actions in the [grammar](grammar.html),
|
||||||
// but some are created by other nodes as a method of code generation. To convert
|
// but some are created by other nodes as a method of code generation. To convert
|
||||||
// the syntax tree into a string of JavaScript code, call `compile()` on the root.
|
// the syntax tree into a string of JavaScript code, call `compile()` on the root.
|
||||||
var Access, Arr, Assign, AwaitReturn, Base, Block, BooleanLiteral, CSXAttribute, CSXAttributes, CSXElement, CSXEmptyExpression, CSXExpressionContainer, CSXIdentifier, CSXTag, CSXText, Call, Catch, Class, Code, CodeFragment, ComputedPropertyName, DefaultLiteral, DynamicImport, DynamicImportCall, Elision, ExecutableClassBody, Existence, Expansion, ExportAllDeclaration, ExportDeclaration, ExportDefaultDeclaration, ExportNamedDeclaration, ExportSpecifier, ExportSpecifierList, Extends, For, FuncDirectiveReturn, FuncGlyph, HEREGEX_OMIT, HereComment, HoistTarget, IdentifierLiteral, If, ImportClause, ImportDeclaration, ImportDefaultSpecifier, ImportNamespaceSpecifier, ImportSpecifier, ImportSpecifierList, In, Index, InfinityLiteral, Interpolation, JS_FORBIDDEN, LEADING_BLANK_LINE, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, LineComment, Literal, MetaProperty, ModuleDeclaration, ModuleSpecifier, ModuleSpecifierList, NEGATE, NO, NaNLiteral, NullLiteral, NumberLiteral, Obj, ObjectProperty, Op, Param, Parens, PassthroughLiteral, PropertyName, Range, RegexLiteral, RegexWithInterpolations, Return, Root, SIMPLENUM, SIMPLE_STRING_OMIT, STRING_OMIT, Scope, Slice, Splat, StatementLiteral, StringLiteral, StringWithInterpolations, Super, SuperCall, Switch, SwitchCase, SwitchWhen, TAB, THIS, TRAILING_BLANK_LINE, TaggedTemplateCall, TemplateElement, ThisLiteral, Throw, Try, UTILITIES, UndefinedLiteral, Value, While, YES, YieldReturn, addDataToNode, attachCommentsToNode, compact, del, ends, extend, flatten, fragmentsToText, greater, hasLineComments, indentInitial, isAstLocGreater, isFunction, isLiteralArguments, isLiteralThis, isLocationDataEndGreater, isLocationDataStartGreater, isNumber, isPlainObject, isUnassignable, jisonLocationDataToAstLocationData, lesser, locationDataToString, makeDelimitedLiteral, merge, mergeAstLocationData, mergeLocationData, moveComments, multident, replaceUnicodeCodePointEscapes, shouldCacheOrIsAssignable, some, starts, throwSyntaxError, unfoldSoak, unshiftAfterComments, utility,
|
var Access, Arr, Assign, AwaitReturn, Base, Block, BooleanLiteral, Call, Catch, Class, Code, CodeFragment, ComputedPropertyName, DefaultLiteral, DynamicImport, DynamicImportCall, Elision, ExecutableClassBody, Existence, Expansion, ExportAllDeclaration, ExportDeclaration, ExportDefaultDeclaration, ExportNamedDeclaration, ExportSpecifier, ExportSpecifierList, Extends, For, FuncDirectiveReturn, FuncGlyph, HEREGEX_OMIT, HereComment, HoistTarget, IdentifierLiteral, If, ImportClause, ImportDeclaration, ImportDefaultSpecifier, ImportNamespaceSpecifier, ImportSpecifier, ImportSpecifierList, In, Index, InfinityLiteral, Interpolation, JSXAttribute, JSXAttributes, JSXElement, JSXEmptyExpression, JSXExpressionContainer, JSXIdentifier, JSXTag, JSXText, JS_FORBIDDEN, LEADING_BLANK_LINE, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, LineComment, Literal, MetaProperty, ModuleDeclaration, ModuleSpecifier, ModuleSpecifierList, NEGATE, NO, NaNLiteral, NullLiteral, NumberLiteral, Obj, ObjectProperty, Op, Param, Parens, PassthroughLiteral, PropertyName, Range, RegexLiteral, RegexWithInterpolations, Return, Root, SIMPLENUM, SIMPLE_STRING_OMIT, STRING_OMIT, Scope, Slice, Splat, StatementLiteral, StringLiteral, StringWithInterpolations, Super, SuperCall, Switch, SwitchCase, SwitchWhen, TAB, THIS, TRAILING_BLANK_LINE, TaggedTemplateCall, TemplateElement, ThisLiteral, Throw, Try, UTILITIES, UndefinedLiteral, Value, While, YES, YieldReturn, addDataToNode, attachCommentsToNode, compact, del, ends, extend, flatten, fragmentsToText, greater, hasLineComments, indentInitial, isAstLocGreater, isFunction, isLiteralArguments, isLiteralThis, isLocationDataEndGreater, isLocationDataStartGreater, isNumber, isPlainObject, isUnassignable, jisonLocationDataToAstLocationData, lesser, locationDataToString, makeDelimitedLiteral, merge, mergeAstLocationData, mergeLocationData, moveComments, multident, replaceUnicodeCodePointEscapes, shouldCacheOrIsAssignable, some, starts, throwSyntaxError, unfoldSoak, unshiftAfterComments, utility,
|
||||||
indexOf = [].indexOf,
|
indexOf = [].indexOf,
|
||||||
splice = [].splice,
|
splice = [].splice,
|
||||||
slice1 = [].slice;
|
slice1 = [].slice;
|
||||||
|
@ -796,7 +796,7 @@
|
||||||
len = this.expressions.length;
|
len = this.expressions.length;
|
||||||
ref1 = this.expressions, [lastExp] = slice1.call(ref1, -1);
|
ref1 = this.expressions, [lastExp] = slice1.call(ref1, -1);
|
||||||
lastExp = (lastExp != null ? lastExp.unwrap() : void 0) || false;
|
lastExp = (lastExp != null ? lastExp.unwrap() : void 0) || false;
|
||||||
// We also need to check that we’re not returning a CSX tag if there’s an
|
// We also need to check that we’re not returning a JSX tag if there’s an
|
||||||
// adjacent one at the same level; JSX doesn’t allow that.
|
// adjacent one at the same level; JSX doesn’t allow that.
|
||||||
if (lastExp && lastExp instanceof Parens && lastExp.body.expressions.length > 1) {
|
if (lastExp && lastExp instanceof Parens && lastExp.body.expressions.length > 1) {
|
||||||
({
|
({
|
||||||
|
@ -805,7 +805,7 @@
|
||||||
[penult, last] = slice1.call(expressions, -2);
|
[penult, last] = slice1.call(expressions, -2);
|
||||||
penult = penult.unwrap();
|
penult = penult.unwrap();
|
||||||
last = last.unwrap();
|
last = last.unwrap();
|
||||||
if (penult instanceof CSXElement && last instanceof CSXElement) {
|
if (penult instanceof JSXElement && last instanceof JSXElement) {
|
||||||
expressions[expressions.length - 1].error('Adjacent JSX elements must be wrapped in an enclosing tag');
|
expressions[expressions.length - 1].error('Adjacent JSX elements must be wrapped in an enclosing tag');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1335,19 +1335,19 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
compileNode(o) {
|
compileNode(o) {
|
||||||
if (this.csx) {
|
if (this.jsx) {
|
||||||
return [this.makeCode(this.unquote(true, true))];
|
return [this.makeCode(this.unquote(true, true))];
|
||||||
}
|
}
|
||||||
return super.compileNode(o);
|
return super.compileNode(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
unquote(doubleQuote = false, csx = false) {
|
unquote(doubleQuote = false, jsx = false) {
|
||||||
var unquoted;
|
var unquoted;
|
||||||
unquoted = this.value.slice(1, -1);
|
unquoted = this.value.slice(1, -1);
|
||||||
if (doubleQuote) {
|
if (doubleQuote) {
|
||||||
unquoted = unquoted.replace(/\\"/g, '"');
|
unquoted = unquoted.replace(/\\"/g, '"');
|
||||||
}
|
}
|
||||||
if (csx) {
|
if (jsx) {
|
||||||
unquoted = unquoted.replace(/\\n/g, '\n');
|
unquoted = unquoted.replace(/\\n/g, '\n');
|
||||||
}
|
}
|
||||||
return unquoted;
|
return unquoted;
|
||||||
|
@ -1458,7 +1458,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
astType() {
|
astType() {
|
||||||
if (this.csx) {
|
if (this.jsx) {
|
||||||
return 'JSXIdentifier';
|
return 'JSXIdentifier';
|
||||||
} else {
|
} else {
|
||||||
return 'Identifier';
|
return 'Identifier';
|
||||||
|
@ -1479,32 +1479,10 @@
|
||||||
|
|
||||||
}).call(this);
|
}).call(this);
|
||||||
|
|
||||||
exports.CSXTag = CSXTag = class CSXTag extends IdentifierLiteral {
|
|
||||||
constructor(value, {tagNameLocationData, closingTagOpeningBracketLocationData, closingTagSlashLocationData, closingTagNameLocationData, closingTagClosingBracketLocationData}) {
|
|
||||||
super(value);
|
|
||||||
this.tagNameLocationData = tagNameLocationData;
|
|
||||||
this.closingTagOpeningBracketLocationData = closingTagOpeningBracketLocationData;
|
|
||||||
this.closingTagSlashLocationData = closingTagSlashLocationData;
|
|
||||||
this.closingTagNameLocationData = closingTagNameLocationData;
|
|
||||||
this.closingTagClosingBracketLocationData = closingTagClosingBracketLocationData;
|
|
||||||
}
|
|
||||||
|
|
||||||
astType() {
|
|
||||||
return 'JSXIdentifier';
|
|
||||||
}
|
|
||||||
|
|
||||||
astProperties() {
|
|
||||||
return {
|
|
||||||
name: this.value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.PropertyName = PropertyName = (function() {
|
exports.PropertyName = PropertyName = (function() {
|
||||||
class PropertyName extends Literal {
|
class PropertyName extends Literal {
|
||||||
astType() {
|
astType() {
|
||||||
if (this.csx) {
|
if (this.jsx) {
|
||||||
return 'JSXIdentifier';
|
return 'JSXIdentifier';
|
||||||
} else {
|
} else {
|
||||||
return 'Identifier';
|
return 'Identifier';
|
||||||
|
@ -1883,8 +1861,8 @@
|
||||||
return !this.properties.length && this.base.isStatement(o);
|
return !this.properties.length && this.base.isStatement(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
isCSXTag() {
|
isJSXTag() {
|
||||||
return this.base instanceof CSXTag;
|
return this.base instanceof JSXTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
assigns(name) {
|
assigns(name) {
|
||||||
|
@ -2061,7 +2039,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
astType() {
|
astType() {
|
||||||
if (this.isCSXTag()) {
|
if (this.isJSXTag()) {
|
||||||
return 'JSXMemberExpression';
|
return 'JSXMemberExpression';
|
||||||
} else {
|
} else {
|
||||||
return 'MemberExpression';
|
return 'MemberExpression';
|
||||||
|
@ -2074,8 +2052,8 @@
|
||||||
astProperties(o) {
|
astProperties(o) {
|
||||||
var computed, property, ref1, ref2;
|
var computed, property, ref1, ref2;
|
||||||
ref1 = this.properties, [property] = slice1.call(ref1, -1);
|
ref1 = this.properties, [property] = slice1.call(ref1, -1);
|
||||||
if (this.isCSXTag()) {
|
if (this.isJSXTag()) {
|
||||||
property.name.csx = true;
|
property.name.jsx = true;
|
||||||
}
|
}
|
||||||
computed = property instanceof Index || !(((ref2 = property.name) != null ? ref2.unwrap() : void 0) instanceof PropertyName);
|
computed = property instanceof Index || !(((ref2 = property.name) != null ? ref2.unwrap() : void 0) instanceof PropertyName);
|
||||||
return {
|
return {
|
||||||
|
@ -2088,7 +2066,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
astLocationData() {
|
astLocationData() {
|
||||||
if (!this.isCSXTag()) {
|
if (!this.isJSXTag()) {
|
||||||
return super.astLocationData();
|
return super.astLocationData();
|
||||||
}
|
}
|
||||||
// don't include leading < of JSX tag in location data
|
// don't include leading < of JSX tag in location data
|
||||||
|
@ -2223,20 +2201,38 @@
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//### CSX
|
//### JSX
|
||||||
exports.CSXIdentifier = CSXIdentifier = class CSXIdentifier extends IdentifierLiteral {
|
exports.JSXIdentifier = JSXIdentifier = class JSXIdentifier extends IdentifierLiteral {
|
||||||
astType() {
|
astType() {
|
||||||
return 'JSXIdentifier';
|
return 'JSXIdentifier';
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.CSXExpressionContainer = CSXExpressionContainer = (function() {
|
exports.JSXTag = JSXTag = class JSXTag extends JSXIdentifier {
|
||||||
class CSXExpressionContainer extends Base {
|
constructor(value, {tagNameLocationData, closingTagOpeningBracketLocationData, closingTagSlashLocationData, closingTagNameLocationData, closingTagClosingBracketLocationData}) {
|
||||||
|
super(value);
|
||||||
|
this.tagNameLocationData = tagNameLocationData;
|
||||||
|
this.closingTagOpeningBracketLocationData = closingTagOpeningBracketLocationData;
|
||||||
|
this.closingTagSlashLocationData = closingTagSlashLocationData;
|
||||||
|
this.closingTagNameLocationData = closingTagNameLocationData;
|
||||||
|
this.closingTagClosingBracketLocationData = closingTagClosingBracketLocationData;
|
||||||
|
}
|
||||||
|
|
||||||
|
astProperties() {
|
||||||
|
return {
|
||||||
|
name: this.value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.JSXExpressionContainer = JSXExpressionContainer = (function() {
|
||||||
|
class JSXExpressionContainer extends Base {
|
||||||
constructor(expression1, {locationData} = {}) {
|
constructor(expression1, {locationData} = {}) {
|
||||||
super();
|
super();
|
||||||
this.expression = expression1;
|
this.expression = expression1;
|
||||||
this.expression.csxAttribute = true;
|
this.expression.jsxAttribute = true;
|
||||||
this.locationData = locationData != null ? locationData : this.expression.locationData;
|
this.locationData = locationData != null ? locationData : this.expression.locationData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2244,10 +2240,6 @@
|
||||||
return this.expression.compileNode(o);
|
return this.expression.compileNode(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
astType() {
|
|
||||||
return 'JSXExpressionContainer';
|
|
||||||
}
|
|
||||||
|
|
||||||
astProperties() {
|
astProperties() {
|
||||||
return {
|
return {
|
||||||
expression: this.expression.ast()
|
expression: this.expression.ast()
|
||||||
|
@ -2256,30 +2248,21 @@
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CSXExpressionContainer.prototype.children = ['expression'];
|
JSXExpressionContainer.prototype.children = ['expression'];
|
||||||
|
|
||||||
return CSXExpressionContainer;
|
return JSXExpressionContainer;
|
||||||
|
|
||||||
}).call(this);
|
}).call(this);
|
||||||
|
|
||||||
exports.CSXEmptyExpression = CSXEmptyExpression = class CSXEmptyExpression extends Base {
|
exports.JSXEmptyExpression = JSXEmptyExpression = class JSXEmptyExpression extends Base {};
|
||||||
astType() {
|
|
||||||
return 'JSXEmptyExpression';
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
exports.JSXText = JSXText = class JSXText extends Base {
|
||||||
|
|
||||||
exports.CSXText = CSXText = class CSXText extends Base {
|
|
||||||
constructor(stringLiteral) {
|
constructor(stringLiteral) {
|
||||||
super();
|
super();
|
||||||
this.value = stringLiteral.unquote(true, true);
|
this.value = stringLiteral.unquote(true, true);
|
||||||
this.locationData = stringLiteral.locationData;
|
this.locationData = stringLiteral.locationData;
|
||||||
}
|
}
|
||||||
|
|
||||||
astType() {
|
|
||||||
return 'JSXText';
|
|
||||||
}
|
|
||||||
|
|
||||||
astProperties() {
|
astProperties() {
|
||||||
return {
|
return {
|
||||||
value: this.value,
|
value: this.value,
|
||||||
|
@ -2291,8 +2274,8 @@
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.CSXAttribute = CSXAttribute = (function() {
|
exports.JSXAttribute = JSXAttribute = (function() {
|
||||||
class CSXAttribute extends Base {
|
class JSXAttribute extends Base {
|
||||||
constructor({
|
constructor({
|
||||||
name: name1,
|
name: name1,
|
||||||
value
|
value
|
||||||
|
@ -2300,7 +2283,7 @@
|
||||||
var ref1;
|
var ref1;
|
||||||
super();
|
super();
|
||||||
this.name = name1;
|
this.name = name1;
|
||||||
this.value = value != null ? (value = value.base, value instanceof StringLiteral ? value : new CSXExpressionContainer(value)) : null;
|
this.value = value != null ? (value = value.base, value instanceof StringLiteral ? value : new JSXExpressionContainer(value)) : null;
|
||||||
if ((ref1 = this.value) != null) {
|
if ((ref1 = this.value) != null) {
|
||||||
ref1.comments = value.comments;
|
ref1.comments = value.comments;
|
||||||
}
|
}
|
||||||
|
@ -2316,10 +2299,6 @@
|
||||||
return compiledName.concat(this.makeCode('='), val);
|
return compiledName.concat(this.makeCode('='), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
astType() {
|
|
||||||
return 'JSXAttribute';
|
|
||||||
}
|
|
||||||
|
|
||||||
astProperties() {
|
astProperties() {
|
||||||
var ref1, ref2;
|
var ref1, ref2;
|
||||||
return {
|
return {
|
||||||
|
@ -2330,14 +2309,14 @@
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CSXAttribute.prototype.children = ['name', 'value'];
|
JSXAttribute.prototype.children = ['name', 'value'];
|
||||||
|
|
||||||
return CSXAttribute;
|
return JSXAttribute;
|
||||||
|
|
||||||
}).call(this);
|
}).call(this);
|
||||||
|
|
||||||
exports.CSXAttributes = CSXAttributes = (function() {
|
exports.JSXAttributes = JSXAttributes = (function() {
|
||||||
class CSXAttributes extends Base {
|
class JSXAttributes extends Base {
|
||||||
constructor(arr) {
|
constructor(arr) {
|
||||||
var attribute, base, j, k, len1, len2, object, property, ref1, ref2, value, variable;
|
var attribute, base, j, k, len1, len2, object, property, ref1, ref2, value, variable;
|
||||||
super();
|
super();
|
||||||
|
@ -2349,15 +2328,15 @@
|
||||||
({base} = object);
|
({base} = object);
|
||||||
if (base instanceof IdentifierLiteral) {
|
if (base instanceof IdentifierLiteral) {
|
||||||
// attribute with no value eg disabled
|
// attribute with no value eg disabled
|
||||||
attribute = new CSXAttribute({
|
attribute = new JSXAttribute({
|
||||||
name: new CSXIdentifier(base.value).withLocationDataAndCommentsFrom(base)
|
name: new JSXIdentifier(base.value).withLocationDataAndCommentsFrom(base)
|
||||||
});
|
});
|
||||||
attribute.locationData = base.locationData;
|
attribute.locationData = base.locationData;
|
||||||
this.attributes.push(attribute);
|
this.attributes.push(attribute);
|
||||||
} else if (!base.generated) {
|
} else if (!base.generated) {
|
||||||
// object spread attribute eg {...props}
|
// object spread attribute eg {...props}
|
||||||
attribute = base.properties[0];
|
attribute = base.properties[0];
|
||||||
attribute.csx = true;
|
attribute.jsx = true;
|
||||||
attribute.locationData = base.locationData;
|
attribute.locationData = base.locationData;
|
||||||
this.attributes.push(attribute);
|
this.attributes.push(attribute);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2366,8 +2345,8 @@
|
||||||
for (k = 0, len2 = ref2.length; k < len2; k++) {
|
for (k = 0, len2 = ref2.length; k < len2; k++) {
|
||||||
property = ref2[k];
|
property = ref2[k];
|
||||||
({variable, value} = property);
|
({variable, value} = property);
|
||||||
attribute = new CSXAttribute({
|
attribute = new JSXAttribute({
|
||||||
name: new CSXIdentifier(variable.base.value).withLocationDataAndCommentsFrom(variable.base),
|
name: new JSXIdentifier(variable.base.value).withLocationDataAndCommentsFrom(variable.base),
|
||||||
value
|
value
|
||||||
});
|
});
|
||||||
attribute.locationData = property.locationData;
|
attribute.locationData = property.locationData;
|
||||||
|
@ -2386,7 +2365,7 @@
|
||||||
} = object);
|
} = object);
|
||||||
properties = (attribute != null ? attribute.properties : void 0) || [];
|
properties = (attribute != null ? attribute.properties : void 0) || [];
|
||||||
if (!(attribute instanceof Obj || attribute instanceof IdentifierLiteral) || (attribute instanceof Obj && !attribute.generated && (properties.length > 1 || !(properties[0] instanceof Splat)))) {
|
if (!(attribute instanceof Obj || attribute instanceof IdentifierLiteral) || (attribute instanceof Obj && !attribute.generated && (properties.length > 1 || !(properties[0] instanceof Splat)))) {
|
||||||
return object.error("Unexpected token. Allowed CSX attributes are: id=\"val\", src={source}, {props...} or attribute.");
|
return object.error("Unexpected token. Allowed JSX attributes are: id=\"val\", src={source}, {props...} or attribute.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2415,15 +2394,15 @@
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CSXAttributes.prototype.children = ['attributes'];
|
JSXAttributes.prototype.children = ['attributes'];
|
||||||
|
|
||||||
return CSXAttributes;
|
return JSXAttributes;
|
||||||
|
|
||||||
}).call(this);
|
}).call(this);
|
||||||
|
|
||||||
// Node for a CSX element
|
// Node for a JSX element
|
||||||
exports.CSXElement = CSXElement = (function() {
|
exports.JSXElement = JSXElement = (function() {
|
||||||
class CSXElement extends Base {
|
class JSXElement extends Base {
|
||||||
constructor({
|
constructor({
|
||||||
tagName: tagName1,
|
tagName: tagName1,
|
||||||
attributes,
|
attributes,
|
||||||
|
@ -2438,7 +2417,7 @@
|
||||||
compileNode(o) {
|
compileNode(o) {
|
||||||
var fragments, ref1, tag;
|
var fragments, ref1, tag;
|
||||||
if ((ref1 = this.content) != null) {
|
if ((ref1 = this.content) != null) {
|
||||||
ref1.base.csx = true;
|
ref1.base.jsx = true;
|
||||||
}
|
}
|
||||||
fragments = [this.makeCode('<')];
|
fragments = [this.makeCode('<')];
|
||||||
fragments.push(...(tag = this.tagName.compileToFragments(o, LEVEL_ACCESS)));
|
fragments.push(...(tag = this.tagName.compileToFragments(o, LEVEL_ACCESS)));
|
||||||
|
@ -2541,7 +2520,7 @@
|
||||||
children = (function() {
|
children = (function() {
|
||||||
var j, len1, ref1, results;
|
var j, len1, ref1, results;
|
||||||
if (content instanceof StringLiteral) {
|
if (content instanceof StringLiteral) {
|
||||||
return [new CSXText(content)]; // StringWithInterpolations
|
return [new JSXText(content)]; // StringWithInterpolations
|
||||||
} else {
|
} else {
|
||||||
ref1 = this.content.unwrapAll().extractElements(o, {
|
ref1 = this.content.unwrapAll().extractElements(o, {
|
||||||
includeInterpolationWrappers: true
|
includeInterpolationWrappers: true
|
||||||
|
@ -2550,17 +2529,17 @@
|
||||||
for (j = 0, len1 = ref1.length; j < len1; j++) {
|
for (j = 0, len1 = ref1.length; j < len1; j++) {
|
||||||
element = ref1[j];
|
element = ref1[j];
|
||||||
if (element instanceof StringLiteral) {
|
if (element instanceof StringLiteral) {
|
||||||
results.push(new CSXText(element)); // Interpolation
|
results.push(new JSXText(element)); // Interpolation
|
||||||
} else {
|
} else {
|
||||||
({expression} = element);
|
({expression} = element);
|
||||||
if (expression == null) {
|
if (expression == null) {
|
||||||
results.push(new CSXEmptyExpression().withLocationDataFrom(element));
|
results.push(new JSXEmptyExpression().withLocationDataFrom(element));
|
||||||
} else {
|
} else {
|
||||||
unwrapped = expression.unwrapAll();
|
unwrapped = expression.unwrapAll();
|
||||||
if (unwrapped instanceof CSXElement) {
|
if (unwrapped instanceof JSXElement) {
|
||||||
results.push(unwrapped);
|
results.push(unwrapped);
|
||||||
} else {
|
} else {
|
||||||
results.push(new CSXExpressionContainer(unwrapped, {
|
results.push(new JSXExpressionContainer(unwrapped, {
|
||||||
locationData: element.locationData
|
locationData: element.locationData
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -2573,7 +2552,7 @@
|
||||||
results = [];
|
results = [];
|
||||||
for (j = 0, len1 = children.length; j < len1; j++) {
|
for (j = 0, len1 = children.length; j < len1; j++) {
|
||||||
child = children[j];
|
child = children[j];
|
||||||
if (!(child instanceof CSXText && child.value.length === 0)) {
|
if (!(child instanceof JSXText && child.value.length === 0)) {
|
||||||
results.push(child.ast(o));
|
results.push(child.ast(o));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2596,9 +2575,9 @@
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CSXElement.prototype.children = ['tagName', 'attributes', 'content'];
|
JSXElement.prototype.children = ['tagName', 'attributes', 'content'];
|
||||||
|
|
||||||
return CSXElement;
|
return JSXElement;
|
||||||
|
|
||||||
}).call(this);
|
}).call(this);
|
||||||
|
|
||||||
|
@ -2619,10 +2598,10 @@
|
||||||
if (this.variable instanceof Value && this.variable.isNotCallable()) {
|
if (this.variable instanceof Value && this.variable.isNotCallable()) {
|
||||||
this.variable.error("literal is not a function");
|
this.variable.error("literal is not a function");
|
||||||
}
|
}
|
||||||
if (this.variable.base instanceof CSXTag) {
|
if (this.variable.base instanceof JSXTag) {
|
||||||
return new CSXElement({
|
return new JSXElement({
|
||||||
tagName: this.variable,
|
tagName: this.variable,
|
||||||
attributes: new CSXAttributes(this.args[0].base),
|
attributes: new JSXAttributes(this.args[0].base),
|
||||||
content: this.args[1]
|
content: this.args[1]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -5836,7 +5815,7 @@
|
||||||
compileNode(o) {
|
compileNode(o) {
|
||||||
var compiledSplat;
|
var compiledSplat;
|
||||||
compiledSplat = [this.makeCode('...'), ...this.name.compileToFragments(o, LEVEL_OP)];
|
compiledSplat = [this.makeCode('...'), ...this.name.compileToFragments(o, LEVEL_OP)];
|
||||||
if (!this.csx) {
|
if (!this.jsx) {
|
||||||
return compiledSplat;
|
return compiledSplat;
|
||||||
}
|
}
|
||||||
return [this.makeCode('{'), ...compiledSplat, this.makeCode('}')];
|
return [this.makeCode('{'), ...compiledSplat, this.makeCode('}')];
|
||||||
|
@ -5847,7 +5826,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
astType() {
|
astType() {
|
||||||
if (this.csx) {
|
if (this.jsx) {
|
||||||
return 'JSXSpreadAttribute';
|
return 'JSXSpreadAttribute';
|
||||||
} else if (this.lhs) {
|
} else if (this.lhs) {
|
||||||
return 'RestElement';
|
return 'RestElement';
|
||||||
|
@ -6781,13 +6760,13 @@
|
||||||
shouldWrapComment = (ref1 = expr.comments) != null ? ref1.some(function(comment) {
|
shouldWrapComment = (ref1 = expr.comments) != null ? ref1.some(function(comment) {
|
||||||
return comment.here && !comment.unshift && !comment.newLine;
|
return comment.here && !comment.unshift && !comment.newLine;
|
||||||
}) : void 0;
|
}) : void 0;
|
||||||
if (expr instanceof Value && expr.isAtomic() && !this.csxAttribute && !shouldWrapComment) {
|
if (expr instanceof Value && expr.isAtomic() && !this.jsxAttribute && !shouldWrapComment) {
|
||||||
expr.front = this.front;
|
expr.front = this.front;
|
||||||
return expr.compileToFragments(o);
|
return expr.compileToFragments(o);
|
||||||
}
|
}
|
||||||
fragments = expr.compileToFragments(o, LEVEL_PAREN);
|
fragments = expr.compileToFragments(o, LEVEL_PAREN);
|
||||||
bare = o.level < LEVEL_OP && !shouldWrapComment && (expr instanceof Op && !expr.isInOperator() || expr.unwrap() instanceof Call || (expr instanceof For && expr.returns)) && (o.level < LEVEL_COND || fragments.length <= 3);
|
bare = o.level < LEVEL_OP && !shouldWrapComment && (expr instanceof Op && !expr.isInOperator() || expr.unwrap() instanceof Call || (expr instanceof For && expr.returns)) && (o.level < LEVEL_COND || fragments.length <= 3);
|
||||||
if (this.csxAttribute) {
|
if (this.jsxAttribute) {
|
||||||
return this.wrapInBraces(fragments);
|
return this.wrapInBraces(fragments);
|
||||||
}
|
}
|
||||||
if (bare) {
|
if (bare) {
|
||||||
|
@ -6863,7 +6842,7 @@
|
||||||
}
|
}
|
||||||
attachCommentsToNode(salvagedComments, node);
|
attachCommentsToNode(salvagedComments, node);
|
||||||
}
|
}
|
||||||
if ((unwrapped = (ref1 = node.expression) != null ? ref1.unwrapAll() : void 0) instanceof PassthroughLiteral && unwrapped.generated && !this.csx) {
|
if ((unwrapped = (ref1 = node.expression) != null ? ref1.unwrapAll() : void 0) instanceof PassthroughLiteral && unwrapped.generated && !this.jsx) {
|
||||||
commentPlaceholder = new StringLiteral('').withLocationDataFrom(node);
|
commentPlaceholder = new StringLiteral('').withLocationDataFrom(node);
|
||||||
commentPlaceholder.comments = unwrapped.comments;
|
commentPlaceholder.comments = unwrapped.comments;
|
||||||
if (node.comments) {
|
if (node.comments) {
|
||||||
|
@ -6902,21 +6881,21 @@
|
||||||
if (this.comments == null) {
|
if (this.comments == null) {
|
||||||
this.comments = (ref1 = this.startQuote) != null ? ref1.comments : void 0;
|
this.comments = (ref1 = this.startQuote) != null ? ref1.comments : void 0;
|
||||||
}
|
}
|
||||||
if (this.csxAttribute) {
|
if (this.jsxAttribute) {
|
||||||
wrapped = new Parens(new StringWithInterpolations(this.body));
|
wrapped = new Parens(new StringWithInterpolations(this.body));
|
||||||
wrapped.csxAttribute = true;
|
wrapped.jsxAttribute = true;
|
||||||
return wrapped.compileNode(o);
|
return wrapped.compileNode(o);
|
||||||
}
|
}
|
||||||
elements = this.extractElements(o);
|
elements = this.extractElements(o);
|
||||||
fragments = [];
|
fragments = [];
|
||||||
if (!this.csx) {
|
if (!this.jsx) {
|
||||||
fragments.push(this.makeCode('`'));
|
fragments.push(this.makeCode('`'));
|
||||||
}
|
}
|
||||||
for (j = 0, len1 = elements.length; j < len1; j++) {
|
for (j = 0, len1 = elements.length; j < len1; j++) {
|
||||||
element = elements[j];
|
element = elements[j];
|
||||||
if (element instanceof StringLiteral) {
|
if (element instanceof StringLiteral) {
|
||||||
element.value = element.unquote(true, this.csx);
|
element.value = element.unquote(true, this.jsx);
|
||||||
if (!this.csx) {
|
if (!this.jsx) {
|
||||||
// Backticks and `${` inside template literals must be escaped.
|
// Backticks and `${` inside template literals must be escaped.
|
||||||
element.value = element.value.replace(/(\\*)(`|\$\{)/g, function(match, backslashes, toBeEscaped) {
|
element.value = element.value.replace(/(\\*)(`|\$\{)/g, function(match, backslashes, toBeEscaped) {
|
||||||
if (backslashes.length % 2 === 0) {
|
if (backslashes.length % 2 === 0) {
|
||||||
|
@ -6928,7 +6907,7 @@
|
||||||
}
|
}
|
||||||
fragments.push(...element.compileToFragments(o));
|
fragments.push(...element.compileToFragments(o));
|
||||||
} else {
|
} else {
|
||||||
if (!this.csx) {
|
if (!this.jsx) {
|
||||||
fragments.push(this.makeCode('$'));
|
fragments.push(this.makeCode('$'));
|
||||||
}
|
}
|
||||||
code = element.compileToFragments(o, LEVEL_PAREN);
|
code = element.compileToFragments(o, LEVEL_PAREN);
|
||||||
|
@ -6951,7 +6930,7 @@
|
||||||
fragments.push(...code);
|
fragments.push(...code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!this.csx) {
|
if (!this.jsx) {
|
||||||
fragments.push(this.makeCode('`'));
|
fragments.push(this.makeCode('`'));
|
||||||
}
|
}
|
||||||
return fragments;
|
return fragments;
|
||||||
|
@ -6960,7 +6939,7 @@
|
||||||
isNestedTag(element) {
|
isNestedTag(element) {
|
||||||
var call;
|
var call;
|
||||||
call = typeof element.unwrapAll === "function" ? element.unwrapAll() : void 0;
|
call = typeof element.unwrapAll === "function" ? element.unwrapAll() : void 0;
|
||||||
return this.csx && call instanceof CSXElement;
|
return this.jsx && call instanceof JSXElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
astType() {
|
astType() {
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -89,7 +89,7 @@
|
||||||
this.addImplicitBracesAndParens();
|
this.addImplicitBracesAndParens();
|
||||||
this.rescueStowawayComments();
|
this.rescueStowawayComments();
|
||||||
this.addLocationDataToGeneratedTokens();
|
this.addLocationDataToGeneratedTokens();
|
||||||
this.enforceValidCSXAttributes();
|
this.enforceValidJSXAttributes();
|
||||||
this.fixOutdentLocationData();
|
this.fixOutdentLocationData();
|
||||||
this.exposeTokenDataToGrammar();
|
this.exposeTokenDataToGrammar();
|
||||||
if (typeof process !== "undefined" && process !== null ? (ref1 = process.env) != null ? ref1.DEBUG_REWRITTEN_TOKEN_STREAM : void 0 : void 0) {
|
if (typeof process !== "undefined" && process !== null ? (ref1 = process.env) != null ? ref1.DEBUG_REWRITTEN_TOKEN_STREAM : void 0 : void 0) {
|
||||||
|
@ -578,11 +578,11 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure only strings and wrapped expressions are used in CSX attributes.
|
// Make sure only strings and wrapped expressions are used in JSX attributes.
|
||||||
enforceValidCSXAttributes() {
|
enforceValidJSXAttributes() {
|
||||||
return this.scanTokens(function(token, i, tokens) {
|
return this.scanTokens(function(token, i, tokens) {
|
||||||
var next, ref;
|
var next, ref;
|
||||||
if (token.csxColon) {
|
if (token.jsxColon) {
|
||||||
next = tokens[i + 1];
|
next = tokens[i + 1];
|
||||||
if ((ref = next[0]) !== 'STRING_START' && ref !== 'STRING' && ref !== '(') {
|
if ((ref = next[0]) !== 'STRING_START' && ref !== 'STRING' && ref !== '(') {
|
||||||
throwSyntaxError('expected wrapped or quoted JSX attribute', next[2]);
|
throwSyntaxError('expected wrapped or quoted JSX attribute', next[2]);
|
||||||
|
@ -993,7 +993,7 @@
|
||||||
IMPLICIT_FUNC = ['IDENTIFIER', 'PROPERTY', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
|
IMPLICIT_FUNC = ['IDENTIFIER', 'PROPERTY', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
|
||||||
|
|
||||||
// If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
|
// If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
|
||||||
IMPLICIT_CALL = ['IDENTIFIER', 'CSX_TAG', 'PROPERTY', 'NUMBER', 'INFINITY', 'NAN', 'STRING', 'STRING_START', 'REGEX', 'REGEX_START', 'JS', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'UNDEFINED', 'NULL', 'BOOL', 'UNARY', 'DO', 'DO_IIFE', 'YIELD', 'AWAIT', 'UNARY_MATH', 'SUPER', 'THROW', '@', '->', '=>', '[', '(', '{', '--', '++'];
|
IMPLICIT_CALL = ['IDENTIFIER', 'JSX_TAG', 'PROPERTY', 'NUMBER', 'INFINITY', 'NAN', 'STRING', 'STRING_START', 'REGEX', 'REGEX_START', 'JS', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'UNDEFINED', 'NULL', 'BOOL', 'UNARY', 'DO', 'DO_IIFE', 'YIELD', 'AWAIT', 'UNARY_MATH', 'SUPER', 'THROW', '@', '->', '=>', '[', '(', '{', '--', '++'];
|
||||||
|
|
||||||
IMPLICIT_UNSPACED_CALL = ['+', '-'];
|
IMPLICIT_UNSPACED_CALL = ['+', '-'];
|
||||||
|
|
||||||
|
|
|
@ -153,7 +153,7 @@ grammar =
|
||||||
|
|
||||||
Identifier: [
|
Identifier: [
|
||||||
o 'IDENTIFIER', -> new IdentifierLiteral $1
|
o 'IDENTIFIER', -> new IdentifierLiteral $1
|
||||||
o 'CSX_TAG', -> new CSXTag $1.toString(),
|
o 'JSX_TAG', -> new JSXTag $1.toString(),
|
||||||
tagNameLocationData: $1.tagNameToken[2]
|
tagNameLocationData: $1.tagNameToken[2]
|
||||||
closingTagOpeningBracketLocationData: $1.closingTagOpeningBracketToken?[2]
|
closingTagOpeningBracketLocationData: $1.closingTagOpeningBracketToken?[2]
|
||||||
closingTagSlashLocationData: $1.closingTagSlashToken?[2]
|
closingTagSlashLocationData: $1.closingTagSlashToken?[2]
|
||||||
|
|
|
@ -49,8 +49,8 @@ exports.Lexer = class Lexer
|
||||||
@seenExport = no # Used to recognize `EXPORT FROM? AS?` tokens.
|
@seenExport = no # Used to recognize `EXPORT FROM? AS?` tokens.
|
||||||
@importSpecifierList = no # Used to identify when in an `IMPORT {...} FROM? ...`.
|
@importSpecifierList = no # Used to identify when in an `IMPORT {...} FROM? ...`.
|
||||||
@exportSpecifierList = no # Used to identify when in an `EXPORT {...} FROM? ...`.
|
@exportSpecifierList = no # Used to identify when in an `EXPORT {...} FROM? ...`.
|
||||||
@csxDepth = 0 # Used to optimize CSX checks, how deep in CSX we are.
|
@jsxDepth = 0 # Used to optimize JSX checks, how deep in JSX we are.
|
||||||
@csxObjAttribute = {} # Used to detect if CSX attributes is wrapped in {} (<div {props...} />).
|
@jsxObjAttribute = {} # Used to detect if JSX attributes is wrapped in {} (<div {props...} />).
|
||||||
|
|
||||||
@chunkLine =
|
@chunkLine =
|
||||||
opts.line or 0 # The start line for the current @chunk.
|
opts.line or 0 # The start line for the current @chunk.
|
||||||
|
@ -72,7 +72,7 @@ exports.Lexer = class Lexer
|
||||||
@lineToken() or
|
@lineToken() or
|
||||||
@stringToken() or
|
@stringToken() or
|
||||||
@numberToken() or
|
@numberToken() or
|
||||||
@csxToken() or
|
@jsxToken() or
|
||||||
@regexToken() or
|
@regexToken() or
|
||||||
@jsToken() or
|
@jsToken() or
|
||||||
@literalToken()
|
@literalToken()
|
||||||
|
@ -111,8 +111,8 @@ exports.Lexer = class Lexer
|
||||||
# referenced as property names here, so you can still do `jQuery.is()` even
|
# referenced as property names here, so you can still do `jQuery.is()` even
|
||||||
# though `is` means `===` otherwise.
|
# though `is` means `===` otherwise.
|
||||||
identifierToken: ->
|
identifierToken: ->
|
||||||
inCSXTag = @atCSXTag()
|
inJSXTag = @atJSXTag()
|
||||||
regex = if inCSXTag then CSX_ATTRIBUTE else IDENTIFIER
|
regex = if inJSXTag then JSX_ATTRIBUTE else IDENTIFIER
|
||||||
return 0 unless match = regex.exec @chunk
|
return 0 unless match = regex.exec @chunk
|
||||||
[input, id, colon] = match
|
[input, id, colon] = match
|
||||||
|
|
||||||
|
@ -233,10 +233,10 @@ exports.Lexer = class Lexer
|
||||||
[tagToken[2].first_line, tagToken[2].first_column, tagToken[2].range[0]] =
|
[tagToken[2].first_line, tagToken[2].first_column, tagToken[2].range[0]] =
|
||||||
[poppedToken[2].first_line, poppedToken[2].first_column, poppedToken[2].range[0]]
|
[poppedToken[2].first_line, poppedToken[2].first_column, poppedToken[2].range[0]]
|
||||||
if colon
|
if colon
|
||||||
colonOffset = input.lastIndexOf if inCSXTag then '=' else ':'
|
colonOffset = input.lastIndexOf if inJSXTag then '=' else ':'
|
||||||
colonToken = @token ':', ':', offset: colonOffset, length: colon.length
|
colonToken = @token ':', ':', offset: colonOffset, length: colon.length
|
||||||
colonToken.csxColon = yes if inCSXTag # used by rewriter
|
colonToken.jsxColon = yes if inJSXTag # used by rewriter
|
||||||
if inCSXTag and tag is 'IDENTIFIER' and prev[0] isnt ':'
|
if inJSXTag and tag is 'IDENTIFIER' and prev[0] isnt ':'
|
||||||
@token ',', ',', length: 0, origin: tagToken
|
@token ',', ',', length: 0, origin: tagToken
|
||||||
|
|
||||||
input.length
|
input.length
|
||||||
|
@ -304,7 +304,7 @@ exports.Lexer = class Lexer
|
||||||
@mergeInterpolationTokens tokens, {quote, indent, endOffset: end}, (value) =>
|
@mergeInterpolationTokens tokens, {quote, indent, endOffset: end}, (value) =>
|
||||||
@validateUnicodeCodePointEscapes value, delimiter: quote
|
@validateUnicodeCodePointEscapes value, delimiter: quote
|
||||||
|
|
||||||
if @atCSXTag()
|
if @atJSXTag()
|
||||||
@token ',', ',', length: 0, origin: @prev
|
@token ',', ',', length: 0, origin: @prev
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -543,15 +543,14 @@ exports.Lexer = class Lexer
|
||||||
@tokens.pop()
|
@tokens.pop()
|
||||||
this
|
this
|
||||||
|
|
||||||
# CSX is like JSX but for CoffeeScript.
|
jsxToken: ->
|
||||||
csxToken: ->
|
|
||||||
firstChar = @chunk[0]
|
firstChar = @chunk[0]
|
||||||
# Check the previous token to detect if attribute is spread.
|
# Check the previous token to detect if attribute is spread.
|
||||||
prevChar = if @tokens.length > 0 then @tokens[@tokens.length - 1][0] else ''
|
prevChar = if @tokens.length > 0 then @tokens[@tokens.length - 1][0] else ''
|
||||||
if firstChar is '<'
|
if firstChar is '<'
|
||||||
match = CSX_IDENTIFIER.exec(@chunk[1...]) or CSX_FRAGMENT_IDENTIFIER.exec(@chunk[1...])
|
match = JSX_IDENTIFIER.exec(@chunk[1...]) or JSX_FRAGMENT_IDENTIFIER.exec(@chunk[1...])
|
||||||
return 0 unless match and (
|
return 0 unless match and (
|
||||||
@csxDepth > 0 or
|
@jsxDepth > 0 or
|
||||||
# Not the right hand side of an unspaced comparison (i.e. `a<b`).
|
# Not the right hand side of an unspaced comparison (i.e. `a<b`).
|
||||||
not (prev = @prev()) or
|
not (prev = @prev()) or
|
||||||
prev.spaced or
|
prev.spaced or
|
||||||
|
@ -563,7 +562,7 @@ exports.Lexer = class Lexer
|
||||||
[id, properties...] = id.split '.'
|
[id, properties...] = id.split '.'
|
||||||
else
|
else
|
||||||
properties = []
|
properties = []
|
||||||
tagToken = @token 'CSX_TAG', id,
|
tagToken = @token 'JSX_TAG', id,
|
||||||
length: id.length + 1
|
length: id.length + 1
|
||||||
data:
|
data:
|
||||||
openingBracketToken: @makeToken '<', '<'
|
openingBracketToken: @makeToken '<', '<'
|
||||||
|
@ -577,9 +576,9 @@ exports.Lexer = class Lexer
|
||||||
@token 'CALL_START', '(', generated: yes
|
@token 'CALL_START', '(', generated: yes
|
||||||
@token '[', '[', generated: yes
|
@token '[', '[', generated: yes
|
||||||
@ends.push {tag: '/>', origin: tagToken, name: id, properties}
|
@ends.push {tag: '/>', origin: tagToken, name: id, properties}
|
||||||
@csxDepth++
|
@jsxDepth++
|
||||||
return fullId.length + 1
|
return fullId.length + 1
|
||||||
else if csxTag = @atCSXTag()
|
else if jsxTag = @atJSXTag()
|
||||||
if @chunk[...2] is '/>' # Self-closing tag.
|
if @chunk[...2] is '/>' # Self-closing tag.
|
||||||
@pair '/>'
|
@pair '/>'
|
||||||
@token ']', ']',
|
@token ']', ']',
|
||||||
|
@ -591,15 +590,15 @@ exports.Lexer = class Lexer
|
||||||
data:
|
data:
|
||||||
selfClosingSlashToken: @makeToken '/', '/'
|
selfClosingSlashToken: @makeToken '/', '/'
|
||||||
closingBracketToken: @makeToken '>', '>', offset: 1
|
closingBracketToken: @makeToken '>', '>', offset: 1
|
||||||
@csxDepth--
|
@jsxDepth--
|
||||||
return 2
|
return 2
|
||||||
else if firstChar is '{'
|
else if firstChar is '{'
|
||||||
if prevChar is ':'
|
if prevChar is ':'
|
||||||
token = @token '(', '('
|
token = @token '(', '('
|
||||||
@csxObjAttribute[@csxDepth] = no
|
@jsxObjAttribute[@jsxDepth] = no
|
||||||
else
|
else
|
||||||
token = @token '{', '{'
|
token = @token '{', '{'
|
||||||
@csxObjAttribute[@csxDepth] = yes
|
@jsxObjAttribute[@jsxDepth] = yes
|
||||||
@ends.push {tag: '}', origin: token}
|
@ends.push {tag: '}', origin: token}
|
||||||
return 1
|
return 1
|
||||||
else if firstChar is '>' # end of opening tag
|
else if firstChar is '>' # end of opening tag
|
||||||
|
@ -611,13 +610,13 @@ exports.Lexer = class Lexer
|
||||||
closingBracketToken: @makeToken '>', '>'
|
closingBracketToken: @makeToken '>', '>'
|
||||||
@token ',', 'JSX_COMMA', generated: yes
|
@token ',', 'JSX_COMMA', generated: yes
|
||||||
{tokens, index: end} =
|
{tokens, index: end} =
|
||||||
@matchWithInterpolations INSIDE_CSX, '>', '</', CSX_INTERPOLATION
|
@matchWithInterpolations INSIDE_JSX, '>', '</', JSX_INTERPOLATION
|
||||||
@mergeInterpolationTokens tokens, {endOffset: end}, (value) =>
|
@mergeInterpolationTokens tokens, {endOffset: end}, (value) =>
|
||||||
@validateUnicodeCodePointEscapes value, delimiter: '>'
|
@validateUnicodeCodePointEscapes value, delimiter: '>'
|
||||||
match = CSX_IDENTIFIER.exec(@chunk[end...]) or CSX_FRAGMENT_IDENTIFIER.exec(@chunk[end...])
|
match = JSX_IDENTIFIER.exec(@chunk[end...]) or JSX_FRAGMENT_IDENTIFIER.exec(@chunk[end...])
|
||||||
if not match or match[1] isnt "#{csxTag.name}#{(".#{property}" for property in csxTag.properties).join ''}"
|
if not match or match[1] isnt "#{jsxTag.name}#{(".#{property}" for property in jsxTag.properties).join ''}"
|
||||||
@error "expected corresponding CSX closing tag for #{csxTag.name}",
|
@error "expected corresponding JSX closing tag for #{jsxTag.name}",
|
||||||
csxTag.origin.data.tagNameToken[2]
|
jsxTag.origin.data.tagNameToken[2]
|
||||||
[, fullTagName] = match
|
[, fullTagName] = match
|
||||||
afterTag = end + fullTagName.length
|
afterTag = end + fullTagName.length
|
||||||
if @chunk[afterTag] isnt '>'
|
if @chunk[afterTag] isnt '>'
|
||||||
|
@ -635,16 +634,16 @@ exports.Lexer = class Lexer
|
||||||
closingTagClosingBracketToken: @makeToken '>', '>', offset: end + fullTagName.length
|
closingTagClosingBracketToken: @makeToken '>', '>', offset: end + fullTagName.length
|
||||||
# make the closing tag location data more easily accessible to the grammar
|
# make the closing tag location data more easily accessible to the grammar
|
||||||
addTokenData openingTagToken, endToken.data
|
addTokenData openingTagToken, endToken.data
|
||||||
@csxDepth--
|
@jsxDepth--
|
||||||
return afterTag + 1
|
return afterTag + 1
|
||||||
else
|
else
|
||||||
return 0
|
return 0
|
||||||
else if @atCSXTag 1
|
else if @atJSXTag 1
|
||||||
if firstChar is '}'
|
if firstChar is '}'
|
||||||
@pair firstChar
|
@pair firstChar
|
||||||
if @csxObjAttribute[@csxDepth]
|
if @jsxObjAttribute[@jsxDepth]
|
||||||
@token '}', '}'
|
@token '}', '}'
|
||||||
@csxObjAttribute[@csxDepth] = no
|
@jsxObjAttribute[@jsxDepth] = no
|
||||||
else
|
else
|
||||||
@token ')', ')'
|
@token ')', ')'
|
||||||
@token ',', ','
|
@token ',', ','
|
||||||
|
@ -654,8 +653,8 @@ exports.Lexer = class Lexer
|
||||||
else
|
else
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
atCSXTag: (depth = 0) ->
|
atJSXTag: (depth = 0) ->
|
||||||
return no if @csxDepth is 0
|
return no if @jsxDepth is 0
|
||||||
i = @ends.length - 1
|
i = @ends.length - 1
|
||||||
i-- while @ends[i]?.tag is 'OUTDENT' or depth-- > 0 # Ignore indents.
|
i-- while @ends[i]?.tag is 'OUTDENT' or depth-- > 0 # Ignore indents.
|
||||||
last = @ends[i]
|
last = @ends[i]
|
||||||
|
@ -782,9 +781,9 @@ exports.Lexer = class Lexer
|
||||||
# `#{` if interpolations are desired).
|
# `#{` if interpolations are desired).
|
||||||
# - `delimiter` is the delimiter of the token. Examples are `'`, `"`, `'''`,
|
# - `delimiter` is the delimiter of the token. Examples are `'`, `"`, `'''`,
|
||||||
# `"""` and `///`.
|
# `"""` and `///`.
|
||||||
# - `closingDelimiter` is different from `delimiter` only in CSX
|
# - `closingDelimiter` is different from `delimiter` only in JSX
|
||||||
# - `interpolators` matches the start of an interpolation, for CSX it's both
|
# - `interpolators` matches the start of an interpolation, for JSX it's both
|
||||||
# `{` and `<` (i.e. nested CSX tag)
|
# `{` and `<` (i.e. nested JSX tag)
|
||||||
#
|
#
|
||||||
# This method allows us to have strings within interpolations within strings,
|
# This method allows us to have strings within interpolations within strings,
|
||||||
# ad infinitum.
|
# ad infinitum.
|
||||||
|
@ -1163,17 +1162,17 @@ IDENTIFIER = /// ^
|
||||||
( [^\n\S]* : (?!:) )? # Is this a property name?
|
( [^\n\S]* : (?!:) )? # Is this a property name?
|
||||||
///
|
///
|
||||||
|
|
||||||
CSX_IDENTIFIER = /// ^
|
JSX_IDENTIFIER = /// ^
|
||||||
(?![\d<]) # Must not start with `<`.
|
(?![\d<]) # Must not start with `<`.
|
||||||
( (?: (?!\s)[\.\-$\w\x7f-\uffff] )+ ) # Like `IDENTIFIER`, but includes `-`s and `.`s.
|
( (?: (?!\s)[\.\-$\w\x7f-\uffff] )+ ) # Like `IDENTIFIER`, but includes `-`s and `.`s.
|
||||||
///
|
///
|
||||||
|
|
||||||
# Fragment: <></>
|
# Fragment: <></>
|
||||||
CSX_FRAGMENT_IDENTIFIER = /// ^
|
JSX_FRAGMENT_IDENTIFIER = /// ^
|
||||||
()> # Ends immediately with `>`.
|
()> # Ends immediately with `>`.
|
||||||
///
|
///
|
||||||
|
|
||||||
CSX_ATTRIBUTE = /// ^
|
JSX_ATTRIBUTE = /// ^
|
||||||
(?!\d)
|
(?!\d)
|
||||||
( (?: (?!\s)[\-$\w\x7f-\uffff] )+ ) # Like `IDENTIFIER`, but includes `-`s.
|
( (?: (?!\s)[\-$\w\x7f-\uffff] )+ ) # Like `IDENTIFIER`, but includes `-`s.
|
||||||
( [^\S]* = (?!=) )? # Is this an attribute with a value?
|
( [^\S]* = (?!=) )? # Is this an attribute with a value?
|
||||||
|
@ -1215,15 +1214,15 @@ STRING_DOUBLE = /// ^(?: [^\\"#] | \\[\s\S] | \#(?!\{) )* ///
|
||||||
HEREDOC_SINGLE = /// ^(?: [^\\'] | \\[\s\S] | '(?!'') )* ///
|
HEREDOC_SINGLE = /// ^(?: [^\\'] | \\[\s\S] | '(?!'') )* ///
|
||||||
HEREDOC_DOUBLE = /// ^(?: [^\\"#] | \\[\s\S] | "(?!"") | \#(?!\{) )* ///
|
HEREDOC_DOUBLE = /// ^(?: [^\\"#] | \\[\s\S] | "(?!"") | \#(?!\{) )* ///
|
||||||
|
|
||||||
INSIDE_CSX = /// ^(?:
|
INSIDE_JSX = /// ^(?:
|
||||||
[^
|
[^
|
||||||
\{ # Start of CoffeeScript interpolation.
|
\{ # Start of CoffeeScript interpolation.
|
||||||
< # Maybe CSX tag (`<` not allowed even if bare).
|
< # Maybe JSX tag (`<` not allowed even if bare).
|
||||||
]
|
]
|
||||||
)* /// # Similar to `HEREDOC_DOUBLE` but there is no escaping.
|
)* /// # Similar to `HEREDOC_DOUBLE` but there is no escaping.
|
||||||
CSX_INTERPOLATION = /// ^(?:
|
JSX_INTERPOLATION = /// ^(?:
|
||||||
\{ # CoffeeScript interpolation.
|
\{ # CoffeeScript interpolation.
|
||||||
| <(?!/) # CSX opening tag.
|
| <(?!/) # JSX opening tag.
|
||||||
)///
|
)///
|
||||||
|
|
||||||
HEREDOC_INDENT = /\n+([^\n\S]*)(?=\S)/g
|
HEREDOC_INDENT = /\n+([^\n\S]*)(?=\S)/g
|
||||||
|
|
137
src/nodes.coffee
137
src/nodes.coffee
|
@ -563,14 +563,14 @@ exports.Block = class Block extends Base
|
||||||
len = @expressions.length
|
len = @expressions.length
|
||||||
[..., lastExp] = @expressions
|
[..., lastExp] = @expressions
|
||||||
lastExp = lastExp?.unwrap() or no
|
lastExp = lastExp?.unwrap() or no
|
||||||
# We also need to check that we’re not returning a CSX tag if there’s an
|
# We also need to check that we’re not returning a JSX tag if there’s an
|
||||||
# adjacent one at the same level; JSX doesn’t allow that.
|
# adjacent one at the same level; JSX doesn’t allow that.
|
||||||
if lastExp and lastExp instanceof Parens and lastExp.body.expressions.length > 1
|
if lastExp and lastExp instanceof Parens and lastExp.body.expressions.length > 1
|
||||||
{body:{expressions}} = lastExp
|
{body:{expressions}} = lastExp
|
||||||
[..., penult, last] = expressions
|
[..., penult, last] = expressions
|
||||||
penult = penult.unwrap()
|
penult = penult.unwrap()
|
||||||
last = last.unwrap()
|
last = last.unwrap()
|
||||||
if penult instanceof CSXElement and last instanceof CSXElement
|
if penult instanceof JSXElement and last instanceof JSXElement
|
||||||
expressions[expressions.length - 1].error 'Adjacent JSX elements must be wrapped in an enclosing tag'
|
expressions[expressions.length - 1].error 'Adjacent JSX elements must be wrapped in an enclosing tag'
|
||||||
while len--
|
while len--
|
||||||
expr = @expressions[len]
|
expr = @expressions[len]
|
||||||
|
@ -940,13 +940,13 @@ exports.StringLiteral = class StringLiteral extends Literal
|
||||||
}
|
}
|
||||||
|
|
||||||
compileNode: (o) ->
|
compileNode: (o) ->
|
||||||
return [@makeCode @unquote(yes, yes)] if @csx
|
return [@makeCode @unquote(yes, yes)] if @jsx
|
||||||
super o
|
super o
|
||||||
|
|
||||||
unquote: (doubleQuote = no, csx = no) ->
|
unquote: (doubleQuote = no, jsx = no) ->
|
||||||
unquoted = @value[1...-1]
|
unquoted = @value[1...-1]
|
||||||
unquoted = unquoted.replace /\\"/g, '"' if doubleQuote
|
unquoted = unquoted.replace /\\"/g, '"' if doubleQuote
|
||||||
unquoted = unquoted.replace /\\n/g, '\n' if csx
|
unquoted = unquoted.replace /\\n/g, '\n' if jsx
|
||||||
unquoted
|
unquoted
|
||||||
|
|
||||||
# `StringLiteral`s can represent either entire literal strings
|
# `StringLiteral`s can represent either entire literal strings
|
||||||
|
@ -1025,7 +1025,7 @@ exports.IdentifierLiteral = class IdentifierLiteral extends Literal
|
||||||
iterator @
|
iterator @
|
||||||
|
|
||||||
astType: ->
|
astType: ->
|
||||||
if @csx
|
if @jsx
|
||||||
'JSXIdentifier'
|
'JSXIdentifier'
|
||||||
else
|
else
|
||||||
'Identifier'
|
'Identifier'
|
||||||
|
@ -1034,27 +1034,11 @@ exports.IdentifierLiteral = class IdentifierLiteral extends Literal
|
||||||
return
|
return
|
||||||
name: @value
|
name: @value
|
||||||
|
|
||||||
exports.CSXTag = class CSXTag extends IdentifierLiteral
|
|
||||||
constructor: (value, {
|
|
||||||
@tagNameLocationData
|
|
||||||
@closingTagOpeningBracketLocationData
|
|
||||||
@closingTagSlashLocationData
|
|
||||||
@closingTagNameLocationData
|
|
||||||
@closingTagClosingBracketLocationData
|
|
||||||
}) ->
|
|
||||||
super value
|
|
||||||
|
|
||||||
astType: -> 'JSXIdentifier'
|
|
||||||
|
|
||||||
astProperties: ->
|
|
||||||
return
|
|
||||||
name: @value
|
|
||||||
|
|
||||||
exports.PropertyName = class PropertyName extends Literal
|
exports.PropertyName = class PropertyName extends Literal
|
||||||
isAssignable: YES
|
isAssignable: YES
|
||||||
|
|
||||||
astType: ->
|
astType: ->
|
||||||
if @csx
|
if @jsx
|
||||||
'JSXIdentifier'
|
'JSXIdentifier'
|
||||||
else
|
else
|
||||||
'Identifier'
|
'Identifier'
|
||||||
|
@ -1269,7 +1253,7 @@ exports.Value = class Value extends Base
|
||||||
@isUndefined() or @isNull() or @isBoolean()
|
@isUndefined() or @isNull() or @isBoolean()
|
||||||
|
|
||||||
isStatement : (o) -> not @properties.length and @base.isStatement o
|
isStatement : (o) -> not @properties.length and @base.isStatement o
|
||||||
isCSXTag : -> @base instanceof CSXTag
|
isJSXTag : -> @base instanceof JSXTag
|
||||||
assigns : (name) -> not @properties.length and @base.assigns name
|
assigns : (name) -> not @properties.length and @base.assigns name
|
||||||
jumps : (o) -> not @properties.length and @base.jumps o
|
jumps : (o) -> not @properties.length and @base.jumps o
|
||||||
|
|
||||||
|
@ -1395,7 +1379,7 @@ exports.Value = class Value extends Base
|
||||||
super o, level
|
super o, level
|
||||||
|
|
||||||
astType: ->
|
astType: ->
|
||||||
if @isCSXTag()
|
if @isJSXTag()
|
||||||
'JSXMemberExpression'
|
'JSXMemberExpression'
|
||||||
else
|
else
|
||||||
'MemberExpression'
|
'MemberExpression'
|
||||||
|
@ -1405,7 +1389,7 @@ exports.Value = class Value extends Base
|
||||||
# a child `Value` node assigned to the `object` property.
|
# a child `Value` node assigned to the `object` property.
|
||||||
astProperties: (o) ->
|
astProperties: (o) ->
|
||||||
[..., property] = @properties
|
[..., property] = @properties
|
||||||
property.name.csx = yes if @isCSXTag()
|
property.name.jsx = yes if @isJSXTag()
|
||||||
computed = property instanceof Index or property.name?.unwrap() not instanceof PropertyName
|
computed = property instanceof Index or property.name?.unwrap() not instanceof PropertyName
|
||||||
return {
|
return {
|
||||||
object: @object().ast o, LEVEL_ACCESS
|
object: @object().ast o, LEVEL_ACCESS
|
||||||
|
@ -1416,7 +1400,7 @@ exports.Value = class Value extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
astLocationData: ->
|
astLocationData: ->
|
||||||
return super() unless @isCSXTag()
|
return super() unless @isJSXTag()
|
||||||
# don't include leading < of JSX tag in location data
|
# don't include leading < of JSX tag in location data
|
||||||
mergeAstLocationData(
|
mergeAstLocationData(
|
||||||
jisonLocationDataToAstLocationData(@base.tagNameLocationData),
|
jisonLocationDataToAstLocationData(@base.tagNameLocationData),
|
||||||
|
@ -1497,15 +1481,29 @@ exports.LineComment = class LineComment extends Base
|
||||||
fragment.isComment = fragment.isLineComment = yes
|
fragment.isComment = fragment.isLineComment = yes
|
||||||
fragment
|
fragment
|
||||||
|
|
||||||
#### CSX
|
#### JSX
|
||||||
|
|
||||||
exports.CSXIdentifier = class CSXIdentifier extends IdentifierLiteral
|
exports.JSXIdentifier = class JSXIdentifier extends IdentifierLiteral
|
||||||
astType: -> 'JSXIdentifier'
|
astType: -> 'JSXIdentifier'
|
||||||
|
|
||||||
exports.CSXExpressionContainer = class CSXExpressionContainer extends Base
|
exports.JSXTag = class JSXTag extends JSXIdentifier
|
||||||
|
constructor: (value, {
|
||||||
|
@tagNameLocationData
|
||||||
|
@closingTagOpeningBracketLocationData
|
||||||
|
@closingTagSlashLocationData
|
||||||
|
@closingTagNameLocationData
|
||||||
|
@closingTagClosingBracketLocationData
|
||||||
|
}) ->
|
||||||
|
super value
|
||||||
|
|
||||||
|
astProperties: ->
|
||||||
|
return
|
||||||
|
name: @value
|
||||||
|
|
||||||
|
exports.JSXExpressionContainer = class JSXExpressionContainer extends Base
|
||||||
constructor: (@expression, {locationData} = {}) ->
|
constructor: (@expression, {locationData} = {}) ->
|
||||||
super()
|
super()
|
||||||
@expression.csxAttribute = yes
|
@expression.jsxAttribute = yes
|
||||||
@locationData = locationData ? @expression.locationData
|
@locationData = locationData ? @expression.locationData
|
||||||
|
|
||||||
children: ['expression']
|
children: ['expression']
|
||||||
|
@ -1513,23 +1511,18 @@ exports.CSXExpressionContainer = class CSXExpressionContainer extends Base
|
||||||
compileNode: (o) ->
|
compileNode: (o) ->
|
||||||
@expression.compileNode(o)
|
@expression.compileNode(o)
|
||||||
|
|
||||||
astType: -> 'JSXExpressionContainer'
|
|
||||||
|
|
||||||
astProperties: ->
|
astProperties: ->
|
||||||
return
|
return
|
||||||
expression: @expression.ast()
|
expression: @expression.ast()
|
||||||
|
|
||||||
exports.CSXEmptyExpression = class CSXEmptyExpression extends Base
|
exports.JSXEmptyExpression = class JSXEmptyExpression extends Base
|
||||||
astType: -> 'JSXEmptyExpression'
|
|
||||||
|
|
||||||
exports.CSXText = class CSXText extends Base
|
exports.JSXText = class JSXText extends Base
|
||||||
constructor: (stringLiteral) ->
|
constructor: (stringLiteral) ->
|
||||||
super()
|
super()
|
||||||
@value = stringLiteral.unquote yes, yes
|
@value = stringLiteral.unquote yes, yes
|
||||||
@locationData = stringLiteral.locationData
|
@locationData = stringLiteral.locationData
|
||||||
|
|
||||||
astType: -> 'JSXText'
|
|
||||||
|
|
||||||
astProperties: ->
|
astProperties: ->
|
||||||
return {
|
return {
|
||||||
@value
|
@value
|
||||||
|
@ -1537,7 +1530,7 @@ exports.CSXText = class CSXText extends Base
|
||||||
raw: @value
|
raw: @value
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.CSXAttribute = class CSXAttribute extends Base
|
exports.JSXAttribute = class JSXAttribute extends Base
|
||||||
constructor: ({@name, value}) ->
|
constructor: ({@name, value}) ->
|
||||||
super()
|
super()
|
||||||
@value =
|
@value =
|
||||||
|
@ -1546,7 +1539,7 @@ exports.CSXAttribute = class CSXAttribute extends Base
|
||||||
if value instanceof StringLiteral
|
if value instanceof StringLiteral
|
||||||
value
|
value
|
||||||
else
|
else
|
||||||
new CSXExpressionContainer value
|
new JSXExpressionContainer value
|
||||||
else
|
else
|
||||||
null
|
null
|
||||||
@value?.comments = value.comments
|
@value?.comments = value.comments
|
||||||
|
@ -1559,14 +1552,12 @@ exports.CSXAttribute = class CSXAttribute extends Base
|
||||||
val = @value.compileToFragments o, LEVEL_LIST
|
val = @value.compileToFragments o, LEVEL_LIST
|
||||||
compiledName.concat @makeCode('='), val
|
compiledName.concat @makeCode('='), val
|
||||||
|
|
||||||
astType: -> 'JSXAttribute'
|
|
||||||
|
|
||||||
astProperties: ->
|
astProperties: ->
|
||||||
return
|
return
|
||||||
name: @name.ast()
|
name: @name.ast()
|
||||||
value: @value?.ast() ? null
|
value: @value?.ast() ? null
|
||||||
|
|
||||||
exports.CSXAttributes = class CSXAttributes extends Base
|
exports.JSXAttributes = class JSXAttributes extends Base
|
||||||
constructor: (arr) ->
|
constructor: (arr) ->
|
||||||
super()
|
super()
|
||||||
@attributes = []
|
@attributes = []
|
||||||
|
@ -1575,21 +1566,21 @@ exports.CSXAttributes = class CSXAttributes extends Base
|
||||||
{base} = object
|
{base} = object
|
||||||
if base instanceof IdentifierLiteral
|
if base instanceof IdentifierLiteral
|
||||||
# attribute with no value eg disabled
|
# attribute with no value eg disabled
|
||||||
attribute = new CSXAttribute name: new CSXIdentifier(base.value).withLocationDataAndCommentsFrom base
|
attribute = new JSXAttribute name: new JSXIdentifier(base.value).withLocationDataAndCommentsFrom base
|
||||||
attribute.locationData = base.locationData
|
attribute.locationData = base.locationData
|
||||||
@attributes.push attribute
|
@attributes.push attribute
|
||||||
else if not base.generated
|
else if not base.generated
|
||||||
# object spread attribute eg {...props}
|
# object spread attribute eg {...props}
|
||||||
attribute = base.properties[0]
|
attribute = base.properties[0]
|
||||||
attribute.csx = yes
|
attribute.jsx = yes
|
||||||
attribute.locationData = base.locationData
|
attribute.locationData = base.locationData
|
||||||
@attributes.push attribute
|
@attributes.push attribute
|
||||||
else
|
else
|
||||||
# Obj containing attributes with values eg a="b" c={d}
|
# Obj containing attributes with values eg a="b" c={d}
|
||||||
for property in base.properties
|
for property in base.properties
|
||||||
{variable, value} = property
|
{variable, value} = property
|
||||||
attribute = new CSXAttribute {
|
attribute = new JSXAttribute {
|
||||||
name: new CSXIdentifier(variable.base.value).withLocationDataAndCommentsFrom variable.base
|
name: new JSXIdentifier(variable.base.value).withLocationDataAndCommentsFrom variable.base
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
attribute.locationData = property.locationData
|
attribute.locationData = property.locationData
|
||||||
|
@ -1604,7 +1595,7 @@ exports.CSXAttributes = class CSXAttributes extends Base
|
||||||
properties = attribute?.properties or []
|
properties = attribute?.properties or []
|
||||||
if not (attribute instanceof Obj or attribute instanceof IdentifierLiteral) or (attribute instanceof Obj and not attribute.generated and (properties.length > 1 or not (properties[0] instanceof Splat)))
|
if not (attribute instanceof Obj or attribute instanceof IdentifierLiteral) or (attribute instanceof Obj and not attribute.generated and (properties.length > 1 or not (properties[0] instanceof Splat)))
|
||||||
object.error """
|
object.error """
|
||||||
Unexpected token. Allowed CSX attributes are: id="val", src={source}, {props...} or attribute.
|
Unexpected token. Allowed JSX attributes are: id="val", src={source}, {props...} or attribute.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
compileNode: (o) ->
|
compileNode: (o) ->
|
||||||
|
@ -1617,15 +1608,15 @@ exports.CSXAttributes = class CSXAttributes extends Base
|
||||||
ast: (o) ->
|
ast: (o) ->
|
||||||
attribute.ast(o) for attribute in @attributes
|
attribute.ast(o) for attribute in @attributes
|
||||||
|
|
||||||
# Node for a CSX element
|
# Node for a JSX element
|
||||||
exports.CSXElement = class CSXElement extends Base
|
exports.JSXElement = class JSXElement extends Base
|
||||||
constructor: ({@tagName, @attributes, @content}) ->
|
constructor: ({@tagName, @attributes, @content}) ->
|
||||||
super()
|
super()
|
||||||
|
|
||||||
children: ['tagName', 'attributes', 'content']
|
children: ['tagName', 'attributes', 'content']
|
||||||
|
|
||||||
compileNode: (o) ->
|
compileNode: (o) ->
|
||||||
@content?.base.csx = yes
|
@content?.base.jsx = yes
|
||||||
fragments = [@makeCode('<')]
|
fragments = [@makeCode('<')]
|
||||||
fragments.push (tag = @tagName.compileToFragments(o, LEVEL_ACCESS))...
|
fragments.push (tag = @tagName.compileToFragments(o, LEVEL_ACCESS))...
|
||||||
fragments.push @attributes.compileToFragments(o)...
|
fragments.push @attributes.compileToFragments(o)...
|
||||||
|
@ -1719,23 +1710,23 @@ exports.CSXElement = class CSXElement extends Base
|
||||||
content = @content.unwrapAll()
|
content = @content.unwrapAll()
|
||||||
children =
|
children =
|
||||||
if content instanceof StringLiteral
|
if content instanceof StringLiteral
|
||||||
[new CSXText content]
|
[new JSXText content]
|
||||||
else # StringWithInterpolations
|
else # StringWithInterpolations
|
||||||
for element in @content.unwrapAll().extractElements o, includeInterpolationWrappers: yes
|
for element in @content.unwrapAll().extractElements o, includeInterpolationWrappers: yes
|
||||||
if element instanceof StringLiteral
|
if element instanceof StringLiteral
|
||||||
new CSXText element
|
new JSXText element
|
||||||
else # Interpolation
|
else # Interpolation
|
||||||
{expression} = element
|
{expression} = element
|
||||||
unless expression?
|
unless expression?
|
||||||
new CSXEmptyExpression().withLocationDataFrom element
|
new JSXEmptyExpression().withLocationDataFrom element
|
||||||
else
|
else
|
||||||
unwrapped = expression.unwrapAll()
|
unwrapped = expression.unwrapAll()
|
||||||
if unwrapped instanceof CSXElement
|
if unwrapped instanceof JSXElement
|
||||||
unwrapped
|
unwrapped
|
||||||
else
|
else
|
||||||
new CSXExpressionContainer unwrapped, locationData: element.locationData
|
new JSXExpressionContainer unwrapped, locationData: element.locationData
|
||||||
|
|
||||||
child.ast(o) for child in children when not (child instanceof CSXText and child.value.length is 0)
|
child.ast(o) for child in children when not (child instanceof JSXText and child.value.length is 0)
|
||||||
|
|
||||||
astProperties: (o) ->
|
astProperties: (o) ->
|
||||||
Object.assign(
|
Object.assign(
|
||||||
|
@ -1765,10 +1756,10 @@ exports.Call = class Call extends Base
|
||||||
if @variable instanceof Value and @variable.isNotCallable()
|
if @variable instanceof Value and @variable.isNotCallable()
|
||||||
@variable.error "literal is not a function"
|
@variable.error "literal is not a function"
|
||||||
|
|
||||||
if @variable.base instanceof CSXTag
|
if @variable.base instanceof JSXTag
|
||||||
return new CSXElement(
|
return new JSXElement(
|
||||||
tagName: @variable
|
tagName: @variable
|
||||||
attributes: new CSXAttributes @args[0].base
|
attributes: new JSXAttributes @args[0].base
|
||||||
content: @args[1]
|
content: @args[1]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -3905,13 +3896,13 @@ exports.Splat = class Splat extends Base
|
||||||
|
|
||||||
compileNode: (o) ->
|
compileNode: (o) ->
|
||||||
compiledSplat = [@makeCode('...'), @name.compileToFragments(o, LEVEL_OP)...]
|
compiledSplat = [@makeCode('...'), @name.compileToFragments(o, LEVEL_OP)...]
|
||||||
return compiledSplat unless @csx
|
return compiledSplat unless @jsx
|
||||||
return [@makeCode('{'), compiledSplat..., @makeCode('}')]
|
return [@makeCode('{'), compiledSplat..., @makeCode('}')]
|
||||||
|
|
||||||
unwrap: -> @name
|
unwrap: -> @name
|
||||||
|
|
||||||
astType: ->
|
astType: ->
|
||||||
if @csx
|
if @jsx
|
||||||
'JSXSpreadAttribute'
|
'JSXSpreadAttribute'
|
||||||
else if @lhs
|
else if @lhs
|
||||||
'RestElement'
|
'RestElement'
|
||||||
|
@ -4527,7 +4518,7 @@ exports.Parens = class Parens extends Base
|
||||||
# by comment-based type annotations from JavaScript labels.
|
# by comment-based type annotations from JavaScript labels.
|
||||||
shouldWrapComment = expr.comments?.some(
|
shouldWrapComment = expr.comments?.some(
|
||||||
(comment) -> comment.here and not comment.unshift and not comment.newLine)
|
(comment) -> comment.here and not comment.unshift and not comment.newLine)
|
||||||
if expr instanceof Value and expr.isAtomic() and not @csxAttribute and not shouldWrapComment
|
if expr instanceof Value and expr.isAtomic() and not @jsxAttribute and not shouldWrapComment
|
||||||
expr.front = @front
|
expr.front = @front
|
||||||
return expr.compileToFragments o
|
return expr.compileToFragments o
|
||||||
fragments = expr.compileToFragments o, LEVEL_PAREN
|
fragments = expr.compileToFragments o, LEVEL_PAREN
|
||||||
|
@ -4535,7 +4526,7 @@ exports.Parens = class Parens extends Base
|
||||||
expr instanceof Op and not expr.isInOperator() or expr.unwrap() instanceof Call or
|
expr instanceof Op and not expr.isInOperator() or expr.unwrap() instanceof Call or
|
||||||
(expr instanceof For and expr.returns)
|
(expr instanceof For and expr.returns)
|
||||||
) and (o.level < LEVEL_COND or fragments.length <= 3)
|
) and (o.level < LEVEL_COND or fragments.length <= 3)
|
||||||
return @wrapInBraces fragments if @csxAttribute
|
return @wrapInBraces fragments if @jsxAttribute
|
||||||
if bare then fragments else @wrapInParentheses fragments
|
if bare then fragments else @wrapInParentheses fragments
|
||||||
|
|
||||||
ast: (o) -> @body.unwrap().ast o, LEVEL_PAREN
|
ast: (o) -> @body.unwrap().ast o, LEVEL_PAREN
|
||||||
|
@ -4580,7 +4571,7 @@ exports.StringWithInterpolations = class StringWithInterpolations extends Base
|
||||||
comment.unshift = yes
|
comment.unshift = yes
|
||||||
comment.newLine = yes
|
comment.newLine = yes
|
||||||
attachCommentsToNode salvagedComments, node
|
attachCommentsToNode salvagedComments, node
|
||||||
if (unwrapped = node.expression?.unwrapAll()) instanceof PassthroughLiteral and unwrapped.generated and not @csx
|
if (unwrapped = node.expression?.unwrapAll()) instanceof PassthroughLiteral and unwrapped.generated and not @jsx
|
||||||
commentPlaceholder = new StringLiteral('').withLocationDataFrom node
|
commentPlaceholder = new StringLiteral('').withLocationDataFrom node
|
||||||
commentPlaceholder.comments = unwrapped.comments
|
commentPlaceholder.comments = unwrapped.comments
|
||||||
(commentPlaceholder.comments ?= []).push node.comments... if node.comments
|
(commentPlaceholder.comments ?= []).push node.comments... if node.comments
|
||||||
|
@ -4606,19 +4597,19 @@ exports.StringWithInterpolations = class StringWithInterpolations extends Base
|
||||||
compileNode: (o) ->
|
compileNode: (o) ->
|
||||||
@comments ?= @startQuote?.comments
|
@comments ?= @startQuote?.comments
|
||||||
|
|
||||||
if @csxAttribute
|
if @jsxAttribute
|
||||||
wrapped = new Parens new StringWithInterpolations @body
|
wrapped = new Parens new StringWithInterpolations @body
|
||||||
wrapped.csxAttribute = yes
|
wrapped.jsxAttribute = yes
|
||||||
return wrapped.compileNode o
|
return wrapped.compileNode o
|
||||||
|
|
||||||
elements = @extractElements o
|
elements = @extractElements o
|
||||||
|
|
||||||
fragments = []
|
fragments = []
|
||||||
fragments.push @makeCode '`' unless @csx
|
fragments.push @makeCode '`' unless @jsx
|
||||||
for element in elements
|
for element in elements
|
||||||
if element instanceof StringLiteral
|
if element instanceof StringLiteral
|
||||||
element.value = element.unquote yes, @csx
|
element.value = element.unquote yes, @jsx
|
||||||
unless @csx
|
unless @jsx
|
||||||
# Backticks and `${` inside template literals must be escaped.
|
# Backticks and `${` inside template literals must be escaped.
|
||||||
element.value = element.value.replace /(\\*)(`|\$\{)/g, (match, backslashes, toBeEscaped) ->
|
element.value = element.value.replace /(\\*)(`|\$\{)/g, (match, backslashes, toBeEscaped) ->
|
||||||
if backslashes.length % 2 is 0
|
if backslashes.length % 2 is 0
|
||||||
|
@ -4627,7 +4618,7 @@ exports.StringWithInterpolations = class StringWithInterpolations extends Base
|
||||||
match
|
match
|
||||||
fragments.push element.compileToFragments(o)...
|
fragments.push element.compileToFragments(o)...
|
||||||
else
|
else
|
||||||
fragments.push @makeCode '$' unless @csx
|
fragments.push @makeCode '$' unless @jsx
|
||||||
code = element.compileToFragments(o, LEVEL_PAREN)
|
code = element.compileToFragments(o, LEVEL_PAREN)
|
||||||
if not @isNestedTag(element) or
|
if not @isNestedTag(element) or
|
||||||
code.some((fragment) -> fragment.comments?.some((comment) -> comment.here is no))
|
code.some((fragment) -> fragment.comments?.some((comment) -> comment.here is no))
|
||||||
|
@ -4641,12 +4632,12 @@ exports.StringWithInterpolations = class StringWithInterpolations extends Base
|
||||||
code[0].isStringWithInterpolations = yes
|
code[0].isStringWithInterpolations = yes
|
||||||
code[code.length - 1].isStringWithInterpolations = yes
|
code[code.length - 1].isStringWithInterpolations = yes
|
||||||
fragments.push code...
|
fragments.push code...
|
||||||
fragments.push @makeCode '`' unless @csx
|
fragments.push @makeCode '`' unless @jsx
|
||||||
fragments
|
fragments
|
||||||
|
|
||||||
isNestedTag: (element) ->
|
isNestedTag: (element) ->
|
||||||
call = element.unwrapAll?()
|
call = element.unwrapAll?()
|
||||||
@csx and call instanceof CSXElement
|
@jsx and call instanceof JSXElement
|
||||||
|
|
||||||
astType: -> 'TemplateLiteral'
|
astType: -> 'TemplateLiteral'
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ exports.Rewriter = class Rewriter
|
||||||
@addImplicitBracesAndParens()
|
@addImplicitBracesAndParens()
|
||||||
@rescueStowawayComments()
|
@rescueStowawayComments()
|
||||||
@addLocationDataToGeneratedTokens()
|
@addLocationDataToGeneratedTokens()
|
||||||
@enforceValidCSXAttributes()
|
@enforceValidJSXAttributes()
|
||||||
@fixOutdentLocationData()
|
@fixOutdentLocationData()
|
||||||
@exposeTokenDataToGrammar()
|
@exposeTokenDataToGrammar()
|
||||||
if process?.env?.DEBUG_REWRITTEN_TOKEN_STREAM
|
if process?.env?.DEBUG_REWRITTEN_TOKEN_STREAM
|
||||||
|
@ -409,10 +409,10 @@ exports.Rewriter = class Rewriter
|
||||||
endImplicitObject i + offset
|
endImplicitObject i + offset
|
||||||
return forward(1)
|
return forward(1)
|
||||||
|
|
||||||
# Make sure only strings and wrapped expressions are used in CSX attributes.
|
# Make sure only strings and wrapped expressions are used in JSX attributes.
|
||||||
enforceValidCSXAttributes: ->
|
enforceValidJSXAttributes: ->
|
||||||
@scanTokens (token, i, tokens) ->
|
@scanTokens (token, i, tokens) ->
|
||||||
if token.csxColon
|
if token.jsxColon
|
||||||
next = tokens[i + 1]
|
next = tokens[i + 1]
|
||||||
if next[0] not in ['STRING_START', 'STRING', '(']
|
if next[0] not in ['STRING_START', 'STRING', '(']
|
||||||
throwSyntaxError 'expected wrapped or quoted JSX attribute', next[2]
|
throwSyntaxError 'expected wrapped or quoted JSX attribute', next[2]
|
||||||
|
@ -722,7 +722,7 @@ IMPLICIT_FUNC = ['IDENTIFIER', 'PROPERTY', 'SUPER', ')', 'CALL_END', ']', 'IN
|
||||||
|
|
||||||
# If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
|
# If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
|
||||||
IMPLICIT_CALL = [
|
IMPLICIT_CALL = [
|
||||||
'IDENTIFIER', 'CSX_TAG', 'PROPERTY', 'NUMBER', 'INFINITY', 'NAN'
|
'IDENTIFIER', 'JSX_TAG', 'PROPERTY', 'NUMBER', 'INFINITY', 'NAN'
|
||||||
'STRING', 'STRING_START', 'REGEX', 'REGEX_START', 'JS'
|
'STRING', 'STRING_START', 'REGEX', 'REGEX_START', 'JS'
|
||||||
'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS'
|
'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS'
|
||||||
'UNDEFINED', 'NULL', 'BOOL'
|
'UNDEFINED', 'NULL', 'BOOL'
|
||||||
|
|
|
@ -200,7 +200,7 @@ test "AST as expected for IdentifierLiteral node", ->
|
||||||
type: 'Identifier'
|
type: 'Identifier'
|
||||||
name: 'id'
|
name: 'id'
|
||||||
|
|
||||||
test "AST as expected for CSXTag node", ->
|
test "AST as expected for JSXTag node", ->
|
||||||
testExpression '<CSXY />',
|
testExpression '<CSXY />',
|
||||||
type: 'JSXElement'
|
type: 'JSXElement'
|
||||||
openingElement:
|
openingElement:
|
||||||
|
|
|
@ -2241,7 +2241,7 @@ test "AST location data as expected for Existence node", ->
|
||||||
line: 1
|
line: 1
|
||||||
column: 7
|
column: 7
|
||||||
|
|
||||||
test "AST location data as expected for CSXTag node", ->
|
test "AST location data as expected for JSXTag node", ->
|
||||||
testAstLocationData '<CSXY />',
|
testAstLocationData '<CSXY />',
|
||||||
type: 'JSXElement'
|
type: 'JSXElement'
|
||||||
openingElement:
|
openingElement:
|
||||||
|
|
|
@ -725,7 +725,7 @@ test "Block comment in an interpolated string", ->
|
||||||
eqJS '"a#{### Comment ###}b"', '`a${/* Comment */""}b`;'
|
eqJS '"a#{### Comment ###}b"', '`a${/* Comment */""}b`;'
|
||||||
eqJS '"a#{### 1 ###}b#{### 2 ###}c"', '`a${/* 1 */""}b${/* 2 */""}c`;'
|
eqJS '"a#{### 1 ###}b#{### 2 ###}c"', '`a${/* 1 */""}b${/* 2 */""}c`;'
|
||||||
|
|
||||||
test "#4629: Block comment in CSX interpolation", ->
|
test "#4629: Block comment in JSX interpolation", ->
|
||||||
eqJS '<div>{### Comment ###}</div>', '<div>{/* Comment */}</div>;'
|
eqJS '<div>{### Comment ###}</div>', '<div>{/* Comment */}</div>;'
|
||||||
eqJS '''
|
eqJS '''
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -1589,17 +1589,17 @@ test "#4248: Unicode code point escapes", ->
|
||||||
\ ^\^^^^^^^^^^^^^
|
\ ^\^^^^^^^^^^^^^
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test "CSX error: non-matching tag names", ->
|
test "JSX error: non-matching tag names", ->
|
||||||
assertErrorFormat '''
|
assertErrorFormat '''
|
||||||
<div><span></div></span>
|
<div><span></div></span>
|
||||||
''',
|
''',
|
||||||
'''
|
'''
|
||||||
[stdin]:1:7: error: expected corresponding CSX closing tag for span
|
[stdin]:1:7: error: expected corresponding JSX closing tag for span
|
||||||
<div><span></div></span>
|
<div><span></div></span>
|
||||||
^^^^
|
^^^^
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test "CSX error: bare expressions not allowed", ->
|
test "JSX error: bare expressions not allowed", ->
|
||||||
assertErrorFormat '''
|
assertErrorFormat '''
|
||||||
<div x=3 />
|
<div x=3 />
|
||||||
''',
|
''',
|
||||||
|
@ -1609,7 +1609,7 @@ test "CSX error: bare expressions not allowed", ->
|
||||||
^
|
^
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test "CSX error: unescaped opening tag angle bracket disallowed", ->
|
test "JSX error: unescaped opening tag angle bracket disallowed", ->
|
||||||
assertErrorFormat '''
|
assertErrorFormat '''
|
||||||
<Person><<</Person>
|
<Person><<</Person>
|
||||||
''',
|
''',
|
||||||
|
@ -1619,7 +1619,7 @@ test "CSX error: unescaped opening tag angle bracket disallowed", ->
|
||||||
^^
|
^^
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test "CSX error: ambiguous tag-like expression", ->
|
test "JSX error: ambiguous tag-like expression", ->
|
||||||
assertErrorFormat '''
|
assertErrorFormat '''
|
||||||
x = a <b > c
|
x = a <b > c
|
||||||
''',
|
''',
|
||||||
|
@ -1629,51 +1629,51 @@ test "CSX error: ambiguous tag-like expression", ->
|
||||||
^
|
^
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test 'CSX error: invalid attributes', ->
|
test 'JSX error: invalid attributes', ->
|
||||||
assertErrorFormatAst '''
|
assertErrorFormatAst '''
|
||||||
<div a="b" {props} />
|
<div a="b" {props} />
|
||||||
''', '''
|
''', '''
|
||||||
[stdin]:1:12: error: Unexpected token. Allowed CSX attributes are: id="val", src={source}, {props...} or attribute.
|
[stdin]:1:12: error: Unexpected token. Allowed JSX attributes are: id="val", src={source}, {props...} or attribute.
|
||||||
<div a="b" {props} />
|
<div a="b" {props} />
|
||||||
^^^^^^^
|
^^^^^^^
|
||||||
'''
|
'''
|
||||||
assertErrorFormatAst '''
|
assertErrorFormatAst '''
|
||||||
<div a={b} {a:{b}} />
|
<div a={b} {a:{b}} />
|
||||||
''', '''
|
''', '''
|
||||||
[stdin]:1:12: error: Unexpected token. Allowed CSX attributes are: id="val", src={source}, {props...} or attribute.
|
[stdin]:1:12: error: Unexpected token. Allowed JSX attributes are: id="val", src={source}, {props...} or attribute.
|
||||||
<div a={b} {a:{b}} />
|
<div a={b} {a:{b}} />
|
||||||
^^^^^^^
|
^^^^^^^
|
||||||
'''
|
'''
|
||||||
assertErrorFormatAst '''
|
assertErrorFormatAst '''
|
||||||
<div {"#{a}"} />
|
<div {"#{a}"} />
|
||||||
''', '''
|
''', '''
|
||||||
[stdin]:1:6: error: Unexpected token. Allowed CSX attributes are: id="val", src={source}, {props...} or attribute.
|
[stdin]:1:6: error: Unexpected token. Allowed JSX attributes are: id="val", src={source}, {props...} or attribute.
|
||||||
<div {"#{a}"} />
|
<div {"#{a}"} />
|
||||||
^^^^^^^^
|
^^^^^^^^
|
||||||
'''
|
'''
|
||||||
assertErrorFormatAst '''
|
assertErrorFormatAst '''
|
||||||
<div props... />
|
<div props... />
|
||||||
''', '''
|
''', '''
|
||||||
[stdin]:1:11: error: Unexpected token. Allowed CSX attributes are: id="val", src={source}, {props...} or attribute.
|
[stdin]:1:11: error: Unexpected token. Allowed JSX attributes are: id="val", src={source}, {props...} or attribute.
|
||||||
<div props... />
|
<div props... />
|
||||||
^^^
|
^^^
|
||||||
'''
|
'''
|
||||||
assertErrorFormatAst '''
|
assertErrorFormatAst '''
|
||||||
<div {a:"b", props..., c:d()} />
|
<div {a:"b", props..., c:d()} />
|
||||||
''', '''
|
''', '''
|
||||||
[stdin]:1:6: error: Unexpected token. Allowed CSX attributes are: id="val", src={source}, {props...} or attribute.
|
[stdin]:1:6: error: Unexpected token. Allowed JSX attributes are: id="val", src={source}, {props...} or attribute.
|
||||||
<div {a:"b", props..., c:d()} />
|
<div {a:"b", props..., c:d()} />
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
'''
|
'''
|
||||||
assertErrorFormatAst '''
|
assertErrorFormatAst '''
|
||||||
<div {props..., a, b} />
|
<div {props..., a, b} />
|
||||||
''', '''
|
''', '''
|
||||||
[stdin]:1:6: error: Unexpected token. Allowed CSX attributes are: id="val", src={source}, {props...} or attribute.
|
[stdin]:1:6: error: Unexpected token. Allowed JSX attributes are: id="val", src={source}, {props...} or attribute.
|
||||||
<div {props..., a, b} />
|
<div {props..., a, b} />
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test '#5034: CSX error: Adjacent JSX elements must be wrapped in an enclosing tag', ->
|
test '#5034: JSX error: Adjacent JSX elements must be wrapped in an enclosing tag', ->
|
||||||
assertErrorFormat '''
|
assertErrorFormat '''
|
||||||
render = -> (
|
render = -> (
|
||||||
<Row>a</Row>
|
<Row>a</Row>
|
||||||
|
|
|
@ -184,7 +184,7 @@ test 'escaped CoffeeScript attribute over multiple lines', ->
|
||||||
<Person name={test() ? 'yes' : 'no'} />;
|
<Person name={test() ? 'yes' : 'no'} />;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test 'multiple line escaped CoffeeScript with nested CSX', ->
|
test 'multiple line escaped CoffeeScript with nested JSX', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
<Person name={
|
<Person name={
|
||||||
if test()
|
if test()
|
||||||
|
@ -222,7 +222,7 @@ test 'multiple line escaped CoffeeScript with nested CSX', ->
|
||||||
</Person>;
|
</Person>;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test 'nested CSX within an attribute, with object attr value', ->
|
test 'nested JSX within an attribute, with object attr value', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
<Company>
|
<Company>
|
||||||
<Person name={<NameComponent attr3={ {'a': {}, b: '{'} } />} />
|
<Person name={<NameComponent attr3={ {'a': {}, b: '{'} } />} />
|
||||||
|
@ -248,7 +248,7 @@ test 'complex nesting', ->
|
||||||
})} />;
|
})} />;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test 'multiline tag with nested CSX within an attribute', ->
|
test 'multiline tag with nested JSX within an attribute', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
<Person
|
<Person
|
||||||
name={
|
name={
|
||||||
|
@ -299,7 +299,7 @@ test 'lots of attributes', ->
|
||||||
<Person eyes={2} friends={getFriends()} popular="yes" active={isActive() ? 'active' : 'inactive'} data-attr='works' checked check={me_out} />;
|
<Person eyes={2} friends={getFriends()} popular="yes" active={isActive() ? 'active' : 'inactive'} data-attr='works' checked check={me_out} />;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# TODO: fix partially indented CSX
|
# TODO: fix partially indented JSX
|
||||||
# test 'multiline elements', ->
|
# test 'multiline elements', ->
|
||||||
# eqJS '''
|
# eqJS '''
|
||||||
# <div something={
|
# <div something={
|
||||||
|
@ -378,7 +378,7 @@ test 'heregex', ->
|
||||||
<Person />;
|
<Person />;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test 'comment within CSX is not treated as comment', ->
|
test 'comment within JSX is not treated as comment', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
<Person>
|
<Person>
|
||||||
# i am not a comment
|
# i am not a comment
|
||||||
|
@ -389,7 +389,7 @@ test 'comment within CSX is not treated as comment', ->
|
||||||
</Person>;
|
</Person>;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test 'comment at start of CSX escape', ->
|
test 'comment at start of JSX escape', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
<Person>
|
<Person>
|
||||||
{# i am a comment
|
{# i am a comment
|
||||||
|
@ -403,7 +403,7 @@ test 'comment at start of CSX escape', ->
|
||||||
</Person>;
|
</Person>;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test 'comment at end of CSX escape', ->
|
test 'comment at end of JSX escape', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
<Person>
|
<Person>
|
||||||
{"i am a string"
|
{"i am a string"
|
||||||
|
@ -418,7 +418,7 @@ test 'comment at end of CSX escape', ->
|
||||||
</Person>;
|
</Person>;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test 'CSX comment cannot be used inside interpolation', ->
|
test 'JSX comment cannot be used inside interpolation', ->
|
||||||
throws -> CoffeeScript.compile '''
|
throws -> CoffeeScript.compile '''
|
||||||
<Person>
|
<Person>
|
||||||
{# i am a comment}
|
{# i am a comment}
|
||||||
|
@ -430,21 +430,21 @@ test 'comment syntax cannot be used inline', ->
|
||||||
<Person>{#comment inline}</Person>
|
<Person>{#comment inline}</Person>
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test 'string within CSX is ignored', ->
|
test 'string within JSX is ignored', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
<Person> "i am not a string" 'nor am i' </Person>
|
<Person> "i am not a string" 'nor am i' </Person>
|
||||||
''', '''
|
''', '''
|
||||||
<Person> "i am not a string" 'nor am i' </Person>;
|
<Person> "i am not a string" 'nor am i' </Person>;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test 'special chars within CSX are ignored', ->
|
test 'special chars within JSX are ignored', ->
|
||||||
eqJS """
|
eqJS """
|
||||||
<Person> a,/';][' a\''@$%^&˚¬∑˜˚∆å∂¬˚*()*&^%$>> '"''"'''\'\'m' i </Person>
|
<Person> a,/';][' a\''@$%^&˚¬∑˜˚∆å∂¬˚*()*&^%$>> '"''"'''\'\'m' i </Person>
|
||||||
""", """
|
""", """
|
||||||
<Person> a,/';][' a''@$%^&˚¬∑˜˚∆å∂¬˚*()*&^%$>> '"''"'''''m' i </Person>;
|
<Person> a,/';][' a''@$%^&˚¬∑˜˚∆å∂¬˚*()*&^%$>> '"''"'''''m' i </Person>;
|
||||||
"""
|
"""
|
||||||
|
|
||||||
test 'html entities (name, decimal, hex) within CSX', ->
|
test 'html entities (name, decimal, hex) within JSX', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
<Person> &&&€ € €;; </Person>
|
<Person> &&&€ € €;; </Person>
|
||||||
''', '''
|
''', '''
|
||||||
|
@ -619,55 +619,55 @@ test 'closing tags must be closed', ->
|
||||||
<a></a
|
<a></a
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# Tests for allowing less than operator without spaces when ther is no CSX
|
# Tests for allowing less than operator without spaces when ther is no JSX
|
||||||
|
|
||||||
test 'unspaced less than without CSX: identifier', ->
|
test 'unspaced less than without JSX: identifier', ->
|
||||||
a = 3
|
a = 3
|
||||||
div = 5
|
div = 5
|
||||||
ok a<div
|
ok a<div
|
||||||
|
|
||||||
test 'unspaced less than without CSX: number', ->
|
test 'unspaced less than without JSX: number', ->
|
||||||
div = 5
|
div = 5
|
||||||
ok 3<div
|
ok 3<div
|
||||||
|
|
||||||
test 'unspaced less than without CSX: paren', ->
|
test 'unspaced less than without JSX: paren', ->
|
||||||
div = 5
|
div = 5
|
||||||
ok (3)<div
|
ok (3)<div
|
||||||
|
|
||||||
test 'unspaced less than without CSX: index', ->
|
test 'unspaced less than without JSX: index', ->
|
||||||
div = 5
|
div = 5
|
||||||
a = [3]
|
a = [3]
|
||||||
ok a[0]<div
|
ok a[0]<div
|
||||||
|
|
||||||
test 'tag inside CSX works following: identifier', ->
|
test 'tag inside JSX works following: identifier', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
<span>a<div /></span>
|
<span>a<div /></span>
|
||||||
''', '''
|
''', '''
|
||||||
<span>a<div /></span>;
|
<span>a<div /></span>;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test 'tag inside CSX works following: number', ->
|
test 'tag inside JSX works following: number', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
<span>3<div /></span>
|
<span>3<div /></span>
|
||||||
''', '''
|
''', '''
|
||||||
<span>3<div /></span>;
|
<span>3<div /></span>;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test 'tag inside CSX works following: paren', ->
|
test 'tag inside JSX works following: paren', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
<span>(3)<div /></span>
|
<span>(3)<div /></span>
|
||||||
''', '''
|
''', '''
|
||||||
<span>(3)<div /></span>;
|
<span>(3)<div /></span>;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test 'tag inside CSX works following: square bracket', ->
|
test 'tag inside JSX works following: square bracket', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
<span>]<div /></span>
|
<span>]<div /></span>
|
||||||
''', '''
|
''', '''
|
||||||
<span>]<div /></span>;
|
<span>]<div /></span>;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test 'unspaced less than inside CSX works but is not encouraged', ->
|
test 'unspaced less than inside JSX works but is not encouraged', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
a = 3
|
a = 3
|
||||||
div = 5
|
div = 5
|
||||||
|
@ -682,7 +682,7 @@ test 'unspaced less than inside CSX works but is not encouraged', ->
|
||||||
html = <span>{a < div}</span>;
|
html = <span>{a < div}</span>;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test 'unspaced less than before CSX works but is not encouraged', ->
|
test 'unspaced less than before JSX works but is not encouraged', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
div = 5
|
div = 5
|
||||||
res = 2<div
|
res = 2<div
|
||||||
|
@ -697,7 +697,7 @@ test 'unspaced less than before CSX works but is not encouraged', ->
|
||||||
html = <span />;
|
html = <span />;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test 'unspaced less than after CSX works but is not encouraged', ->
|
test 'unspaced less than after JSX works but is not encouraged', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
div = 5
|
div = 5
|
||||||
html = <span />
|
html = <span />
|
||||||
|
@ -712,7 +712,7 @@ test 'unspaced less than after CSX works but is not encouraged', ->
|
||||||
res = 2 < div;
|
res = 2 < div;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test '#4686: comments inside interpolations that also contain CSX tags', ->
|
test '#4686: comments inside interpolations that also contain JSX tags', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
|
@ -727,7 +727,7 @@ test '#4686: comments inside interpolations that also contain CSX tags', ->
|
||||||
</div>;
|
</div>;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test '#4686: comments inside interpolations that also contain CSX attributes', ->
|
test '#4686: comments inside interpolations that also contain JSX attributes', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
<div>
|
<div>
|
||||||
<div anAttr={
|
<div anAttr={
|
||||||
|
@ -742,7 +742,7 @@ test '#4686: comments inside interpolations that also contain CSX attributes', -
|
||||||
</div>;
|
</div>;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test '#5086: comments inside CSX tags but outside interpolations', ->
|
test '#5086: comments inside JSX tags but outside interpolations', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
<div>
|
<div>
|
||||||
<div ###comment### attribute={value} />
|
<div ###comment### attribute={value} />
|
||||||
|
@ -753,7 +753,7 @@ test '#5086: comments inside CSX tags but outside interpolations', ->
|
||||||
</div>;
|
</div>;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test '#5086: comments inside CSX attributes but outside interpolations', ->
|
test '#5086: comments inside JSX attributes but outside interpolations', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
<div>
|
<div>
|
||||||
<div attribute={###attr comment### value} />
|
<div attribute={###attr comment### value} />
|
||||||
|
@ -764,7 +764,7 @@ test '#5086: comments inside CSX attributes but outside interpolations', ->
|
||||||
</div>;
|
</div>;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
test '#5086: comments inside nested CSX tags and attributes but outside interpolations', ->
|
test '#5086: comments inside nested JSX tags and attributes but outside interpolations', ->
|
||||||
eqJS '''
|
eqJS '''
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
Loading…
Reference in New Issue