diff --git a/static/js/contentCollection.js b/static/js/contentCollection.js index 36a555b..78fe19e 100644 --- a/static/js/contentCollection.js +++ b/static/js/contentCollection.js @@ -1,11 +1,14 @@ 'use strict'; +const {_handleNewLines, _isValid} = require('ep_image_upload/static/js/toolbar'); + // When an image is detected give it a lineAttribute // of Image with the URL to the iamge exports.collectContentImage = (hookName, {node, state: {lineAttributes}, tname}) => { if (tname === 'div' || tname === 'p') delete lineAttributes.img; if (tname !== 'img') return; - lineAttributes.img = + + const imageData = // Client-side. This will also be used for server-side HTML imports once jsdom adds support // for HTMLImageElement.currentSrc. node.currentSrc || @@ -13,6 +16,66 @@ exports.collectContentImage = (hookName, {node, state: {lineAttributes}, tname}) node.src || // Server-side HTML imports using cheerio (Etherpad <= v1.8.14). (node.attribs && node.attribs.src); + + if (typeof window !== 'undefined' && clientVars.ep_image_upload.storageType !== 'base64') { + delete lineAttributes.img; + + const padeditor = require('ep_etherpad-lite/static/js/pad_editor').padeditor; + const formData = new FormData(); + + const match = imageData.match(/data:(?[^;]+);base64,(?.*)/); + if (!match || !match.groups.data || !match.groups.mime) return; + + // decode from internal base64 rep + const decodedData = Uint8Array.from(window.atob(match.groups.data), c => c.charCodeAt(0)); + + // check if size is within limits and mime type is supported + if (!_isValid({size: decodedData.length, type: match.groups.mime})) return; + + const blob = new Blob([decodedData], {type: match.groups.mime}); + + formData.append('file', blob, 'image.png'); + $('#imageUploadModalLoader').show(); + $.ajax({ + type: 'POST', + url: `${clientVars.padId}/pluginfw/ep_image_upload/upload`, + xhr: () => { + const myXhr = $.ajaxSettings.xhr(); + return myXhr; + }, + success: (data) => { + $('#imageUploadModalLoader').hide(); + padeditor.ace.callWithAce((ace) => { + const imageLineNr = _handleNewLines(ace); + ace.ace_addImage(imageLineNr, data); + ace.ace_doReturnKey(); + }, 'img', true); + }, + error: (error) => { + let errorResponse; + try { + errorResponse = JSON.parse(error.responseText.trim()); + if (errorResponse.type) { + errorResponse.message = window._(`ep_image_upload.error.${errorResponse.type}`); + } + } catch (err) { + errorResponse = {message: error.responseText}; + } + + $('#imageUploadModalLoader').hide(); + $('#imageUploadModalError .error').html(errorResponse.message); + $('#imageUploadModalError').show(); + }, + async: true, + data: formData, + cache: false, + contentType: false, + processData: false, + timeout: 20000, + }); + } else { + lineAttributes.img = imageData; + } }; exports.collectContentPre = (name, context) => { diff --git a/static/js/toolbar.js b/static/js/toolbar.js index 57293af..49fd0d1 100644 --- a/static/js/toolbar.js +++ b/static/js/toolbar.js @@ -1,6 +1,6 @@ 'use strict'; -const _handleNewLines = (ace) => { +exports._handleNewLines = (ace) => { const rep = ace.ace_getRep(); const lineNumber = rep.selStart[0]; const curLine = rep.lines.atIndex(lineNumber); @@ -13,7 +13,7 @@ const _handleNewLines = (ace) => { return lineNumber; }; -const _isValid = (file) => { +exports._isValid = (file) => { const mimedb = clientVars.ep_image_upload.mimeTypes; const mimeType = mimedb[file.type]; let validMime = null; @@ -67,7 +67,7 @@ exports.postToolbarInit = (hook, context) => { } const file = files[0]; - if (!_isValid(file)) { + if (!exports._isValid(file)) { return; } if (clientVars.ep_image_upload.storageType === 'base64') { @@ -77,7 +77,7 @@ exports.postToolbarInit = (hook, context) => { reader.onload = () => { const data = reader.result; context.ace.callWithAce((ace) => { - const imageLineNr = _handleNewLines(ace); + const imageLineNr = exports._handleNewLines(ace); ace.ace_addImage(imageLineNr, data); ace.ace_doReturnKey(); }, 'img', true); @@ -99,7 +99,7 @@ exports.postToolbarInit = (hook, context) => { success: (data) => { $('#imageUploadModalLoader').hide(); context.ace.callWithAce((ace) => { - const imageLineNr = _handleNewLines(ace); + const imageLineNr = exports._handleNewLines(ace); ace.ace_addImage(imageLineNr, data); ace.ace_doReturnKey(); }, 'img', true);