-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Paste replacement #976
Paste replacement #976
Changes from 18 commits
d84763d
eae8e25
c434d75
242c8cf
08b1490
693e3f1
091aa2f
5da4676
22f7e81
5d870ea
54d2498
17cc5dd
d2d8a13
2e852c0
ab1ff15
aa75e08
bd65d9c
b9b878a
31f7874
2055b4d
6388b13
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>Get Clipboard HTML and RTF</title> | ||
<style> | ||
|
||
textarea { | ||
border: 1px solid #808080; | ||
float: left; | ||
height: 200px; | ||
width: 100%; | ||
overflow: auto; | ||
margin-bottom: 20px;; | ||
} | ||
|
||
</style> | ||
<script src="../../ckeditor.js"></script> | ||
</head> | ||
<body> | ||
<p>Paste Inside the Editor:</p> | ||
<div><textarea id="input"></textarea></div> | ||
<div> | ||
<div style="float: left; width: 49%"> | ||
<p>Raw HTML Data Received:</p> | ||
<textarea data-name="input.html" id="rawHtml" readonly="readonly"></textarea> | ||
<button id="htmlData">Save HTML Data</button> | ||
</div> | ||
<div style="float: right; width: 49%"> | ||
<p>Raw RTF Data Received:</p> | ||
<textarea data-name="input.rtf" id="rawRtf" readonly="readonly"></textarea> | ||
<button id="rtfData">Save RTF Data</button> | ||
</div> | ||
</div> | ||
<div style="width: 100%; float: left;"> | ||
<p>After Paste Processing:</p> | ||
<textarea id="output" readonly="readonly"></textarea> | ||
</div> | ||
|
||
<script> | ||
var editor = CKEDITOR.replace( 'input', { | ||
height: 100, | ||
allowedContent: true, | ||
plugins: 'pastefromword,pastefromwordimage,wysiwygarea' | ||
} ); | ||
|
||
editor.on( 'paste', function( evt ) { | ||
var val = evt.data.dataValue; | ||
|
||
if ( evt.data.dataTransfer && evt.data.dataTransfer.getData( 'text/html', true ) ) { | ||
val = evt.data.dataTransfer.getData( 'text/html', true ); | ||
} | ||
document.getElementById( 'rawHtml' ).value = val; | ||
|
||
if ( evt.data.dataTransfer && evt.data.dataTransfer.getData( 'text/rtf', true ) ) { | ||
val = evt.data.dataTransfer.getData( 'text/rtf', true ); | ||
} | ||
document.getElementById( 'rawRtf' ).value = val; | ||
|
||
}, null, null, -1 ); | ||
|
||
editor.on( 'paste', function( evt ) { | ||
setTimeout( function() { | ||
document.getElementById( 'output' ).value = editor.getData(); | ||
}, 0 ); | ||
}, null, null, 999 ); | ||
|
||
var rtfButton = document.getElementById( 'rtfData' ), | ||
htmlButton = document.getElementById( 'htmlData' ); | ||
|
||
rtfButton.onclick = save( document.getElementById( 'rawRtf' ) ); | ||
htmlButton.onclick = save( document.getElementById( 'rawHtml' ) ); | ||
|
||
function save( input ) { | ||
return function() { | ||
var textBlob = new Blob( [ input.value ], { type: 'text/plain' } ); | ||
var saveLink = document.createElement( 'a' ); | ||
|
||
saveLink.download = input.dataset.name; | ||
saveLink.innerHTML = 'Save file'; | ||
if ( CKEDITOR.env.webkit ) { | ||
saveLink.href = window.URL.createObjectURL( textBlob ); | ||
} else { | ||
saveLink.href = window.URL.createObjectURL( textBlob ); | ||
saveLink.onclick = function( evt ) { | ||
document.body.removeChild( evt.target ) | ||
}; | ||
saveLink.style.display = 'none'; | ||
document.body.appendChild( saveLink ); | ||
} | ||
saveLink.click(); | ||
} | ||
} | ||
|
||
|
||
</script> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,9 +8,55 @@ | |
|
||
CKEDITOR.plugins.add( 'pastefromwordimage', { | ||
requires: 'pastefromword', | ||
init: function() {} | ||
init: function( editor ) { | ||
if ( !CKEDITOR.plugins.clipboard.isCustomDataTypesSupported ) { | ||
return; | ||
} | ||
|
||
// Register a proper filter, so that images are not stripped out. | ||
editor.filter.allow( 'img[src]' ); | ||
|
||
editor.on( 'afterPasteFromWord', pasteListener ); | ||
} | ||
} ); | ||
|
||
|
||
function pasteListener( evt ) { | ||
var pfwi = CKEDITOR.plugins.pastefromwordimage, | ||
imgTags, | ||
hexImages, | ||
newSrcValues = [], | ||
i; | ||
|
||
imgTags = pfwi.extractImgTagsFromHtml( evt.data.dataValue ); | ||
if ( imgTags.length === 0 ) { | ||
return; | ||
} | ||
|
||
hexImages = pfwi.extractImagesFromRtf( evt.data.dataTransfer[ 'text/rtf' ] ); | ||
if ( hexImages.length === 0 ) { | ||
return; | ||
} | ||
|
||
CKEDITOR.tools.array.forEach( hexImages, function( img ) { | ||
newSrcValues.push( createSrcWithBase64( img ) ); | ||
}, this ); | ||
|
||
// Assumption there is equal amount of Images in RTF and HTML source, so we can match them accordingly to existing order. | ||
if ( imgTags.length === newSrcValues.length ) { | ||
for ( i = 0; i < imgTags.length; i++ ) { | ||
// Replace only `file` urls of images ( shapes get newSrcValue with null ). | ||
if ( ( imgTags[ i ].indexOf( 'file://' ) === 0 ) && newSrcValues[ i ] ) { | ||
evt.data.dataValue = evt.data.dataValue.replace( imgTags[ i ], newSrcValues[ i ] ); | ||
} | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know the above two looks nice and super clear, but |
||
} | ||
|
||
function createSrcWithBase64( img ) { | ||
return img.type ? 'data:' + img.type + ';base64,' + CKEDITOR.tools.convertBytesToBase64( CKEDITOR.tools.convertHexStringToBytes( img.hex ) ) : null; | ||
} | ||
|
||
/** | ||
* Help methods used by paste from word image plugin. | ||
* | ||
|
@@ -36,7 +82,6 @@ | |
rePictureOrShape = new RegExp( '(?:(' + rePictureHeader.source + ')|(' + reShapeHeader.source + '))([\\da-fA-F\\s]+)\\}', 'g' ), | ||
wholeImages, | ||
imageType; | ||
|
||
wholeImages = rtfContent.match( rePictureOrShape ); | ||
if ( !wholeImages ) { | ||
return ret; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ | |
* @param {Boolean} [options.compareRawData=false] If `true` test case will assert against raw paste's `data.dataValue` rather than | ||
* what will appear in the editor after all transformations and filtering. | ||
* @param {Boolean} [options.ignoreAll=false] Whenever to ignore all tests. | ||
* @param {Boolean} [options.includeRTF=false] Whether RTF clipboard should be loaded in test case | ||
* @returns {Object} Test data object which should be passed to `bender.test` function. | ||
*/ | ||
function createTestSuite( options ) { | ||
|
@@ -24,7 +25,8 @@ function createTestSuite( options ) { | |
testData: { _should: { ignore: {} } }, | ||
ignoreAll: false, | ||
compareRawData: false, | ||
customFilters: null | ||
customFilters: null, | ||
includeRTF: false | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing docs for |
||
} ); | ||
|
||
var testData = options.testData, | ||
|
@@ -52,7 +54,8 @@ function createTestSuite( options ) { | |
wordVersion: wordVersion, | ||
browser: options.browsers[ j ], | ||
compareRawData: options.compareRawData, | ||
customFilters: options.customFilters | ||
customFilters: options.customFilters, | ||
includeRTF: options.includeRTF | ||
} ); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<p style="margin-left:0in; margin-right:0in"><span style="font-size:11pt"><span style="line-height:107%"><span>Kitty from internet: <img alt="http://placekitten.com/200/305" style="width:200px; height:305px" src="http://placekitten.com/200/305" /></span></span></span></p><p style="margin-left:0in; margin-right:0in"><span style="font-size:11pt"><span style="line-height:107%"><span>My drawing: <img style="width:32px; height:32px" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAOwgAADsIBFShKgAAAAOdJREFUSEvtljEWgjAQRA0HsLG19P4nsrS18QK6efFBMpMsS1hS+KQDNn+YAbIbntfb5XE/lcf7BRdMp+GMZQIPvLSPPnNAphDYia5qLAI6ne0b678CrWrm2iNNazUBC33Wqz6iEKIA39uEVjSigBc9yTBtMn3h5iK2jgJ94SgPUAi40AHiHBFbGSjgkk9ykKMGOjB/itsK/w5W81oi8uo2sCP92DtwSQkgwyPaaaLSvo5umfWIOnw055JWL+V9sfVP6SPPqMFL97G6H0BB3g9w+O1IX6HLrUkm7Lwijko0hRsd8FqBfwBKE0DK1O0llgAAAABJRU5ErkJggg==" /> hehehehe :D <img style="width:32px; height:32px" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAOwgAADsIBFShKgAAAAU1JREFUSEu9ljEOwjAMRZvuXZhhAiQOADvszNwBcQkugbgDMzvscAAkxNQZBjhAsIjaJnaT2m1p1aWN/Z/tOK3Vsz/qpfcIXR+F33CeE42sXoOx0hq/jeqp59ouxgU0lC5jWICg+vC0ROk/FsdQ2bI8MoBHnepSUS/pxwgBOOo5rxyT6B/ADX++unJaxmdzPkyLpUTHTXsmHMtHxU2C5fhigKjuYkAr6khE6XcRh1kb7Ld2aOnaeaRRU3u7ozrcA1F9Lpsb3L49sKUEGRjRsDRFcgE03tluIu4in0OgGpUMVgYQbH5XKiIDFoCKMusDjgWg4vueQUwq4Tw6PQfVJ1ladDj53gyYVeLXx9kDaaRMe9xFrSRhs+OITEvM0Fhmpf9k4yn69oF98KcP638fW/wMX0LCwcvI/GF0dLuolQ13RWKYsJ1+gOXaGOIL4l+GAZPNqBWlOAAAAABJRU5ErkJggg==" /></span></span></span></p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you could also add a container which will show all images pasted to the CKEditor (in the form already transformed by CKEditor), something like
Extracted Images
? If it's relatively easy to do (like 0,5h) you could take a look at it. From the other hand you can see pasted images inside editor instance, so not sure if it is needed. WDYT?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On this stage of implementation it might be problematic. I could process RTF clipboard, but it might contains also Word Shapes, which are ignored for processing while pasting. That's why preparing similar solution here might be repeating functionality of the plugin, which seems to be not a good thing.
It should be easier, when further changes related to file transfer will be implemented:
https://github.com/ckeditor/ckeditor-dev/blob/128516a52485505176189743962eaf97d52aa067/plugins/pastefromwordimage/plugin.js#L60-L63
There is nice event when will be exposed processed URL and image which is going to be embed. With that implementation it should be like 0,5h of work :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@msamsel Ok, so let's leave it as it is for now.