Fix #936: too many return characters inserted when pasting formatted text from OpenOffice

This commit is contained in:
josdejong 2020-05-13 08:17:54 +02:00
parent 79beb26d66
commit ad021ec7af
4 changed files with 134 additions and 17 deletions

View File

@ -3,6 +3,12 @@
https://github.com/josdejong/jsoneditor
## not yet published, version 8.6.8
- Fix #936: too many return characters inserted when pasting formatted text
from OpenOffice.
## 2020-05-10, version 8.6.7
- Fix #858: the `dist/jsoneditor.js` bundle containing a link to a

View File

@ -5,7 +5,7 @@ const VanillaPicker = require('./vanilla-picker') // may be undefined in case of
const { treeModeMixins } = require('./treemode')
const { textModeMixins } = require('./textmode')
const { previewModeMixins } = require('./previewmode')
const { clear, extend, getInternetExplorerVersion, parse } = require('./util')
const { clear, extend, getInnerText, getInternetExplorerVersion, parse } = require('./util')
const { tryRequireAjv } = require('./tryRequireAjv')
const { showTransformModal } = require('./showTransformModal')
const { showSortModal } = require('./showSortModal')
@ -484,6 +484,7 @@ JSONEditor.VanillaPicker = VanillaPicker
// expose some utils (this is undocumented, unofficial)
JSONEditor.showTransformModal = showTransformModal
JSONEditor.showSortModal = showSortModal
JSONEditor.getInnerText = getInnerText
// default export for TypeScript ES6 projects
JSONEditor.default = JSONEditor

View File

@ -663,7 +663,6 @@ export function setSelectionOffset (params) {
}
}
}
/**
* Get the inner text of an HTML element (for example a div element)
* @param {Element} element
@ -674,21 +673,28 @@ export function getInnerText (element, buffer) {
const first = (buffer === undefined)
if (first) {
buffer = {
text: '',
_text: '',
flush: function () {
const text = this.text
this.text = ''
const text = this._text
this._text = ''
return text
},
set: function (text) {
this.text = text
this._text = text
}
}
}
// text node
if (element.nodeValue) {
return buffer.flush() + element.nodeValue
// remove return characters and the whitespace surrounding return characters
const trimmedValue = element.nodeValue.replace(/\s*\n\s*/g, '')
if (trimmedValue !== '') {
return buffer.flush() + trimmedValue
} else {
// ignore empty text
return ''
}
}
// divs or other HTML elements
@ -703,7 +709,9 @@ export function getInnerText (element, buffer) {
const prevChild = childNodes[i - 1]
const prevName = prevChild ? prevChild.nodeName : undefined
if (prevName && prevName !== 'DIV' && prevName !== 'P' && prevName !== 'BR') {
innerText += '\n'
if (innerText !== '') {
innerText += '\n'
}
buffer.flush()
}
innerText += getInnerText(child, buffer)
@ -717,15 +725,6 @@ export function getInnerText (element, buffer) {
}
return innerText
} else {
if (element.nodeName === 'P' && getInternetExplorerVersion() !== -1) {
// On Internet Explorer, a <p> with hasChildNodes()==false is
// rendered with a new line. Note that a <p> with
// hasChildNodes()==true is rendered without a new line
// Other browsers always ensure there is a <br> inside the <p>,
// and if not, the <p> does not render a new line
return buffer.flush()
}
}
// br or unknown

View File

@ -0,0 +1,111 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JSONEditor test getInnerHtml</title>
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>
<style>
html, body {
font-family: verdana;
background: #f5f5f5;
font-size: 11pt;
}
#editableDiv {
width: 600px;
height: 200px;
border: 1px solid red;
background: white;
font-family: monospace;
}
#editableDiv p {
margin: 0;
}
#innerText,
#getInnerText,
#innerTextStr,
#textContentStr {
width: 600px;
}
#innerText,
#getInnerText {
height: 200px;
border: 1px solid green;
}
#innerTextStr,
#textContentStr {
width: 600px;
border: 1px solid gray;
background: #f5f5f5;
font-family: monospace;
}
</style>
</head>
<body>
contenteditable div:
<div id="editableDiv" contenteditable="true">
<p>Hello world</p>
<p>test paste from OpenOffice </p>
a
<p>
<br>
</p>
<p>test</p>
</div>
<p>
innerText: <br/>
<textarea id="innerText"></textarea>
</p>
<p>
getInnerText: <br/>
<textarea id="getInnerText"></textarea>
</p>
<p>
<p>
inner text (stringified): <br/>
<input id="innerTextStr" readonly />
</p>
<p>
text content (stringified): <br/>
<input id="textContentStr" readonly />
</p>
<script>
const editableDiv = document.getElementById('editableDiv')
const innerText = document.getElementById('innerText')
const getInnerTextDiv = document.getElementById('getInnerText')
const innerTextStr = document.getElementById('innerTextStr')
const textContentStr = document.getElementById('textContentStr')
function updateInnerTexts () {
innerText.value = editableDiv.innerText
getInnerTextDiv.value = JSONEditor.getInnerText(editableDiv)
innerTextStr.value = JSON.stringify(editableDiv.innerText)
textContentStr.value = JSON.stringify(editableDiv.textContent)
}
editableDiv.oninput = updateInnerTexts
updateInnerTexts()
innerText.oninput = function () {
editableDiv.innerText = innerText.value
getInnerTextDiv.value = getInnerText(editableDiv)
}
getInnerTextDiv.oninput = function () {
editableDiv.innerText = getInnerTextDiv.value
innerText.value = editableDiv.innerText
}
</script>
</body>
</html>