mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
* CSX fragments * regex improvement; tests * regex improvement * regex improvement * bug fix; regex * Fix style * Split fragment tests
This commit is contained in:
parent
5bc85b8f6d
commit
7f5ab7eb0d
4 changed files with 60 additions and 10 deletions
|
@ -17,12 +17,10 @@
|
||||||
// from our rules and saves it into `lib/parser.js`.
|
// from our rules and saves it into `lib/parser.js`.
|
||||||
|
|
||||||
// The only dependency is on the **Jison.Parser**.
|
// The only dependency is on the **Jison.Parser**.
|
||||||
var Parser, alt, alternatives, grammar, log, name, o, operators, token, tokens, unwrap;
|
var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
|
||||||
|
|
||||||
({Parser} = require('jison'));
|
({Parser} = require('jison'));
|
||||||
|
|
||||||
log = console.log;
|
|
||||||
|
|
||||||
// Jison DSL
|
// Jison DSL
|
||||||
// ---------
|
// ---------
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
// where locationData is {first_line, first_column, last_line, last_column}, which is a
|
// where locationData is {first_line, first_column, last_line, last_column}, 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_IDENTIFIER, CSX_INTERPOLATION, HERECOMMENT_ILLEGAL, HEREDOC_DOUBLE, HEREDOC_INDENT, HEREDOC_SINGLE, HEREGEX, HEREGEX_OMIT, HERE_JSTOKEN, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, INSIDE_CSX, INVERSES, JSTOKEN, JS_KEYWORDS, LEADING_BLANK_LINE, 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, SIMPLE_STRING_OMIT, STRICT_PROSCRIBED, STRING_DOUBLE, STRING_INVALID_ESCAPE, STRING_OMIT, STRING_SINGLE, STRING_START, TRAILING_BLANK_LINE, TRAILING_SPACES, UNARY, UNARY_MATH, UNFINISHED, UNICODE_CODE_POINT_ESCAPE, VALID_FLAGS, WHITESPACE, attachCommentsToNode, compact, count, invertLiterate, isForFrom, isUnassignable, key, locationDataToString, merge, repeat, starts, throwSyntaxError,
|
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, HEREGEX_OMIT, HERE_JSTOKEN, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, INSIDE_CSX, INVERSES, JSTOKEN, JS_KEYWORDS, LEADING_BLANK_LINE, 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, SIMPLE_STRING_OMIT, STRICT_PROSCRIBED, STRING_DOUBLE, STRING_INVALID_ESCAPE, STRING_OMIT, STRING_SINGLE, STRING_START, TRAILING_BLANK_LINE, TRAILING_SPACES, UNARY, UNARY_MATH, UNFINISHED, UNICODE_CODE_POINT_ESCAPE, VALID_FLAGS, WHITESPACE, attachCommentsToNode, compact, count, invertLiterate, isForFrom, isUnassignable, key, locationDataToString, merge, repeat, starts, throwSyntaxError,
|
||||||
indexOf = [].indexOf;
|
indexOf = [].indexOf;
|
||||||
|
|
||||||
({Rewriter, INVERSES} = require('./rewriter'));
|
({Rewriter, INVERSES} = require('./rewriter'));
|
||||||
|
@ -741,7 +741,7 @@
|
||||||
// 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));
|
match = CSX_IDENTIFIER.exec(this.chunk.slice(1)) || CSX_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.csxDepth > 0 || !(prev = this.prev()) || prev.spaced || (ref = prev[0], indexOf.call(COMPARABLE_LEFT_SIDE, ref) < 0)))) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -793,8 +793,8 @@
|
||||||
delimiter: '>'
|
delimiter: '>'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
match = CSX_IDENTIFIER.exec(this.chunk.slice(end));
|
match = CSX_IDENTIFIER.exec(this.chunk.slice(end)) || CSX_FRAGMENT_IDENTIFIER.exec(this.chunk.slice(end));
|
||||||
if (!match || match[0] !== csxTag.name) {
|
if (!match || match[1] !== csxTag.name) {
|
||||||
this.error(`expected corresponding CSX closing tag for ${csxTag.name}`, csxTag.origin[2]);
|
this.error(`expected corresponding CSX closing tag for ${csxTag.name}`, csxTag.origin[2]);
|
||||||
}
|
}
|
||||||
afterTag = end + csxTag.name.length;
|
afterTag = end + csxTag.name.length;
|
||||||
|
@ -1541,6 +1541,9 @@
|
||||||
CSX_IDENTIFIER = /^(?![\d<])((?:(?!\s)[\.\-$\w\x7f-\uffff])+)/; // Must not start with `<`.
|
CSX_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: <></>
|
||||||
|
CSX_FRAGMENT_IDENTIFIER = /^()>/; // Ends immediately with `>`.
|
||||||
|
|
||||||
CSX_ATTRIBUTE = /^(?!\d)((?:(?!\s)[\-$\w\x7f-\uffff])+)([^\S]*=(?!=))?/; // Like `IDENTIFIER`, but includes `-`s.
|
CSX_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?
|
||||||
|
|
||||||
|
|
|
@ -556,7 +556,7 @@ exports.Lexer = class Lexer
|
||||||
# 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...]
|
match = CSX_IDENTIFIER.exec(@chunk[1...]) or CSX_FRAGMENT_IDENTIFIER.exec(@chunk[1...])
|
||||||
return 0 unless match and (
|
return 0 unless match and (
|
||||||
@csxDepth > 0 or
|
@csxDepth > 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`).
|
||||||
|
@ -596,8 +596,8 @@ exports.Lexer = class Lexer
|
||||||
@matchWithInterpolations INSIDE_CSX, '>', '</', CSX_INTERPOLATION
|
@matchWithInterpolations INSIDE_CSX, '>', '</', CSX_INTERPOLATION
|
||||||
@mergeInterpolationTokens tokens, {delimiter: '"'}, (value, i) =>
|
@mergeInterpolationTokens tokens, {delimiter: '"'}, (value, i) =>
|
||||||
@formatString value, delimiter: '>'
|
@formatString value, delimiter: '>'
|
||||||
match = CSX_IDENTIFIER.exec @chunk[end...]
|
match = CSX_IDENTIFIER.exec(@chunk[end...]) or CSX_FRAGMENT_IDENTIFIER.exec(@chunk[end...])
|
||||||
if not match or match[0] isnt csxTag.name
|
if not match or match[1] isnt csxTag.name
|
||||||
@error "expected corresponding CSX closing tag for #{csxTag.name}",
|
@error "expected corresponding CSX closing tag for #{csxTag.name}",
|
||||||
csxTag.origin[2]
|
csxTag.origin[2]
|
||||||
afterTag = end + csxTag.name.length
|
afterTag = end + csxTag.name.length
|
||||||
|
@ -1178,6 +1178,11 @@ CSX_IDENTIFIER = /// ^
|
||||||
( (?: (?!\s)[\.\-$\w\x7f-\uffff] )+ ) # Like `IDENTIFIER`, but includes `-`s and `.`s.
|
( (?: (?!\s)[\.\-$\w\x7f-\uffff] )+ ) # Like `IDENTIFIER`, but includes `-`s and `.`s.
|
||||||
///
|
///
|
||||||
|
|
||||||
|
# Fragment: <></>
|
||||||
|
CSX_FRAGMENT_IDENTIFIER = /// ^
|
||||||
|
()> # Ends immediately with `>`.
|
||||||
|
///
|
||||||
|
|
||||||
CSX_ATTRIBUTE = /// ^
|
CSX_ATTRIBUTE = /// ^
|
||||||
(?!\d)
|
(?!\d)
|
||||||
( (?: (?!\s)[\-$\w\x7f-\uffff] )+ ) # Like `IDENTIFIER`, but includes `-`s.
|
( (?: (?!\s)[\-$\w\x7f-\uffff] )+ ) # Like `IDENTIFIER`, but includes `-`s.
|
||||||
|
|
|
@ -742,3 +742,47 @@ test '#4686: comments inside interpolations that also contain CSX attributes', -
|
||||||
</div>;
|
</div>;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
# https://reactjs.org/blog/2017/11/28/react-v16.2.0-fragment-support.html
|
||||||
|
test 'JSX fragments: empty fragment', ->
|
||||||
|
eqJS '''
|
||||||
|
<></>
|
||||||
|
''', '''
|
||||||
|
<></>;
|
||||||
|
'''
|
||||||
|
|
||||||
|
test 'JSX fragments: fragment with text nodes', ->
|
||||||
|
eqJS '''
|
||||||
|
<>
|
||||||
|
Some text.
|
||||||
|
<h2>A heading</h2>
|
||||||
|
More text.
|
||||||
|
<h2>Another heading</h2>
|
||||||
|
Even more text.
|
||||||
|
</>
|
||||||
|
''', '''
|
||||||
|
<>
|
||||||
|
Some text.
|
||||||
|
<h2>A heading</h2>
|
||||||
|
More text.
|
||||||
|
<h2>Another heading</h2>
|
||||||
|
Even more text.
|
||||||
|
</>;
|
||||||
|
'''
|
||||||
|
|
||||||
|
test 'JSX fragments: fragment with component nodes', ->
|
||||||
|
eqJS '''
|
||||||
|
Component = (props) =>
|
||||||
|
<Fragment>
|
||||||
|
<OtherComponent />
|
||||||
|
<OtherComponent />
|
||||||
|
</Fragment>
|
||||||
|
''', '''
|
||||||
|
var Component;
|
||||||
|
|
||||||
|
Component = (props) => {
|
||||||
|
return <Fragment>
|
||||||
|
<OtherComponent />
|
||||||
|
<OtherComponent />
|
||||||
|
</Fragment>;
|
||||||
|
};
|
||||||
|
'''
|
||||||
|
|
Loading…
Reference in a new issue