diff --git a/internal_packages/composer/lib/contenteditable-component.cjsx b/internal_packages/composer/lib/contenteditable-component.cjsx
index b99930398..a169ac9fe 100644
--- a/internal_packages/composer/lib/contenteditable-component.cjsx
+++ b/internal_packages/composer/lib/contenteditable-component.cjsx
@@ -670,53 +670,57 @@ class ContenteditableComponent extends React.Component
-
####### CLEAN PASTE #########
_onPaste: (evt) =>
- html = evt.clipboardData.getData("text/html") ? ""
- if html.length is 0
- text = evt.clipboardData.getData("text/plain") ? ""
- if text.length > 0
- evt.preventDefault()
- cleanHtml = text
- else
- else
- evt.preventDefault()
- cleanHtml = @_sanitizeHtml(html)
+ inputText = evt.clipboardData.getData("text/html") ? ""
+ type = "text/html"
+ if inputText.length is 0
+ inputText = evt.clipboardData.getData("text/plain") ? ""
+ type = "text/plain"
- document.execCommand("insertHTML", false, cleanHtml)
+ if inputText.length > 0
+ cleanHtml = @_sanitizeInput(inputText, type)
+ document.execCommand("insertHTML", false, cleanHtml)
+
+ evt.preventDefault()
return false
# This is used primarily when pasting text in
- _sanitizeHtml: (html) =>
- cleanHTML = sanitizeHtml html.replace(/[\n\r]/g, "
"),
- allowedTags: ['p', 'b', 'i', 'em', 'strong', 'a', 'br', 'img', 'ul', 'ol', 'li', 'strike']
- allowedAttributes:
- a: ['href', 'name']
- img: ['src', 'alt']
- transformTags:
- h1: "p"
- h2: "p"
- h3: "p"
- h4: "p"
- h5: "p"
- h6: "p"
- div: "p"
- pre: "p"
- blockquote: "p"
- table: "p"
+ _sanitizeInput: (inputText="", type="text/html") =>
+ if type is "text/plain"
+ inputText = Utils.encodeHTMLEntities(inputText)
+ inputText = inputText.replace(/[\r\n]|[03];/g, "
").
+ replace(/\s\s/g, " ")
+ else
+ inputText = sanitizeHtml inputText.replace(/[\n\r]/g, "
"),
+ allowedTags: ['p', 'b', 'i', 'em', 'strong', 'a', 'br', 'img', 'ul', 'ol', 'li', 'strike']
+ allowedAttributes:
+ a: ['href', 'name']
+ img: ['src', 'alt']
+ transformTags:
+ h1: "p"
+ h2: "p"
+ h3: "p"
+ h4: "p"
+ h5: "p"
+ h6: "p"
+ div: "p"
+ pre: "p"
+ blockquote: "p"
+ table: "p"
- # We sanitized everything and convert all whitespace-inducing elements
- # into
tags. We want to de-wrap
tags and replace with two line - # breaks instead. - cleanHTML = cleanHTML.replace(/
/gim, "").replace(/<\/p>/gi, "
")
+ # We sanitized everything and convert all whitespace-inducing
+ # elements into
tags. We want to de-wrap
tags and replace + # with two line breaks instead. + inputText = inputText.replace(/
/gim, "").
+ replace(/<\/p>/gi, "
")
- # We never want more then 2 line breaks in a row.
- # https://regex101.com/r/gF6bF4/4
- cleanHTML = cleanHTML.replace(/(
\s*){3,}/g, "
")
+ # We never want more then 2 line breaks in a row.
+ # https://regex101.com/r/gF6bF4/4
+ inputText = inputText.replace(/(
\s*){3,}/g, "
")
- return cleanHTML
+ return inputText
@@ -744,4 +748,4 @@ class ContenteditableComponent extends React.Component
else return (innerHTML + @props.html.substr(quoteStart))
-module.exports = ContenteditableComponent
\ No newline at end of file
+module.exports = ContenteditableComponent
diff --git a/internal_packages/composer/spec/contenteditable-component-spec.cjsx b/internal_packages/composer/spec/contenteditable-component-spec.cjsx
index f9663535e..3bc4af042 100644
--- a/internal_packages/composer/spec/contenteditable-component-spec.cjsx
+++ b/internal_packages/composer/spec/contenteditable-component-spec.cjsx
@@ -43,3 +43,77 @@ describe "ContenteditableComponent", ->
expect(@onChange.callCount).toBe(1)
@performEdit(@changedHtmlWithoutQuote)
expect(@onChange.callCount).toBe(2)
+
+ describe "pasting behavior", ->
+ tests = [
+ {
+ in: ""
+ sanitizedAsHTML: ""
+ sanitizedAsPlain: ""
+ },
+ {
+ in: "Hello World"
+ sanitizedAsHTML: "Hello World"
+ sanitizedAsPlain: "Hello World"
+ },
+ {
+ in: " Hello World"
+ # Should collapse to 1 space when rendered
+ sanitizedAsHTML: " Hello World"
+ # Preserving 2 spaces
+ sanitizedAsPlain: " Hello World"
+ },
+ {
+ in: " Hello World"
+ sanitizedAsHTML: " Hello World"
+ # Preserving 3 spaces
+ sanitizedAsPlain: " Hello World"
+ },
+ {
+ in: " Hello World"
+ sanitizedAsHTML: " Hello World"
+ # Preserving 4 spaces
+ sanitizedAsPlain: " Hello World"
+ },
+ {
+ in: "Hello\nWorld"
+ sanitizedAsHTML: "Hello
World"
+ # Convert newline to br
+ sanitizedAsPlain: "Hello
World"
+ },
+ {
+ in: "Hello\rWorld"
+ sanitizedAsHTML: "Hello
World"
+ # Convert carriage return to br
+ sanitizedAsPlain: "Hello
World"
+ },
+ {
+ in: "Hello\n\n\nWorld"
+ # Never have more than 2 br's in a row
+ sanitizedAsHTML: "Hello
World"
+ # Convert multiple newlines to same number of brs
+ sanitizedAsPlain: "Hello
World"
+ },
+ {
+ in: " Foo Bar