mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-05-03 03:00:14 -04:00
[CS2] Support for CSX - equivalent of JSX (#4551)
* CSX implementation * fixed comment, used toJS, added error tests, fixed error in identifier regex, fixed interpolation inside attributes value and added test * added missing test for bare attributes, split attribute and indentifier regex, fixed checking for closing tags closing angle bracket * Refactor tests that compare expected generated JavaScript with actual generated JavaScript to use common helper; add colors to error message to make differences easier to read * Better match the style of the rest of the codebase * Remove unused function * More style fixes * Allow unspaced less-than operator when not using CSX * Replace includesCSX with a counter and simplify the unspaced operator logic * Fixed indexing and realized that I completely enabled the tight spacing, added a test for it too * Style fixes
This commit is contained in:
committed by
Geoffrey Booth
parent
63b109a4f5
commit
dc0fb85fd3
@@ -213,57 +213,50 @@ test "#2916: block comment before implicit call with implicit object", ->
|
||||
a: yes
|
||||
|
||||
test "#3132: Format single-line block comment nicely", ->
|
||||
input = """
|
||||
### Single-line block comment without additional space here => ###"""
|
||||
|
||||
output = """
|
||||
eqJS """
|
||||
### Single-line block comment without additional space here => ###""",
|
||||
"""
|
||||
/* Single-line block comment without additional space here => */
|
||||
"""
|
||||
eq toJS(input), output
|
||||
|
||||
test "#3132: Format multi-line block comment nicely", ->
|
||||
input = """
|
||||
eqJS """
|
||||
###
|
||||
# Multi-line
|
||||
# block
|
||||
# comment
|
||||
###"""
|
||||
|
||||
output = """
|
||||
###""",
|
||||
"""
|
||||
/*
|
||||
* Multi-line
|
||||
* block
|
||||
* comment
|
||||
*/
|
||||
"""
|
||||
eq toJS(input), output
|
||||
|
||||
test "#3132: Format simple block comment nicely", ->
|
||||
input = """
|
||||
eqJS """
|
||||
###
|
||||
No
|
||||
Preceding hash
|
||||
###"""
|
||||
|
||||
output = """
|
||||
###""",
|
||||
"""
|
||||
/*
|
||||
No
|
||||
Preceding hash
|
||||
*/
|
||||
"""
|
||||
|
||||
eq toJS(input), output
|
||||
|
||||
test "#3132: Format indented block-comment nicely", ->
|
||||
input = """
|
||||
eqJS """
|
||||
fn = () ->
|
||||
###
|
||||
# Indented
|
||||
Multiline
|
||||
###
|
||||
1"""
|
||||
|
||||
output = """
|
||||
1""",
|
||||
"""
|
||||
var fn;
|
||||
|
||||
fn = function() {
|
||||
@@ -275,21 +268,19 @@ test "#3132: Format indented block-comment nicely", ->
|
||||
return 1;
|
||||
};
|
||||
"""
|
||||
eq toJS(input), output
|
||||
|
||||
# Although adequately working, block comment-placement is not yet perfect.
|
||||
# (Considering a case where multiple variables have been declared …)
|
||||
test "#3132: Format jsdoc-style block-comment nicely", ->
|
||||
input = """
|
||||
eqJS """
|
||||
###*
|
||||
# Multiline for jsdoc-"@doctags"
|
||||
#
|
||||
# @type {Function}
|
||||
###
|
||||
fn = () -> 1
|
||||
""",
|
||||
"""
|
||||
|
||||
output = """
|
||||
/**
|
||||
* Multiline for jsdoc-"@doctags"
|
||||
*
|
||||
@@ -300,21 +291,19 @@ test "#3132: Format jsdoc-style block-comment nicely", ->
|
||||
fn = function() {
|
||||
return 1;
|
||||
};"""
|
||||
eq toJS(input), output
|
||||
|
||||
# Although adequately working, block comment-placement is not yet perfect.
|
||||
# (Considering a case where multiple variables have been declared …)
|
||||
test "#3132: Format hand-made (raw) jsdoc-style block-comment nicely", ->
|
||||
input = """
|
||||
eqJS """
|
||||
###*
|
||||
* Multiline for jsdoc-"@doctags"
|
||||
*
|
||||
* @type {Function}
|
||||
###
|
||||
fn = () -> 1
|
||||
""",
|
||||
"""
|
||||
|
||||
output = """
|
||||
/**
|
||||
* Multiline for jsdoc-"@doctags"
|
||||
*
|
||||
@@ -325,12 +314,11 @@ test "#3132: Format hand-made (raw) jsdoc-style block-comment nicely", ->
|
||||
fn = function() {
|
||||
return 1;
|
||||
};"""
|
||||
eq toJS(input), output
|
||||
|
||||
# Although adequately working, block comment-placement is not yet perfect.
|
||||
# (Considering a case where multiple variables have been declared …)
|
||||
test "#3132: Place block-comments nicely", ->
|
||||
input = """
|
||||
eqJS """
|
||||
###*
|
||||
# A dummy class definition
|
||||
#
|
||||
@@ -350,9 +338,8 @@ test "#3132: Place block-comments nicely", ->
|
||||
###
|
||||
@instance = new DummyClass()
|
||||
|
||||
""",
|
||||
"""
|
||||
|
||||
output = """
|
||||
/**
|
||||
* A dummy class definition
|
||||
*
|
||||
@@ -383,22 +370,19 @@ test "#3132: Place block-comments nicely", ->
|
||||
return DummyClass;
|
||||
|
||||
})();"""
|
||||
eq toJS(input), output
|
||||
|
||||
test "#3638: Demand a whitespace after # symbol", ->
|
||||
input = """
|
||||
eqJS """
|
||||
###
|
||||
#No
|
||||
#whitespace
|
||||
###"""
|
||||
|
||||
output = """
|
||||
###""",
|
||||
"""
|
||||
/*
|
||||
#No
|
||||
#whitespace
|
||||
*/"""
|
||||
|
||||
eq toJS(input), output
|
||||
|
||||
test "#3761: Multiline comment at end of an object", ->
|
||||
anObject =
|
||||
|
||||
726
test/csx.coffee
Normal file
726
test/csx.coffee
Normal file
@@ -0,0 +1,726 @@
|
||||
# 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 '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 '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', ->
|
||||
throws -> CoffeeScript.compile '<div x=3 />'
|
||||
|
||||
test 'bare expressions not allowed', ->
|
||||
throws -> CoffeeScript.compile '<div x=y />'
|
||||
|
||||
test 'bare complex expressions not allowed', ->
|
||||
throws -> CoffeeScript.compile '<div x=f(3) />'
|
||||
|
||||
test 'unescaped opening tag angle bracket disallowed', ->
|
||||
throws -> CoffeeScript.compile '<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', ->
|
||||
throws -> CoffeeScript.compile '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 CSX', ->
|
||||
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 CSX 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 CSX 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 CSX
|
||||
# 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;
|
||||
|
||||
6 / 432 / gm;
|
||||
|
||||
<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)/;
|
||||
|
||||
<Person />;
|
||||
'''
|
||||
|
||||
test 'comment within CSX 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 CSX escape', ->
|
||||
eqJS '''
|
||||
<Person>
|
||||
{# i am a comment
|
||||
"i am a string"
|
||||
}
|
||||
</Person>
|
||||
''', '''
|
||||
<Person>
|
||||
{"i am a string"}
|
||||
</Person>;
|
||||
'''
|
||||
|
||||
test 'CSX comment cannot be used inside interpolation', ->
|
||||
throws -> CoffeeScript.compile '''
|
||||
<Person>
|
||||
{# i am a comment}
|
||||
</Person>
|
||||
'''
|
||||
|
||||
test 'comment syntax cannot be used inline', ->
|
||||
throws -> CoffeeScript.compile '''
|
||||
<Person>{#comment inline}</Person>
|
||||
'''
|
||||
|
||||
test 'string within CSX 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 CSX are ignored', ->
|
||||
eqJS """
|
||||
<Person> a,/';][' a\''@$%^&˚¬∑˜˚∆å∂¬˚*()*&^%$>> '"''"'''\'\'m' i </Person>
|
||||
""", """
|
||||
<Person> a,/';][' a''@$%^&˚¬∑˜˚∆å∂¬˚*()*&^%$>> '"''"'''''m' i </Person>;
|
||||
"""
|
||||
|
||||
test 'html entities (name, decimal, hex) within CSX', ->
|
||||
eqJS '''
|
||||
<Person> &&&€ € €;; </Person>
|
||||
''', '''
|
||||
<Person> &&&€ € €;; </Person>;
|
||||
'''
|
||||
|
||||
test 'tag with {{}}', ->
|
||||
eqJS '''
|
||||
<Person name={{value: item, key, item}} />
|
||||
''', '''
|
||||
<Person name={{
|
||||
value: item,
|
||||
key,
|
||||
item
|
||||
}} />;
|
||||
'''
|
||||
|
||||
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 />;
|
||||
'''
|
||||
|
||||
# TODO: Uncomment the following test once destructured object spreads are supported.
|
||||
# test 'self closing tag with spread attribute', ->
|
||||
# eqJS '''
|
||||
# <Component a={b} {... x } b="c" />
|
||||
# ''', '''
|
||||
# React.createElement(Component, Object.assign({"a": (b)}, x , {"b": "c"}))
|
||||
# '''
|
||||
|
||||
# TODO: Uncomment the following test once destructured object spreads are supported.
|
||||
# test 'complex spread attribute', ->
|
||||
# eqJS '''
|
||||
# <Component {...x} a={b} {... x } b="c" {...$my_xtraCoolVar123 } />
|
||||
# ''', '''
|
||||
# React.createElement(Component, Object.assign({}, x, {"a": (b)}, x , {"b": "c"}, $my_xtraCoolVar123 ))
|
||||
# '''
|
||||
|
||||
# TODO: Uncomment the following test once destructured object spreads are supported.
|
||||
# test 'multiline spread attribute', ->
|
||||
# eqJS '''
|
||||
# <Component {...
|
||||
# x } a={b} {... x } b="c" {...z }>
|
||||
# </Component>
|
||||
# ''', '''
|
||||
# React.createElement(Component, Object.assign({},
|
||||
# x , {"a": (b)}, x , {"b": "c"}, z )
|
||||
# )
|
||||
# '''
|
||||
|
||||
# TODO: Uncomment the following test once destructured object spreads are supported.
|
||||
# test 'multiline tag with spread attribute', ->
|
||||
# eqJS '''
|
||||
# <Component
|
||||
# z="1"
|
||||
# {...x}
|
||||
# a={b}
|
||||
# b="c"
|
||||
# >
|
||||
# </Component>
|
||||
# ''', '''
|
||||
# React.createElement(Component, Object.assign({ \
|
||||
# "z": "1"
|
||||
# }, x, { \
|
||||
# "a": (b), \
|
||||
# "b": "c"
|
||||
# })
|
||||
# )
|
||||
# '''
|
||||
|
||||
# TODO: Uncomment the following test once destructured object spreads are supported.
|
||||
# test 'multiline tag with spread attribute first', ->
|
||||
# eqJS '''
|
||||
# <Component
|
||||
# {...
|
||||
# x}
|
||||
# z="1"
|
||||
# a={b}
|
||||
# b="c"
|
||||
# >
|
||||
# </Component>
|
||||
# ''', '''
|
||||
# React.createElement(Component, Object.assign({}, \
|
||||
|
||||
# x, { \
|
||||
# "z": "1", \
|
||||
# "a": (b), \
|
||||
# "b": "c"
|
||||
# })
|
||||
# )
|
||||
# '''
|
||||
|
||||
# TODO: Uncomment the following test once destructured object spreads are supported.
|
||||
# test 'complex multiline spread attribute', ->
|
||||
# eqJS '''
|
||||
# <Component
|
||||
# {...
|
||||
# y} a={b} {... x } b="c" {...z }>
|
||||
# <div code={someFunc({a:{b:{}, C:'}'}})} />
|
||||
# </Component>
|
||||
# ''', '''
|
||||
# React.createElement(Component, Object.assign({}, \
|
||||
|
||||
# y, {"a": (b)}, x , {"b": "c"}, z ),
|
||||
# React.createElement("div", {"code": (someFunc({a:{b:{}, C:'}'}}))})
|
||||
# )
|
||||
# '''
|
||||
|
||||
# TODO: Uncomment the following test once destructured object spreads are supported.
|
||||
# test 'self closing spread attribute on single line', ->
|
||||
# eqJS '''
|
||||
# <Component a="b" c="d" {...@props} />
|
||||
# ''', '''
|
||||
# React.createElement(Component, Object.assign({"a": "b", "c": "d"}, @props ))
|
||||
# '''
|
||||
|
||||
# TODO: Uncomment the following test once destructured object spreads are supported.
|
||||
# test 'self closing spread attribute on new line', ->
|
||||
# eqJS '''
|
||||
# <Component
|
||||
# a="b"
|
||||
# c="d"
|
||||
# {...@props}
|
||||
# />
|
||||
# ''', '''
|
||||
# React.createElement(Component, Object.assign({ \
|
||||
# "a": "b", \
|
||||
# "c": "d"
|
||||
# }, @props
|
||||
# ))
|
||||
# '''
|
||||
|
||||
# TODO: Uncomment the following test once destructured object spreads are supported.
|
||||
# test 'self closing spread attribute on same line', ->
|
||||
# eqJS '''
|
||||
# <Component
|
||||
# a="b"
|
||||
# c="d"
|
||||
# {...@props} />
|
||||
# ''', '''
|
||||
# React.createElement(Component, Object.assign({ \
|
||||
# "a": "b", \
|
||||
# "c": "d"
|
||||
# }, @props ))
|
||||
# '''
|
||||
|
||||
# TODO: Uncomment the following test once destructured object spreads are supported.
|
||||
# test 'self closing spread attribute on next line', ->
|
||||
# eqJS '''
|
||||
# <Component
|
||||
# a="b"
|
||||
# c="d"
|
||||
# {...@props}
|
||||
|
||||
# />
|
||||
# ''', '''
|
||||
# React.createElement(Component, Object.assign({ \
|
||||
# "a": "b", \
|
||||
# "c": "d"
|
||||
# }, @props
|
||||
|
||||
# ))
|
||||
# '''
|
||||
|
||||
test 'empty strings are not converted to true', ->
|
||||
eqJS '''
|
||||
<Component val="" />
|
||||
''', '''
|
||||
<Component val="" />;
|
||||
'''
|
||||
|
||||
test 'CoffeeScript @ syntax in tag name', ->
|
||||
throws -> CoffeeScript.compile '''
|
||||
<@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', ->
|
||||
throws -> CoffeeScript.compile '''
|
||||
<a></a
|
||||
'''
|
||||
|
||||
# Tests for allowing less than operator without spaces when ther is no CSX
|
||||
|
||||
test 'unspaced less than without CSX: identifier', ->
|
||||
a = 3
|
||||
div = 5
|
||||
ok a<div
|
||||
|
||||
test 'unspaced less than without CSX: number', ->
|
||||
div = 5
|
||||
ok 3<div
|
||||
|
||||
test 'unspaced less than without CSX: paren', ->
|
||||
div = 5
|
||||
ok (3)<div
|
||||
|
||||
test 'unspaced less than without CSX: index', ->
|
||||
div = 5
|
||||
a = [3]
|
||||
ok a[0]<div
|
||||
|
||||
test 'tag inside CSX works following: identifier', ->
|
||||
eqJS '''
|
||||
<span>a<div /></span>
|
||||
''', '''
|
||||
<span>a<div /></span>;
|
||||
'''
|
||||
|
||||
test 'tag inside CSX works following: number', ->
|
||||
eqJS '''
|
||||
<span>3<div /></span>
|
||||
''', '''
|
||||
<span>3<div /></span>;
|
||||
'''
|
||||
|
||||
test 'tag inside CSX works following: paren', ->
|
||||
eqJS '''
|
||||
<span>(3)<div /></span>
|
||||
''', '''
|
||||
<span>(3)<div /></span>;
|
||||
'''
|
||||
|
||||
test 'tag inside CSX works following: square bracket', ->
|
||||
eqJS '''
|
||||
<span>]<div /></span>
|
||||
''', '''
|
||||
<span>]<div /></span>;
|
||||
'''
|
||||
|
||||
test 'unspaced less than inside CSX 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 CSX 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 CSX works but is not encouraged', ->
|
||||
eqJS '''
|
||||
div = 5
|
||||
html = <span />
|
||||
res = 2<div
|
||||
''', '''
|
||||
var div, html, res;
|
||||
|
||||
div = 5;
|
||||
|
||||
html = <span />;
|
||||
|
||||
res = 2 < div;
|
||||
'''
|
||||
@@ -1545,3 +1545,43 @@ test "#4248: Unicode code point escapes", ->
|
||||
'\\u{a}\\u{1111110000}'
|
||||
\ ^\^^^^^^^^^^^^^
|
||||
'''
|
||||
|
||||
test "CSX error: non-matching tag names", ->
|
||||
assertErrorFormat '''
|
||||
<div><span></div></span>
|
||||
''',
|
||||
'''
|
||||
[stdin]:1:7: error: expected corresponding CSX closing tag for span
|
||||
<div><span></div></span>
|
||||
^^^^
|
||||
'''
|
||||
|
||||
test "CSX error: bare expressions not allowed", ->
|
||||
assertErrorFormat '''
|
||||
<div x=3 />
|
||||
''',
|
||||
'''
|
||||
[stdin]:1:8: error: expected wrapped or quoted CSX attribute
|
||||
<div x=3 />
|
||||
^
|
||||
'''
|
||||
|
||||
test "CSX error: unescaped opening tag angle bracket disallowed", ->
|
||||
assertErrorFormat '''
|
||||
<Person><<</Person>
|
||||
''',
|
||||
'''
|
||||
[stdin]:1:9: error: unexpected <<
|
||||
<Person><<</Person>
|
||||
^^
|
||||
'''
|
||||
|
||||
test "CSX error: ambiguous tag-like expression", ->
|
||||
assertErrorFormat '''
|
||||
x = a <b > c
|
||||
''',
|
||||
'''
|
||||
[stdin]:1:10: error: missing </
|
||||
x = a <b > c
|
||||
^
|
||||
'''
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -300,18 +300,16 @@ test "#4248: Unicode code point escapes", ->
|
||||
ok /a\u{12345}c/.test 'a\ud808\udf45c'
|
||||
|
||||
# rewrite code point escapes unless u flag is set
|
||||
input = """
|
||||
eqJS """
|
||||
/\\u{bcdef}\\u{abc}/u
|
||||
"""
|
||||
output = """
|
||||
""",
|
||||
"""
|
||||
/\\u{bcdef}\\u{abc}/u;
|
||||
"""
|
||||
eq toJS(input), output
|
||||
|
||||
input = """
|
||||
eqJS """
|
||||
///#{ 'a' }\\u{bcdef}///
|
||||
"""
|
||||
output = """
|
||||
""",
|
||||
"""
|
||||
/a\\udab3\\uddef/;
|
||||
"""
|
||||
eq toJS(input), output
|
||||
|
||||
@@ -415,18 +415,16 @@ test "#4248: Unicode code point escapes", ->
|
||||
eq '\\u{123456}', "#{'\\'}#{'u{123456}'}"
|
||||
|
||||
# don't rewrite code point escapes
|
||||
input = """
|
||||
eqJS """
|
||||
'\\u{bcdef}\\u{abc}'
|
||||
"""
|
||||
output = """
|
||||
""",
|
||||
"""
|
||||
'\\u{bcdef}\\u{abc}';
|
||||
"""
|
||||
eq toJS(input), output
|
||||
|
||||
input = """
|
||||
eqJS """
|
||||
"#{ 'a' }\\u{bcdef}"
|
||||
"""
|
||||
output = """
|
||||
""",
|
||||
"""
|
||||
"a\\u{bcdef}";
|
||||
"""
|
||||
eq toJS(input), output
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# See http://wiki.ecmascript.org/doku.php?id=harmony:egal
|
||||
# See [http://wiki.ecmascript.org/doku.php?id=harmony:egal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
|
||||
egal = (a, b) ->
|
||||
if a is b
|
||||
a isnt 0 or 1/a is 1/b
|
||||
@@ -13,9 +13,20 @@ arrayEgal = (a, b) ->
|
||||
return no for el, idx in a when not arrayEgal el, b[idx]
|
||||
yes
|
||||
|
||||
exports.eq = (a, b, msg) -> ok egal(a, b), msg or "Expected #{a} to equal #{b}"
|
||||
exports.arrayEq = (a, b, msg) -> ok arrayEgal(a,b), msg or "Expected #{a} to deep equal #{b}"
|
||||
exports.eq = (a, b, msg) ->
|
||||
ok egal(a, b), msg or
|
||||
"Expected #{reset}#{a}#{red} to equal #{reset}#{b}#{red}"
|
||||
|
||||
exports.toJS = (str) ->
|
||||
CoffeeScript.compile str, bare: yes
|
||||
.replace /^\s+|\s+$/g, '' # Trim leading/trailing whitespace
|
||||
exports.arrayEq = (a, b, msg) ->
|
||||
ok arrayEgal(a,b), msg or
|
||||
"Expected #{reset}#{a}#{red} to deep equal #{reset}#{b}#{red}"
|
||||
|
||||
exports.eqJS = (input, expectedOutput, msg) ->
|
||||
actualOutput = CoffeeScript.compile input, bare: yes
|
||||
.replace /^\s+|\s+$/g, '' # Trim leading/trailing whitespace.
|
||||
|
||||
ok egal(expectedOutput, actualOutput), msg or
|
||||
"""Expected generated JavaScript to be:
|
||||
#{reset}#{expectedOutput}#{red}
|
||||
but instead it was:
|
||||
#{reset}#{actualOutput}#{red}"""
|
||||
|
||||
Reference in New Issue
Block a user