Skip to content
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

after pasting images, upload them if storageType isn't base64 #56

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion static/js/contentCollection.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,47 @@
'use strict';

const {_isValid, uploadFile} = 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 ||
// Server-side HTML imports using jsdom v16.6.0 (Etherpad v1.8.15).
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 === 'local') {
if (/^http/.test(imageData)) {
// an uploaded image is copied, place a copy in the desired line
lineAttributes.img = imageData;
return;
}

const padeditor = require('ep_etherpad-lite/static/js/pad_editor').padeditor;

const match = imageData.match(/data:([^;]+);base64,(.*)/);
if (!match || !match[1] || !match[2]) return;

// decode from internal base64 rep
const decodedData = Uint8Array.from(window.atob(match[2]), (c) => c.charCodeAt(0));

// check if size is within limits and mime type is supported
const extension = _isValid({size: decodedData.length, type: match[1]});
if (!extension) return;

const blob = new Blob([decodedData], {type: match[1]});

// image.* is a temporary name not used on the server
uploadFile(padeditor, blob, `image.${extension}`);
} else {
lineAttributes.img = imageData;
}
};

exports.collectContentPre = (name, context) => {
Expand Down
94 changes: 50 additions & 44 deletions static/js/toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const _handleNewLines = (ace) => {
const _isValid = (file) => {
const mimedb = clientVars.ep_image_upload.mimeTypes;
const mimeType = mimedb[file.type];
const extension = mimeType ? mimeType.extensions[0] : null;
let validMime = null;
if (clientVars.ep_image_upload && clientVars.ep_image_upload.fileTypes) {
validMime = false;
Expand Down Expand Up @@ -44,9 +45,56 @@ const _isValid = (file) => {
return false;
}

return true;
return extension;
};
exports._isValid = _isValid;

const uploadFile = (context, file, filename) => {
const formData = new FormData();

// add assoc key values, this will be posts values
formData.append('file', file, filename ? filename : file.name);
$('#imageUploadModalLoader').addClass('popup-show');
$.ajax({
type: 'POST',
url: `${clientVars.padId}/pluginfw/ep_image_upload/upload`,
xhr: () => {
const myXhr = $.ajaxSettings.xhr();

return myXhr;
},
success: (data) => {
$('#imageUploadModalLoader').removeClass('popup-show');
context.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').removeClass('popup-show');
$('#imageUploadModalError .error').html(errorResponse.message);
$('#imageUploadModalError').addClass('popup-show');
},
async: true,
data: formData,
cache: false,
contentType: false,
processData: false,
timeout: 60000,
});
};
exports.uploadFile = uploadFile;

exports.postToolbarInit = (hook, context) => {
const toolbar = context.toolbar;
Expand Down Expand Up @@ -83,49 +131,7 @@ exports.postToolbarInit = (hook, context) => {
}, 'img', true);
};
} else {
const formData = new FormData();

// add assoc key values, this will be posts values
formData.append('file', file, file.name);
$('#imageUploadModalLoader').addClass('popup-show');
$.ajax({
type: 'POST',
url: `${clientVars.padId}/pluginfw/ep_image_upload/upload`,
xhr: () => {
const myXhr = $.ajaxSettings.xhr();

return myXhr;
},
success: (data) => {
$('#imageUploadModalLoader').removeClass('popup-show');
context.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').removeClass('popup-show');
$('#imageUploadModalError .error').html(errorResponse.message);
$('#imageUploadModalError').addClass('popup-show');
},
async: true,
data: formData,
cache: false,
contentType: false,
processData: false,
timeout: 60000,
});
uploadFile(context, file);
}
});
$(document).find('body').find('#imageInput').trigger('click');
Expand Down
122 changes: 112 additions & 10 deletions static/tests/frontend/specs/insert.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.