Skip to content

Commit ec4ec1b

Browse files
committed
fixed some bugs relating to self closing tags with spread, added more test cases
1 parent 6abc1eb commit ec4ec1b

File tree

2 files changed

+95
-13
lines changed

2 files changed

+95
-13
lines changed

src/serialiser.coffee

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,42 +39,68 @@ class Serialiser
3939
serialised
4040

4141
serialiseSpreadAndPairAttributes: (children) ->
42-
assigns = []
43-
pairAttrsBuffer = []
42+
assigns = [] # nodes
43+
pairAttrsBuffer = [] # nodes
4444

4545
flushPairs = =>
4646
if pairAttrsBuffer.length
4747
serialisedChild = @serialiseAttributePairs(pairAttrsBuffer)
4848
if serialisedChild
49-
assigns.push(serialisedChild)
49+
assigns.push(type: $.CS, value: serialisedChild)
5050
else
51-
assigns.push(type: $.CJSX_WHITESPACE, value: pairAttrsBuffer.map(@serialiseNode.bind(this)).join('').replace('\n', '\\\n'))
51+
serialisedPairs = pairAttrsBuffer
52+
.map((p) => @serialiseNode(p))
53+
.join('')
54+
# escaping newlines might create a syntax error if the newline is
55+
# after the last arg in a list, so we'll fix it below
56+
.replace('\n', '\\\n')
57+
assigns.push(type: $.CJSX_WHITESPACE, value: serialisedPairs)
5258
pairAttrsBuffer = [] # reset buffer
5359

60+
# okay this is pretty gross. once source maps are up and running all of the
61+
# whitespace related bs can be nuked as there will no longer be a need to
62+
# torture the CS syntax to maintain whitespace and output the same number
63+
# of lines while also transforming syntax. however in the mean time, this is
64+
# what we're doing.
65+
66+
# this code rewrites attr pair, spread, etc nodes into CS (code fragment)
67+
# and whitespace nodes. then they are serialised and joined with whitespace
68+
# maintained, and newlines escaped (except at the end of an args list)
69+
70+
# initial object assign arg
5471
if firstNonWhitespaceChild(children)?.type is $.CJSX_ATTR_SPREAD
55-
assigns.push('{}')
72+
assigns.push(type: $.CS, value: '{}')
5673

74+
# group sets of attr pairs between spreads
5775
for child, childIndex in children
5876
if child.type is $.CJSX_ATTR_SPREAD
5977
flushPairs()
60-
assigns.push(child.value)
78+
assigns.push(type: $.CS, value: child.value)
6179
else
6280
pairAttrsBuffer.push(child)
6381

82+
# finally group any remaining pairs
6483
flushPairs()
6584

85+
# serialising the rewritten nodes with whitespace maintained
6686
accumulatedWhitespace = ''
67-
assignsWithWhitespace = []
87+
assignsWithWhitespace = [] # serialised nodes texts
6888
for assignItem, assignIndex in assigns
69-
if typeof assignItem is 'object' and assignItem?.type is $.CJSX_WHITESPACE
70-
accumulatedWhitespace += assignItem.value
71-
if typeof assignItem is 'string'
72-
assignsWithWhitespace.push accumulatedWhitespace+assignItem
73-
accumulatedWhitespace = ''
89+
if assignItem?
90+
if assignItem.type is $.CJSX_WHITESPACE
91+
accumulatedWhitespace += @serialiseNode(assignItem)
92+
else
93+
assignsWithWhitespace.push(accumulatedWhitespace + @serialiseNode(assignItem))
94+
accumulatedWhitespace = ''
7495

7596
if assignsWithWhitespace.length
7697
lastAssignWithWhitespace = assignsWithWhitespace.pop()
77-
assignsWithWhitespace.push lastAssignWithWhitespace+accumulatedWhitespace
98+
# hack to fix potential syntax error when newlines are escaped after last arg
99+
# TODO: kill this with fire once sourcemaps are available
100+
trailingWhiteplace = accumulatedWhitespace.replace('\\\n', '\n')
101+
assignsWithWhitespace.push(lastAssignWithWhitespace + trailingWhiteplace)
102+
103+
joinedAssigns = joinList(assignsWithWhitespace)
78104

79105
"React.__spread(#{joinList(assignsWithWhitespace)})"
80106

test/output-testcases.txt

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,62 @@ React.createElement(Component, React.__spread({}, \
656656
)
657657
##end
658658

659+
##desc
660+
self closing spread attribute on single line
661+
##input
662+
<Component a="b" c="d" {...@props} />
663+
##expected
664+
React.createElement(Component, React.__spread({"a": "b", "c": "d"}, @props ))
665+
##end
666+
667+
##desc
668+
self closing spread attribute on new line
669+
##input
670+
<Component
671+
a="b"
672+
c="d"
673+
{...@props}
674+
/>
675+
##expected
676+
React.createElement(Component, React.__spread({ \
677+
"a": "b", \
678+
"c": "d"
679+
}, @props
680+
))
681+
##end
682+
683+
##desc
684+
self closing spread attribute on same line
685+
##input
686+
<Component
687+
a="b"
688+
c="d"
689+
{...@props} />
690+
##expected
691+
React.createElement(Component, React.__spread({ \
692+
"a": "b", \
693+
"c": "d"
694+
}, @props ))
695+
##end
696+
697+
##desc
698+
self closing spread attribute on next line
699+
##input
700+
<Component
701+
a="b"
702+
c="d"
703+
{...@props}
704+
705+
/>
706+
##expected
707+
React.createElement(Component, React.__spread({ \
708+
"a": "b", \
709+
"c": "d"
710+
}, @props
711+
712+
))
713+
##end
714+
659715
##desc
660716
Empty strings are not converted to true
661717
##input

0 commit comments

Comments
 (0)