mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
887a6174e9
Co-authored-by: Geoffrey Booth <webadmin@geoffreybooth.com>
969 lines
19 KiB
CoffeeScript
969 lines
19 KiB
CoffeeScript
# We usually do not check the actual JS output from the compiler, but since
|
||
# JSX is not natively supported by Node, we do it in this case.
|
||
|
||
test 'self closing', ->
|
||
eqJS '''
|
||
<div />
|
||
''', '''
|
||
<div />;
|
||
'''
|
||
|
||
test 'self closing formatting', ->
|
||
eqJS '''
|
||
<div/>
|
||
''', '''
|
||
<div />;
|
||
'''
|
||
|
||
test 'self closing multiline', ->
|
||
eqJS '''
|
||
<div
|
||
/>
|
||
''', '''
|
||
<div />;
|
||
'''
|
||
|
||
test 'reserved-word self closing', ->
|
||
eqJS '''
|
||
<static />
|
||
''', '''
|
||
<static />;
|
||
'''
|
||
|
||
test 'regex attribute', ->
|
||
eqJS '''
|
||
<div x={/>asds/} />
|
||
''', '''
|
||
<div x={/>asds/} />;
|
||
'''
|
||
|
||
test 'string attribute', ->
|
||
eqJS '''
|
||
<div x="a" />
|
||
''', '''
|
||
<div x="a" />;
|
||
'''
|
||
|
||
test 'simple attribute', ->
|
||
eqJS '''
|
||
<div x={42} />
|
||
''', '''
|
||
<div x={42} />;
|
||
'''
|
||
|
||
test 'assignment attribute', ->
|
||
eqJS '''
|
||
<div x={y = 42} />
|
||
''', '''
|
||
var y;
|
||
|
||
<div x={y = 42} />;
|
||
'''
|
||
|
||
test 'object attribute', ->
|
||
eqJS '''
|
||
<div x={{y: 42}} />
|
||
''', '''
|
||
<div x={{
|
||
y: 42
|
||
}} />;
|
||
'''
|
||
|
||
test 'attribute without value', ->
|
||
eqJS '''
|
||
<div checked x="hello" />
|
||
''', '''
|
||
<div checked x="hello" />;
|
||
'''
|
||
|
||
test 'reserved-word attribute without value', ->
|
||
eqJS '''
|
||
<div static x="hello" />
|
||
''', '''
|
||
<div static x="hello" />;
|
||
'''
|
||
|
||
test 'reserved-word attribute with value', ->
|
||
eqJS '''
|
||
<div static="yes" x="hello" />
|
||
''', '''
|
||
<div static="yes" x="hello" />;
|
||
'''
|
||
|
||
test 'attribute with namespace', ->
|
||
eqJS '''
|
||
<image xlink:href="data:image/png" />
|
||
''', '''
|
||
<image xlink:href="data:image/png" />;
|
||
'''
|
||
|
||
test 'attribute with double namespace disallowed', ->
|
||
throwsCompileError '<image xlink:href:tag="data:image/png" />'
|
||
|
||
test 'attribute with member expression disallowed', ->
|
||
throwsCompileError '<image xlink.href="data:image/png" />'
|
||
|
||
test 'paired', ->
|
||
eqJS '''
|
||
<div></div>
|
||
''', '''
|
||
<div></div>;
|
||
'''
|
||
|
||
test 'simple content', ->
|
||
eqJS '''
|
||
<div>Hello world</div>
|
||
''', '''
|
||
<div>Hello world</div>;
|
||
'''
|
||
|
||
test 'content interpolation', ->
|
||
eqJS '''
|
||
<div>Hello {42}</div>
|
||
''', '''
|
||
<div>Hello {42}</div>;
|
||
'''
|
||
|
||
test 'nested tag', ->
|
||
eqJS '''
|
||
<div><span /></div>
|
||
''', '''
|
||
<div><span /></div>;
|
||
'''
|
||
|
||
test 'tag inside interpolation formatting', ->
|
||
eqJS '''
|
||
<div>Hello {<span />}</div>
|
||
''', '''
|
||
<div>Hello <span /></div>;
|
||
'''
|
||
|
||
test 'tag inside interpolation, tags are callable', ->
|
||
eqJS '''
|
||
<div>Hello {<span /> x}</div>
|
||
''', '''
|
||
<div>Hello {<span />(x)}</div>;
|
||
'''
|
||
|
||
test 'tags inside interpolation, tags trigger implicit calls', ->
|
||
eqJS '''
|
||
<div>Hello {f <span />}</div>
|
||
''', '''
|
||
<div>Hello {f(<span />)}</div>;
|
||
'''
|
||
|
||
test 'regex in interpolation', ->
|
||
eqJS '''
|
||
<div x={/>asds/}><div />{/>asdsad</}</div>
|
||
''', '''
|
||
<div x={/>asds/}><div />{/>asdsad</}</div>;
|
||
'''
|
||
|
||
test 'interpolation in string attribute value', ->
|
||
eqJS '''
|
||
<div x="Hello #{world}" />
|
||
''', '''
|
||
<div x={`Hello ${world}`} />;
|
||
'''
|
||
|
||
# Unlike in `coffee-react-transform`.
|
||
test 'bare numbers not allowed', ->
|
||
throwsCompileError '<div x=3 />'
|
||
|
||
test 'bare expressions not allowed', ->
|
||
throwsCompileError '<div x=y />'
|
||
|
||
test 'bare complex expressions not allowed', ->
|
||
throwsCompileError '<div x=f(3) />'
|
||
|
||
test 'unescaped opening tag angle bracket disallowed', ->
|
||
throwsCompileError '<Person><<</Person>'
|
||
|
||
test 'space around equal sign', ->
|
||
eqJS '''
|
||
<div popular = "yes" />
|
||
''', '''
|
||
<div popular="yes" />;
|
||
'''
|
||
|
||
# The following tests were adopted from James Friend’s
|
||
# [https://github.com/jsdf/coffee-react-transform](https://github.com/jsdf/coffee-react-transform).
|
||
|
||
test 'ambiguous tag-like expression', ->
|
||
throwsCompileError 'x = a <b > c'
|
||
|
||
test 'ambiguous tag', ->
|
||
eqJS '''
|
||
a <b > c </b>
|
||
''', '''
|
||
a(<b> c </b>);
|
||
'''
|
||
|
||
test 'escaped CoffeeScript attribute', ->
|
||
eqJS '''
|
||
<Person name={if test() then 'yes' else 'no'} />
|
||
''', '''
|
||
<Person name={test() ? 'yes' : 'no'} />;
|
||
'''
|
||
|
||
test 'escaped CoffeeScript attribute over multiple lines', ->
|
||
eqJS '''
|
||
<Person name={
|
||
if test()
|
||
'yes'
|
||
else
|
||
'no'
|
||
} />
|
||
''', '''
|
||
<Person name={test() ? 'yes' : 'no'} />;
|
||
'''
|
||
|
||
test 'multiple line escaped CoffeeScript with nested JSX', ->
|
||
eqJS '''
|
||
<Person name={
|
||
if test()
|
||
'yes'
|
||
else
|
||
'no'
|
||
}>
|
||
{
|
||
|
||
for n in a
|
||
<div> a
|
||
asf
|
||
<li xy={"as"}>{ n+1 }<a /> <a /> </li>
|
||
</div>
|
||
}
|
||
|
||
</Person>
|
||
''', '''
|
||
var n;
|
||
|
||
<Person name={test() ? 'yes' : 'no'}>
|
||
{(function() {
|
||
var i, len, results;
|
||
results = [];
|
||
for (i = 0, len = a.length; i < len; i++) {
|
||
n = a[i];
|
||
results.push(<div> a
|
||
asf
|
||
<li xy={"as"}>{n + 1}<a /> <a /> </li>
|
||
</div>);
|
||
}
|
||
return results;
|
||
})()}
|
||
|
||
</Person>;
|
||
'''
|
||
|
||
test 'nested JSX within an attribute, with object attr value', ->
|
||
eqJS '''
|
||
<Company>
|
||
<Person name={<NameComponent attr3={ {'a': {}, b: '{'} } />} />
|
||
</Company>
|
||
''', '''
|
||
<Company>
|
||
<Person name={<NameComponent attr3={{
|
||
'a': {},
|
||
b: '{'
|
||
}} />} />
|
||
</Company>;
|
||
'''
|
||
|
||
test 'complex nesting', ->
|
||
eqJS '''
|
||
<div code={someFunc({a:{b:{}, C:'}{}{'}})} />
|
||
''', '''
|
||
<div code={someFunc({
|
||
a: {
|
||
b: {},
|
||
C: '}{}{'
|
||
}
|
||
})} />;
|
||
'''
|
||
|
||
test 'multiline tag with nested JSX within an attribute', ->
|
||
eqJS '''
|
||
<Person
|
||
name={
|
||
name = formatName(user.name)
|
||
<NameComponent name={name.toUppercase()} />
|
||
}
|
||
>
|
||
blah blah blah
|
||
</Person>
|
||
''', '''
|
||
var name;
|
||
|
||
<Person name={name = formatName(user.name), <NameComponent name={name.toUppercase()} />}>
|
||
blah blah blah
|
||
</Person>;
|
||
'''
|
||
|
||
test 'escaped CoffeeScript with nested object literals', ->
|
||
eqJS '''
|
||
<Person>
|
||
blah blah blah {
|
||
{'a' : {}, 'asd': 'asd'}
|
||
}
|
||
</Person>
|
||
''', '''
|
||
<Person>
|
||
blah blah blah {{
|
||
'a': {},
|
||
'asd': 'asd'
|
||
}}
|
||
</Person>;
|
||
'''
|
||
|
||
test 'multiline tag attributes with escaped CoffeeScript', ->
|
||
eqJS '''
|
||
<Person name={if isActive() then 'active' else 'inactive'}
|
||
someattr='on new line' />
|
||
''', '''
|
||
<Person name={isActive() ? 'active' : 'inactive'} someattr='on new line' />;
|
||
'''
|
||
|
||
test 'lots of attributes', ->
|
||
eqJS '''
|
||
<Person eyes={2} friends={getFriends()} popular = "yes"
|
||
active={ if isActive() then 'active' else '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 JSX
|
||
# test 'multiline elements', ->
|
||
# eqJS '''
|
||
# <div something={
|
||
# do ->
|
||
# test = /432/gm # this is a regex
|
||
# 6 /432/gm # this is division
|
||
# }
|
||
# >
|
||
# <div>
|
||
# <div>
|
||
# <div>
|
||
# <article name={ new Date() } number={203}
|
||
# range={getRange()}
|
||
# >
|
||
# </article>
|
||
# </div>
|
||
# </div>
|
||
# </div>
|
||
# </div>
|
||
# ''', '''
|
||
# bla
|
||
# '''
|
||
|
||
test 'complex regex', ->
|
||
eqJS '''
|
||
<Person />
|
||
/\\/\\/<Person \\/>\\>\\//
|
||
''', '''
|
||
<Person />;
|
||
|
||
/\\/\\/<Person \\/>\\>\\//;
|
||
'''
|
||
|
||
test 'heregex', ->
|
||
eqJS '''
|
||
test = /432/gm # this is a regex
|
||
6 /432/gm # this is division
|
||
<Tag>
|
||
{test = /<Tag>/} this is a regex containing something which looks like a tag
|
||
</Tag>
|
||
<Person />
|
||
REGEX = /// ^
|
||
(/ (?! [\s=] ) # comment comment <comment>comment</comment>
|
||
[^ [ / \n \\ ]* # comment comment
|
||
(?:
|
||
<Tag />
|
||
(?: \\[\s\S] # comment comment
|
||
| \[ # comment comment
|
||
[^ \] \n \\ ]*
|
||
(?: \\[\s\S] [^ \] \n \\ ]* )*
|
||
<Tag>tag</Tag>
|
||
]
|
||
) [^ [ / \n \\ ]*
|
||
)*
|
||
/) ([imgy]{0,4}) (?!\w)
|
||
///
|
||
<Person />
|
||
''', '''
|
||
var REGEX, test;
|
||
|
||
test = /432/gm; // this is a regex
|
||
|
||
6 / 432 / gm; // this is division
|
||
|
||
<Tag>
|
||
{test = /<Tag>/} this is a regex containing something which looks like a tag
|
||
</Tag>;
|
||
|
||
<Person />;
|
||
|
||
REGEX = /^(\\/(?![s=])[^[\\/ ]*(?:<Tag\\/>(?:\\[sS]|[[^] ]*(?:\\[sS][^] ]*)*<Tag>tag<\\/Tag>])[^[\\/ ]*)*\\/)([imgy]{0,4})(?!w)/; // comment comment <comment>comment</comment>
|
||
// comment comment
|
||
// comment comment
|
||
// comment comment
|
||
|
||
<Person />;
|
||
'''
|
||
|
||
test 'comment within JSX is not treated as comment', ->
|
||
eqJS '''
|
||
<Person>
|
||
# i am not a comment
|
||
</Person>
|
||
''', '''
|
||
<Person>
|
||
# i am not a comment
|
||
</Person>;
|
||
'''
|
||
|
||
test 'comment at start of JSX escape', ->
|
||
eqJS '''
|
||
<Person>
|
||
{# i am a comment
|
||
"i am a string"
|
||
}
|
||
</Person>
|
||
''', '''
|
||
<Person>
|
||
{// i am a comment
|
||
"i am a string"}
|
||
</Person>;
|
||
'''
|
||
|
||
test 'comment at end of JSX escape', ->
|
||
eqJS '''
|
||
<Person>
|
||
{"i am a string"
|
||
# i am a comment
|
||
}
|
||
</Person>
|
||
''', '''
|
||
<Person>
|
||
{"i am a string"
|
||
// i am a comment
|
||
}
|
||
</Person>;
|
||
'''
|
||
|
||
test 'JSX comment cannot be used inside interpolation', ->
|
||
throwsCompileError '''
|
||
<Person>
|
||
{# i am a comment}
|
||
</Person>
|
||
'''
|
||
|
||
test 'comment syntax cannot be used inline', ->
|
||
throwsCompileError '''
|
||
<Person>{#comment inline}</Person>
|
||
'''
|
||
|
||
test 'string within JSX is ignored', ->
|
||
eqJS '''
|
||
<Person> "i am not a string" 'nor am i' </Person>
|
||
''', '''
|
||
<Person> "i am not a string" 'nor am i' </Person>;
|
||
'''
|
||
|
||
test 'special chars within JSX are ignored', ->
|
||
eqJS """
|
||
<Person> a,/';][' a\''@$%^&˚¬∑˜˚∆å∂¬˚*()*&^%$>> '"''"'''\'\'m' i </Person>
|
||
""", """
|
||
<Person> a,/';][' a''@$%^&˚¬∑˜˚∆å∂¬˚*()*&^%$>> '"''"'''''m' i </Person>;
|
||
"""
|
||
|
||
test 'html entities (name, decimal, hex) within JSX', ->
|
||
eqJS '''
|
||
<Person> &&&€ € €;; </Person>
|
||
''', '''
|
||
<Person> &&&€ € €;; </Person>;
|
||
'''
|
||
|
||
test 'tag with {{}}', ->
|
||
eqJS '''
|
||
<Person name={{value: item, key, item}} />
|
||
''', '''
|
||
<Person name={{
|
||
value: item,
|
||
key,
|
||
item
|
||
}} />;
|
||
'''
|
||
|
||
test 'tag with member expression', ->
|
||
eqJS '''
|
||
<Something.Tag></Something.Tag>
|
||
''', '''
|
||
<Something.Tag></Something.Tag>;
|
||
'''
|
||
|
||
test 'tag with lowercase member expression', ->
|
||
eqJS '''
|
||
<something.tag></something.tag>
|
||
''', '''
|
||
<something.tag></something.tag>;
|
||
'''
|
||
|
||
test 'self closing tag with member expression', ->
|
||
eqJS '''
|
||
<Something.Tag />
|
||
''', '''
|
||
<Something.Tag />;
|
||
'''
|
||
|
||
test 'self closing tag with multiple member expressions', ->
|
||
eqJS '''
|
||
<Something.Tag.More />
|
||
''', '''
|
||
<Something.Tag.More />;
|
||
'''
|
||
|
||
test 'tag with namespace', ->
|
||
eqJS '''
|
||
<Something:Tag></Something:Tag>
|
||
''', '''
|
||
<Something:Tag></Something:Tag>;
|
||
'''
|
||
|
||
test 'tag with lowercase namespace', ->
|
||
eqJS '''
|
||
<something:tag></something:tag>
|
||
''', '''
|
||
<something:tag></something:tag>;
|
||
'''
|
||
|
||
test 'self closing tag with namespace', ->
|
||
eqJS '''
|
||
<Something:Tag />
|
||
''', '''
|
||
<Something:Tag />;
|
||
'''
|
||
|
||
test 'self closing tag with namespace and member expression disallowed', ->
|
||
throwsCompileError '''
|
||
<Namespace:Something.Tag />
|
||
'''
|
||
|
||
test 'self closing tag with spread attribute', ->
|
||
eqJS '''
|
||
<Component a={b} {x...} b="c" />
|
||
''', '''
|
||
<Component a={b} {...x} b="c" />;
|
||
'''
|
||
|
||
test 'complex spread attribute', ->
|
||
eqJS '''
|
||
<Component {x...} a={b} {x...} b="c" {$my_xtraCoolVar123...} />
|
||
''', '''
|
||
<Component {...x} a={b} {...x} b="c" {...$my_xtraCoolVar123} />;
|
||
'''
|
||
|
||
test 'multiline spread attribute', ->
|
||
eqJS '''
|
||
<Component {
|
||
x...} a={b} {x...} b="c" {z...}>
|
||
</Component>
|
||
''', '''
|
||
<Component {...x} a={b} {...x} b="c" {...z}>
|
||
</Component>;
|
||
'''
|
||
|
||
test 'multiline tag with spread attribute', ->
|
||
eqJS '''
|
||
<Component
|
||
z="1"
|
||
{x...}
|
||
a={b}
|
||
b="c"
|
||
>
|
||
</Component>
|
||
''', '''
|
||
<Component z="1" {...x} a={b} b="c">
|
||
</Component>;
|
||
'''
|
||
|
||
test 'multiline tag with spread attribute first', ->
|
||
eqJS '''
|
||
<Component
|
||
{x...}
|
||
z="1"
|
||
a={b}
|
||
b="c"
|
||
>
|
||
</Component>
|
||
''', '''
|
||
<Component {...x} z="1" a={b} b="c">
|
||
</Component>;
|
||
'''
|
||
|
||
test 'complex multiline spread attribute', ->
|
||
eqJS '''
|
||
<Component
|
||
{y...
|
||
} a={b} {x...} b="c" {z...}>
|
||
<div code={someFunc({a:{b:{}, C:'}'}})} />
|
||
</Component>
|
||
''', '''
|
||
<Component {...y} a={b} {...x} b="c" {...z}>
|
||
<div code={someFunc({
|
||
a: {
|
||
b: {},
|
||
C: '}'
|
||
}
|
||
})} />
|
||
</Component>;
|
||
'''
|
||
|
||
test 'self closing spread attribute on single line', ->
|
||
eqJS '''
|
||
<Component a="b" c="d" {@props...} />
|
||
''', '''
|
||
<Component a="b" c="d" {...this.props} />;
|
||
'''
|
||
|
||
test 'self closing spread attribute on new line', ->
|
||
eqJS '''
|
||
<Component
|
||
a="b"
|
||
c="d"
|
||
{@props...}
|
||
/>
|
||
''', '''
|
||
<Component a="b" c="d" {...this.props} />;
|
||
'''
|
||
|
||
test 'self closing spread attribute on same line', ->
|
||
eqJS '''
|
||
<Component
|
||
a="b"
|
||
c="d"
|
||
{@props...} />
|
||
''', '''
|
||
<Component a="b" c="d" {...this.props} />;
|
||
'''
|
||
|
||
test 'self closing spread attribute on next line', ->
|
||
eqJS '''
|
||
<Component
|
||
a="b"
|
||
c="d"
|
||
{@props...}
|
||
|
||
/>
|
||
''', '''
|
||
<Component a="b" c="d" {...this.props} />;
|
||
'''
|
||
|
||
test 'empty strings are not converted to true', ->
|
||
eqJS '''
|
||
<Component val="" />
|
||
''', '''
|
||
<Component val="" />;
|
||
'''
|
||
|
||
test 'CoffeeScript @ syntax in tag name', ->
|
||
throwsCompileError '''
|
||
<@Component>
|
||
<Component />
|
||
</@Component>
|
||
'''
|
||
|
||
test 'hyphens in tag names', ->
|
||
eqJS '''
|
||
<paper-button className="button">{text}</paper-button>
|
||
''', '''
|
||
<paper-button className="button">{text}</paper-button>;
|
||
'''
|
||
|
||
test 'closing tags must be closed', ->
|
||
throwsCompileError '''
|
||
<a></a
|
||
'''
|
||
|
||
# Tests for allowing less than operator without spaces when ther is no JSX
|
||
|
||
test 'unspaced less than without JSX: identifier', ->
|
||
a = 3
|
||
div = 5
|
||
ok a<div
|
||
|
||
test 'unspaced less than without JSX: number', ->
|
||
div = 5
|
||
ok 3<div
|
||
|
||
test 'unspaced less than without JSX: paren', ->
|
||
div = 5
|
||
ok (3)<div
|
||
|
||
test 'unspaced less than without JSX: index', ->
|
||
div = 5
|
||
a = [3]
|
||
ok a[0]<div
|
||
|
||
test 'tag inside JSX works following: identifier', ->
|
||
eqJS '''
|
||
<span>a<div /></span>
|
||
''', '''
|
||
<span>a<div /></span>;
|
||
'''
|
||
|
||
test 'tag inside JSX works following: number', ->
|
||
eqJS '''
|
||
<span>3<div /></span>
|
||
''', '''
|
||
<span>3<div /></span>;
|
||
'''
|
||
|
||
test 'tag inside JSX works following: paren', ->
|
||
eqJS '''
|
||
<span>(3)<div /></span>
|
||
''', '''
|
||
<span>(3)<div /></span>;
|
||
'''
|
||
|
||
test 'tag inside JSX works following: square bracket', ->
|
||
eqJS '''
|
||
<span>]<div /></span>
|
||
''', '''
|
||
<span>]<div /></span>;
|
||
'''
|
||
|
||
test 'unspaced less than inside JSX works but is not encouraged', ->
|
||
eqJS '''
|
||
a = 3
|
||
div = 5
|
||
html = <span>{a<div}</span>
|
||
''', '''
|
||
var a, div, html;
|
||
|
||
a = 3;
|
||
|
||
div = 5;
|
||
|
||
html = <span>{a < div}</span>;
|
||
'''
|
||
|
||
test 'unspaced less than before JSX works but is not encouraged', ->
|
||
eqJS '''
|
||
div = 5
|
||
res = 2<div
|
||
html = <span />
|
||
''', '''
|
||
var div, html, res;
|
||
|
||
div = 5;
|
||
|
||
res = 2 < div;
|
||
|
||
html = <span />;
|
||
'''
|
||
|
||
test 'unspaced less than after JSX works but is not encouraged', ->
|
||
eqJS '''
|
||
div = 5
|
||
html = <span />
|
||
res = 2<div
|
||
''', '''
|
||
var div, html, res;
|
||
|
||
div = 5;
|
||
|
||
html = <span />;
|
||
|
||
res = 2 < div;
|
||
'''
|
||
|
||
test '#4686: comments inside interpolations that also contain JSX tags', ->
|
||
eqJS '''
|
||
<div>
|
||
{
|
||
# comment
|
||
<div />
|
||
}
|
||
</div>
|
||
''', '''
|
||
<div>
|
||
{ // comment
|
||
<div />}
|
||
</div>;
|
||
'''
|
||
|
||
test '#4686: comments inside interpolations that also contain JSX attributes', ->
|
||
eqJS '''
|
||
<div>
|
||
<div anAttr={
|
||
# comment
|
||
"value"
|
||
} />
|
||
</div>
|
||
''', '''
|
||
<div>
|
||
{ // comment
|
||
<div anAttr={"value"} />}
|
||
</div>;
|
||
'''
|
||
|
||
test '#5086: comments inside JSX tags but outside interpolations', ->
|
||
eqJS '''
|
||
<div>
|
||
<div ###comment### attribute={value} />
|
||
</div>
|
||
''', '''
|
||
<div>
|
||
<div /*comment*/attribute={value} />
|
||
</div>;
|
||
'''
|
||
|
||
test '#5086: comments inside JSX attributes but outside interpolations', ->
|
||
eqJS '''
|
||
<div>
|
||
<div attribute={###attr comment### value} />
|
||
</div>
|
||
''', '''
|
||
<div>
|
||
<div attribute={/*attr comment*/value} />
|
||
</div>;
|
||
'''
|
||
|
||
test '#5086: comments inside nested JSX tags and attributes but outside interpolations', ->
|
||
eqJS '''
|
||
<div>
|
||
<div>
|
||
<div>
|
||
<div ###comment### attribute={###attr comment### value} />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
''', '''
|
||
<div>
|
||
<div>
|
||
<div>
|
||
<div /*comment*/attribute={/*attr comment*/value} />
|
||
</div>
|
||
</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>;
|
||
};
|
||
'''
|
||
|
||
test '#5055: JSX expression indentation bug', ->
|
||
eqJS '''
|
||
<div>
|
||
{someCondition &&
|
||
<span />
|
||
}
|
||
</div>
|
||
''', '''
|
||
<div>
|
||
{someCondition && <span />}
|
||
</div>;
|
||
'''
|
||
|
||
eqJS '''
|
||
<div>{someString +
|
||
"abc"
|
||
}
|
||
</div>
|
||
''', '''
|
||
<div>{someString + "abc"}
|
||
</div>;
|
||
'''
|
||
|
||
eqJS '''
|
||
<div>
|
||
{a ?
|
||
<span />
|
||
}
|
||
</div>
|
||
''', '''
|
||
<div>
|
||
{typeof a !== "undefined" && a !== null ? a : <span />}
|
||
</div>;
|
||
'''
|
||
|
||
# JSX is like XML, in that there needs to be a root element; but
|
||
# technically, adjacent top-level elements where only the last one
|
||
# is returned (as opposed to a fragment or root element) is permissible
|
||
# syntax. It’s almost certainly an error, but it’s valid, so need to leave it
|
||
# to linters to catch. https://github.com/jashkenas/coffeescript/pull/5049
|
||
test '“Adjacent” tags on separate lines should still compile', ->
|
||
eqJS '''
|
||
->
|
||
<a />
|
||
<b />
|
||
''', '''
|
||
(function() {
|
||
<a />;
|
||
return <b />;
|
||
});
|
||
'''
|
||
|
||
test '#5352: triple-quoted non-interpolated attribute values', ->
|
||
eqJS '''
|
||
<div a="""
|
||
b
|
||
c
|
||
""" />
|
||
''', '''
|
||
<div a={`b
|
||
c`} />;
|
||
'''
|
||
|
||
eqJS """
|
||
<div a='''
|
||
b
|
||
c
|
||
''' />
|
||
""", '''
|
||
<div a={`b
|
||
c`} />;
|
||
'''
|