fix(quoted): fix quoted text issue with single blockquotes

Fixes #1084
Also fixes broken tokenizing text field specs
Also protects `MessageBodyExtension`s from errors
This commit is contained in:
Evan Morikawa 2016-01-28 17:24:29 -08:00
parent 9dab8d6335
commit 8f384bb4e8
6 changed files with 285 additions and 15 deletions

View file

@ -295,22 +295,29 @@ describe 'TokenizingTextField', ->
expect(@tabDownEvent.stopPropagation).toHaveBeenCalled()
describe "when blurred", ->
it 'should do nothing if the relatedTarget is null meaning the app has been blurged', ->
ReactTestUtils.Simulate.focus(@renderedInput)
ReactTestUtils.Simulate.change(@renderedInput, {target: {value: 'text'}})
ReactTestUtils.Simulate.blur(@renderedInput, {relatedTarget: null})
expect(@propAdd).not.toHaveBeenCalled()
expect(ReactTestUtils.scryRenderedDOMComponentsWithClass(@renderedField, 'focused').length).toBe(1)
it 'should call add, allowing the parent component to (optionally) turn the entered text into a token', ->
ReactTestUtils.Simulate.focus(@renderedInput)
ReactTestUtils.Simulate.change(@renderedInput, {target: {value: 'text'}})
ReactTestUtils.Simulate.blur(@renderedInput)
ReactTestUtils.Simulate.blur(@renderedInput, {relatedTarget: document.body})
expect(@propAdd).toHaveBeenCalledWith('text', {})
it 'should clear the entered text', ->
ReactTestUtils.Simulate.focus(@renderedInput)
ReactTestUtils.Simulate.change(@renderedInput, {target: {value: 'text'}})
ReactTestUtils.Simulate.blur(@renderedInput)
ReactTestUtils.Simulate.blur(@renderedInput, {relatedTarget: document.body})
expect(@renderedInput.value).toBe('')
it 'should no longer have the `focused` class', ->
ReactTestUtils.Simulate.focus(@renderedInput)
expect(ReactTestUtils.scryRenderedDOMComponentsWithClass(@renderedField, 'focused').length).toBe(1)
ReactTestUtils.Simulate.blur(@renderedInput)
ReactTestUtils.Simulate.blur(@renderedInput, {relatedTarget: document.body})
expect(ReactTestUtils.scryRenderedDOMComponentsWithClass(@renderedField, 'focused').length).toBe(0)
describe "when the user double-clicks a token", ->

140
spec/fixtures/emails/email_17.html vendored Normal file
View file

@ -0,0 +1,140 @@
<table width=3D"600" border=3D"0" align=3D"center" cellpadding=3D"0" cellsp=
acing=3D"0" bgcolor=3D"#ffffff"><tbody><tr><td colspan=3D"3"><table border=
=3D"0" cellpadding=3D"0" cellspacing=3D"0" width=3D"100%"></table></td></tr=
><tr><td valign=3D"top" width=3D"1"><img src=3D"http://gs.place.edu/file=
s/gs/place-gs-lockup.gif"></td></tr></tbody>
<tbody>
<tr>
<td width=3D"583" align=3D"left">&nbsp;</td>
</tr>
<tr></tr>
<tr>
<td colspan=3D"2" valign=3D"top" style=3D"padding:15pt 15px;font-fami=
ly:Arial,Helvetica,sans-serif;font-size:12px;color:rgb(0,0,0);text-align:le=
ft">Dear FOOBAR,</td>
</tr>
<tr>
<td colspan=3D"2" valign=3D"top" style=3D"padding:5pt 15px;font-famil=
y:Arial,Helvetica,sans-serif;font-size:12px;color:rgb(0,0,0);text-align:lef=
t">It is my sincere pleasure to inform you that you have been selected for =
membership in the Honor Society of the School of General Studies. The Socie=
ty was created in 1997 to celebrate the academic achievement of exceptional=
GS scholars. Only juniors or seniors with a grade point average of 3.8 or =
above who have completed at least 30 points at place are eligible for me=
mbership. The chief aim of the Honor Society is to cultivate interaction am=
ong students committed to intellectual discovery and the faculty who enjoy =
teaching them. </td>
</tr>
<tr>
<td colspan=3D"2" valign=3D"top" style=3D"padding:5pt 15px;font-famil=
y:Arial,Helvetica,sans-serif;font-size:12px;color:rgb(0,0,0);text-align:lef=
t">Please join us for the Induction Ceremony, with a reception to follow.</=
td>
</tr>
<tr>
<td colspan=3D"2" valign=3D"top" style=3D"padding:5pt 15px;font-famil=
y:Arial,Helvetica,sans-serif;font-size:12px;color:rgb(0,0,0);text-align:lef=
t"><blockquote>
<p><strong>Induction Ceremony <br>
Honor Society</strong><br>
<br>
Reception to follow.</p>
</blockquote></td>
</tr>
<tr>
<td colspan=3D"2" valign=3D"top" style=3D"padding:5pt 15px;font-famil=
y:Arial,Helvetica,sans-serif;font-size:12px;color:rgb(0,0,0);text-align:lef=
t">The <a href=3D"http://place.us6.list-manage.com/track/click?u=3D257ce=
e2ddd47afbb8be32c6ce&amp;id=3D639cf43a42&amp;e=3D223ebffa5a" style=3D"color=
:#5d82de" target=3D"_blank">favor of a reply</a> is requested by Friday, J=
anuary 29 at 5 p.m. You are invited to bring one guest; business attire is =
requested.</td>
</tr>
<tr>
<td colspan=3D"2" valign=3D"top" style=3D"padding:5pt 15px;font-famil=
y:Arial,Helvetica,sans-serif;font-size:12px;color:rgb(0,0,0);text-align:lef=
t">I look forward to celebrating with you soon.</td>
</tr>
<tr>
<td colspan=3D"2" valign=3D"top" style=3D"padding:5pt 15px;font-famil=
y:Arial,Helvetica,sans-serif;font-size:12px;color:rgb(0,0,0);text-align:lef=
t"><p>Best wishes,<br>
<img src=3D"http://gs.place.edu/files/gs/BAR_signature.jpg" alt=
=3D"Dean FOO J. BAR" width=3D"148" height=3D"44" border=3D"0" style=3D"pa=
dding-top:15px;padding-left:0px" title=3D"place University School of Gen=
eral Studies"><br>
FOO J. BAR<br>
Dean <br>
University<br>
<br>
<br>
N.B. A printed letter concerning your selection has been mailed to =
your local address.</p></td>
</tr>
<tr>
<td colspan=3D"2" valign=3D"top" style=3D"padding:0pt 15px;font-famil=
y:Arial,Helvetica,sans-serif;font-size:12px;color:rgb(0,0,0);text-align:lef=
t">&nbsp;</td>
</tr>
<tr>
<td colspan=3D"2" valign=3D"top" style=3D"padding:0pt 15px;font-famil=
y:Arial,Helvetica,sans-serif;font-size:12px;color:rgb(0,0,0);text-align:lef=
t"></td>
</tr>
</tbody>
<tbody>
<tr>
<td valign=3D"top" width=3D"598"><table border=3D"0" cellpadding=3D"0=
" cellspacing=3D"0" width=3D"594"></table></td><td align=3D"left" valign=3D=
"top" width=3D"1"><img src=3D"http://www.place.edu/cu/gs/images/yrp_spac=
er.jpg"></td>
</tr>
</tbody>
</table>
<center>
<br>
<br>
<br>
<br>
<br>
<br>
<table border=3D"0" cellpadding=3D"0" cellspacing=3D"0" wid=
th=3D"100%" style=3D"background-color:#ffffff;border-top:1px solid #e5e5e5"=
>
<tbody><tr>
<td align=3D"center" valign=3D"top" style=3D"paddin=
g-top:20px;padding-bottom:20px">
<table border=3D"0" cellpadding=3D"0" cellspaci=
ng=3D"0">
<tbody><tr>
<td align=3D"center" valign=3D"top" sty=
le=3D"color:#606060;font-family:Helvetica,Arial,sans-serif;font-size:11px;l=
ine-height:150%;padding-right:20px;padding-bottom:5px;padding-left:20px;tex=
t-align:center">
This email was sent to <a href=3D"m=
ailto:FOOBAR.BAZ@place.edu" style=3D"color:#404040!important" target=3D"_b=
lank">FOOBAR.BAZ@place.edu</a>
<br>
<a href=3D"http://place.us6.list=
-manage1.com/about?u=xxxxxxxxxxxxxxxxxxxxxxxxxxx&amp;id=xxxxxxxxxxxx&amp;e=
=3D223ebffa5a&amp;c=3Df2c0d84500" style=3D"color:#404040!important" target=
=3D"_blank"><em>why did I get this?</em></a>&nbsp;&nbsp;&nbsp;&nbsp;<a href=
=3D"http://place.us6.list-manage1.com/unsubscribe?u=xxxxxxxxxxxxxxxxxxxx=
e32c6ce&amp;id=3Dcebd346d3d&amp;e=3D223ebffa5a&amp;c=3Df2c0d84500" style=3D=
"color:#404040!important" target=3D"_blank">unsubscribe from this list</a>&=
nbsp;&nbsp;&nbsp;&nbsp;<a href=3D"http://place.us6.list-manage2.com/prof=
ile?u=3D257cee2ddd47afbb8be32c6ce&amp;id=3Dcebd346d3d&amp;e=3D223ebffa5a" s=
tyle=3D"color:#404040!important" target=3D"_blank">update subscription pref=
erences</a>
<br>
place
<br>
<br>
=20
</td>
</tr>
</tbody></table>
</td>
</tr>
</tbody></table>
</center>

View file

@ -0,0 +1,94 @@
<head></head><body><table width="3D&quot;600&quot;" border="3D&quot;0&quot;" align="3D&quot;center&quot;" cellpadding="3D&quot;0&quot;" cellsp="acing=3D&quot;0&quot;" bgcolor="3D&quot;#ffffff&quot;"><tbody><tr><td colspan="3D&quot;3&quot;"><table border="=3D&quot;0&quot;" cellpadding="3D&quot;0&quot;" cellspacing="3D&quot;0&quot;" width="3D&quot;100%&quot;"></table></td></tr><tr><td valign="3D&quot;top&quot;" width="3D&quot;1&quot;"><img src="3D&quot;http://gs.place.edu/file=" s="" gs="" place-gs-lockup.gif"=""></td></tr></tbody>
<tbody>
<tr>
<td width="3D&quot;583&quot;" align="3D&quot;left&quot;">&nbsp;</td>
</tr>
<tr></tr>
<tr>
<td colspan="3D&quot;2&quot;" valign="3D&quot;top&quot;" style="3D&quot;padding:15pt" 15px;font-fami="ly:Arial,Helvetica,sans-serif;font-size:12px;color:rgb(0,0,0);text-align:le=" ft"="">Dear FOOBAR,</td>
</tr>
<tr>
<td colspan="3D&quot;2&quot;" valign="3D&quot;top&quot;" style="3D&quot;padding:5pt" 15px;font-famil="y:Arial,Helvetica,sans-serif;font-size:12px;color:rgb(0,0,0);text-align:lef=" t"="">It is my sincere pleasure to inform you that you have been selected for =
membership in the Honor Society of the School of General Studies. The Socie=
ty was created in 1997 to celebrate the academic achievement of exceptional=
GS scholars. Only juniors or seniors with a grade point average of 3.8 or =
above who have completed at least 30 points at place are eligible for me=
mbership. The chief aim of the Honor Society is to cultivate interaction am=
ong students committed to intellectual discovery and the faculty who enjoy =
teaching them. </td>
</tr>
<tr>
<td colspan="3D&quot;2&quot;" valign="3D&quot;top&quot;" style="3D&quot;padding:5pt" 15px;font-famil="y:Arial,Helvetica,sans-serif;font-size:12px;color:rgb(0,0,0);text-align:lef=" t"="">Please join us for the Induction Ceremony, with a reception to follow.<!--=
td-->
</td></tr>
<tr>
<td colspan="3D&quot;2&quot;" valign="3D&quot;top&quot;" style="3D&quot;padding:5pt" 15px;font-famil="y:Arial,Helvetica,sans-serif;font-size:12px;color:rgb(0,0,0);text-align:lef=" t"=""><blockquote>
<p><strong>Induction Ceremony <br>
Honor Society</strong><br>
<br>
Reception to follow.</p>
</blockquote></td>
</tr>
<tr>
<td colspan="3D&quot;2&quot;" valign="3D&quot;top&quot;" style="3D&quot;padding:5pt" 15px;font-famil="y:Arial,Helvetica,sans-serif;font-size:12px;color:rgb(0,0,0);text-align:lef=" t"="">The <a href="3D&quot;http://place.us6.list-manage.com/track/click?u=3D257ce=" e2ddd47afbb8be32c6ce&amp;id="3D639cf43a42&amp;e=3D223ebffa5a&quot;" style="3D&quot;color=" :#5d82de"="" target="3D&quot;_blank&quot;">favor of a reply</a> is requested by Friday, J=
anuary 29 at 5 p.m. You are invited to bring one guest; business attire is =
requested.</td>
</tr>
<tr>
<td colspan="3D&quot;2&quot;" valign="3D&quot;top&quot;" style="3D&quot;padding:5pt" 15px;font-famil="y:Arial,Helvetica,sans-serif;font-size:12px;color:rgb(0,0,0);text-align:lef=" t"="">I look forward to celebrating with you soon.</td>
</tr>
<tr>
<td colspan="3D&quot;2&quot;" valign="3D&quot;top&quot;" style="3D&quot;padding:5pt" 15px;font-famil="y:Arial,Helvetica,sans-serif;font-size:12px;color:rgb(0,0,0);text-align:lef=" t"=""><p>Best wishes,<br>
<img src="3D&quot;http://gs.place.edu/files/gs/BAR_signature.jpg&quot;" alt="=3D&quot;Dean" foo="" j.="" bar"="" width="3D&quot;148&quot;" height="3D&quot;44&quot;" border="3D&quot;0&quot;" style="3D&quot;pa=" dding-top:15px;padding-left:0px"="" title="3D&quot;place" university="" school="" of="" gen="eral" studies"=""><br>
FOO J. BAR<br>
Dean <br>
University<br>
<br>
<br>
N.B. A printed letter concerning your selection has been mailed to =
your local address.</p></td>
</tr>
<tr>
<td colspan="3D&quot;2&quot;" valign="3D&quot;top&quot;" style="3D&quot;padding:0pt" 15px;font-famil="y:Arial,Helvetica,sans-serif;font-size:12px;color:rgb(0,0,0);text-align:lef=" t"="">&nbsp;</td>
</tr>
<tr>
<td colspan="3D&quot;2&quot;" valign="3D&quot;top&quot;" style="3D&quot;padding:0pt" 15px;font-famil="y:Arial,Helvetica,sans-serif;font-size:12px;color:rgb(0,0,0);text-align:lef=" t"=""></td>
</tr>
</tbody>
<tbody>
<tr>
<td valign="3D&quot;top&quot;" width="3D&quot;598&quot;"><table border="3D&quot;0&quot;" cellpadding="3D&quot;0=" "="" cellspacing="3D&quot;0&quot;" width="3D&quot;594&quot;"></table></td><td align="3D&quot;left&quot;" valign="3D=" "top"="" width="3D&quot;1&quot;"><img src="3D&quot;http://www.place.edu/cu/gs/images/yrp_spac=" er.jpg"=""></td>
</tr>
</tbody>
</table>
<center>
<br>
<br>
<br>
<br>
<br>
<br>
<table border="3D&quot;0&quot;" cellpadding="3D&quot;0&quot;" cellspacing="3D&quot;0&quot;" wid="th=3D&quot;100%&quot;" style="3D&quot;background-color:#ffffff;border-top:1px" solid="" #e5e5e5"="">
<tbody><tr>
<td align="3D&quot;center&quot;" valign="3D&quot;top&quot;" style="3D&quot;paddin=" g-top:20px;padding-bottom:20px"="">
<table border="3D&quot;0&quot;" cellpadding="3D&quot;0&quot;" cellspaci="ng=3D&quot;0&quot;">
<tbody><tr>
<td align="3D&quot;center&quot;" valign="3D&quot;top&quot;" sty="le=3D&quot;color:#606060;font-family:Helvetica,Arial,sans-serif;font-size:11px;l=" ine-height:150%;padding-right:20px;padding-bottom:5px;padding-left:20px;tex="t-align:center&quot;">
This email was sent to <a href="3D&quot;m=" ailto:foobar.baz@place.edu"="" style="3D&quot;color:#404040!important&quot;" target="3D&quot;_b=" lank"="">FOOBAR.BAZ@place.edu</a>
<br>
<a href="3D&quot;http://place.us6.list=" -manage1.com="" about?u="xxxxxxxxxxxxxxxxxxxxxxxxxxx&amp;id=xxxxxxxxxxxx&amp;e=" =3d223ebffa5a&amp;c="3Df2c0d84500&quot;" style="3D&quot;color:#404040!important&quot;" target="=3D&quot;_blank&quot;"><em>why did I get this?</em></a>&nbsp;&nbsp;&nbsp;&nbsp;<a href="=3D&quot;http://place.us6.list-manage1.com/unsubscribe?u=xxxxxxxxxxxxxxxxxxxx=" e32c6ce&amp;id="3Dcebd346d3d&amp;e=3D223ebffa5a&amp;c=3Df2c0d84500&quot;" style="3D=" "color:#404040!important"="" target="3D&quot;_blank&quot;">unsubscribe from this list</a>&amp;=
nbsp;&nbsp;&nbsp;&nbsp;<a href="3D&quot;http://place.us6.list-manage2.com/prof=" ile?u="3D257cee2ddd47afbb8be32c6ce&amp;id=3Dcebd346d3d&amp;e=3D223ebffa5a&quot;" s="tyle=3D&quot;color:#404040!important&quot;" target="3D&quot;_blank&quot;">update subscription pref=
erences</a>
<br>
place
<br>
<br>
=20
</td>
</tr>
</tbody></table>
</td>
</tr>
</tbody></table>
</center>
</body>

View file

@ -19,7 +19,7 @@ describe "QuotedHTMLTransformer", ->
re = new RegExp(QuotedHTMLTransformer.annotationClass, 'g')
html.match(re)?.length ? 0
[1..16].forEach (n) ->
[1..17].forEach (n) ->
it "properly parses email_#{n}", ->
opts = keepIfWholeBodyIsQuote: true
expect(removeQuotedHTML("email_#{n}.html", opts)).toEqual readFile("email_#{n}_stripped.html")
@ -268,6 +268,35 @@ describe "QuotedHTMLTransformer", ->
after: """<head></head><body></body>
"""
# Test 12: Make sure that a single quote inside of a bunch of other
# content is detected. We used to have a bug where we were only
# looking at the common ancestor of blockquotes (and if there's 1 then
# the ancestor is itself). We now look at the root document for
# trailing text.
tests.push
before: """
<br>
Yo
<table><tbody>
<tr><td>A</td><td>B</td></tr>
<tr><td>C</td><td><blockquote>SAVE ME</blockquote></td></tr>
<tr><td>E</td><td>F</td></tr>
</tbody></table>
Yo
<br>
"""
after: """<head></head><body>
<br>
Yo
<table><tbody>
<tr><td>A</td><td>B</td></tr>
<tr><td>C</td><td><blockquote>SAVE ME</blockquote></td></tr>
<tr><td>E</td><td>F</td></tr>
</tbody></table>
Yo
<br></body>
"""
it 'works with these manual test cases', ->
for {before, after} in tests
opts = keepIfWholeBodyIsQuote: true
@ -318,7 +347,7 @@ describe "QuotedHTMLTransformer", ->
# `QuotedHTMLTransformer` needs Electron booted up in order to work because
# of the DOMParser.
xit "Run this simple funciton to generate output files", ->
[16].forEach (n) ->
[17].forEach (n) ->
newHTML = QuotedHTMLTransformer.removeQuotedHTML(readFile("email_#{n}.html"))
outPath = path.resolve(__dirname, 'fixtures', 'emails', "email_#{n}_raw_stripped.html")
fs.writeFileSync(outPath, newHTML)

View file

@ -49,10 +49,15 @@ class MessageBodyProcessor
# allow them to modify anything but the body for the time being.
for extension in MessageStore.extensions()
continue unless extension.formatMessageBody
virtual = message.clone()
virtual.body = body
extension.formatMessageBody({message: virtual})
body = virtual.body
latestBody = body
try
virtual = message.clone()
virtual.body = body
extension.formatMessageBody({message: virtual})
body = virtual.body
catch err
NylasEnv.emitError(err)
body = latestBody
# Find inline images and give them a calculated CSS height based on
# html width and height, when available. This means nothing changes size

View file

@ -117,12 +117,7 @@ class QuotedHTMLTransformer
# end of a message. If there were non quoted content after, it'd be
# inline.
# We first need to find the common ancestor of the quoteElements.
# This tells us what depth to look at to determine if there's real
# content after us.
ancestor = DOMUtils.commonAncestor(quoteElements)
trailingQuotes = @_findTrailingQuotes(ancestor, quoteElements)
trailingQuotes = @_findTrailingQuotes(doc, quoteElements)
# Only keep the trailing quotes so we can delete them.
quoteElements = _.intersection(quoteElements, trailingQuotes)