Skip to content

Commit

Permalink
Prefer pasting text/plain when the text/html clipboard data is equive…
Browse files Browse the repository at this point in the history
…lant to help preserve whitespace characters. Closes #246
  • Loading branch information
javan committed Jun 10, 2016
1 parent 029c461 commit 41352e0
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 13 deletions.
35 changes: 25 additions & 10 deletions src/trix/controllers/input_controller.coffee
Expand Up @@ -3,7 +3,8 @@
#= require trix/controllers/composition_input_controller

{handleEvent, findClosestElementFromNode, findElementFromContainerAndOffset,
defer, makeElement, innerElementIsActive, summarizeStringChange, objectsAreEqual} = Trix
defer, makeElement, innerElementIsActive, summarizeStringChange, objectsAreEqual,
tagName} = Trix

class Trix.InputController extends Trix.BasicObject
pastedFileCount = 0
Expand Down Expand Up @@ -212,7 +213,17 @@ class Trix.InputController extends Trix.BasicObject
@delegate?.inputControllerDidPaste(pasteData)
return

if html = paste.getData("text/html")
if dataTransferIsPlainText(paste)
string = paste.getData("text/plain")
pasteData.string = string
@setInputSummary(textAdded: string, didDelete: @selectionIsExpanded())
@delegate?.inputControllerWillPasteText(pasteData)
@responder?.insertString(string)
@requestRender()
@delegate?.inputControllerDidPaste(pasteData)

else if html = paste.getData("text/html")
console.log "pasting HTML"
pasteData.html = html
@delegate?.inputControllerWillPasteText(pasteData)
@responder?.insertHTML(html)
Expand All @@ -227,14 +238,6 @@ class Trix.InputController extends Trix.BasicObject
@requestRender()
@delegate?.inputControllerDidPaste(pasteData)

else if string = paste.getData("text/plain")
pasteData.string = string
@setInputSummary(textAdded: string, didDelete: @selectionIsExpanded())
@delegate?.inputControllerWillPasteText(pasteData)
@responder?.insertString(string)
@requestRender()
@delegate?.inputControllerDidPaste(pasteData)

else if "Files" in paste.types
if file = paste.items?[0]?.getAsFile?()
if not file.name and extension = extensionForFile(file)
Expand Down Expand Up @@ -412,6 +415,18 @@ pasteEventIsCrippledSafariHTMLPaste = (event) ->
if types = event.clipboardData?.types
"text/html" not in types and ("com.apple.webarchive" in types or "com.apple.flat-rtfd" in types)

dataTransferIsPlainText = (dataTransfer) ->
text = dataTransfer.getData("text/plain")
html = dataTransfer.getData("text/html")

if text and html
element = makeElement("div")
element.innerHTML = html
if element.textContent is text
not element.querySelector(":not(meta)")
else
text?.length

testTransferData = "application/x-trix-feature-detection": "test"

dataTransferIsWritable = (dataTransfer) ->
Expand Down
16 changes: 16 additions & 0 deletions test/src/system/pasting_test.coffee
Expand Up @@ -19,6 +19,22 @@ testGroup "Pasting", template: "editor_empty", ->
pasteContent "text/html", "<div>Hello world<br></div><div>This is a test</div>", ->
expectDocument "abHello world\nThis is a test\nc\n"

test "prefers plain text when html lacks formatting", (expectDocument) ->
pasteData =
"text/html": "<meta charset='utf-8'>a\nb"
"text/plain": "a\nb"

pasteContent pasteData, ->
expectDocument "a\nb\n"

test "prefers formatted html", (expectDocument) ->
pasteData =
"text/html": "<meta charset='utf-8'>a\n<strong>b</strong>"
"text/plain": "a\nb"

pasteContent pasteData, ->
expectDocument "a b\n"

test "paste URL", (expectDocument) ->
typeCharacters "a", ->
pasteContent "URL", "http://example.com", ->
Expand Down
12 changes: 9 additions & 3 deletions test/src/test_helpers/input_helpers.coffee
Expand Up @@ -16,11 +16,17 @@ helpers.extend
element.dispatchEvent(helpers.createEvent(type, properties))

pasteContent: (contentType, value, callback) ->
if typeof contentType is "object"
data = contentType
callback = value
else
data = "#{contentType}": value

testClipboardData =
getData: (type) ->
value if type is contentType
types: [contentType]
items: [value]
data[type]
types: (key for key of data)
items: (value for key, value of data)

helpers.triggerEvent(document.activeElement, "paste", {testClipboardData})
helpers.defer callback
Expand Down

0 comments on commit 41352e0

Please sign in to comment.