From 4b1cf05c0e2b3b162969517e1612464745430b51 Mon Sep 17 00:00:00 2001 From: zadam Date: Mon, 25 Feb 2019 21:22:57 +0100 Subject: [PATCH] import images --- bin/deps/mac-x64/image/cjpeg | Bin bin/deps/win-x64/image/cjpeg.exe | Bin src/routes/api/import.js | 2 +- src/services/image.js | 13 +--- src/services/import/enex.js | 10 ++- src/services/import/opml.js | 5 +- src/services/import/single.js | 110 +++++++++++++++++++++++++++++-- src/services/import/tar.js | 7 +- src/views/dialogs/import.ejs | 2 +- 9 files changed, 124 insertions(+), 25 deletions(-) mode change 100644 => 100755 bin/deps/mac-x64/image/cjpeg mode change 100644 => 100755 bin/deps/win-x64/image/cjpeg.exe diff --git a/bin/deps/mac-x64/image/cjpeg b/bin/deps/mac-x64/image/cjpeg old mode 100644 new mode 100755 diff --git a/bin/deps/win-x64/image/cjpeg.exe b/bin/deps/win-x64/image/cjpeg.exe old mode 100644 new mode 100755 diff --git a/src/routes/api/import.js b/src/routes/api/import.js index 5d14d9fc0..c7e4e2c3d 100644 --- a/src/routes/api/import.js +++ b/src/routes/api/import.js @@ -17,7 +17,7 @@ async function importToBranch(req) { const options = { safeImport: req.body.safeImport !== 'false', - optimizedImages: req.body.optimizedImages !== 'false', + shrinkImages: req.body.shrinkImages !== 'false', textImportedAsText: req.body.textImportedAsText !== 'false', codeImportedAsCode: req.body.codeImportedAsCode !== 'false' }; diff --git a/src/services/image.js b/src/services/image.js index fd879a67b..1482e10a3 100644 --- a/src/services/image.js +++ b/src/services/image.js @@ -35,6 +35,7 @@ async function saveImage(buffer, originalName, parentNoteId, shrinkImageSwitch) return { fileName, + note, noteId: note.noteId, url: `api/images/${note.noteId}/${fileName}` }; @@ -47,7 +48,7 @@ async function shrinkImage(buffer) { try { finalImageBuffer = await optimize(resizedImage); } catch (e) { - log.error(e); + log.error(e.message + e.stack); finalImageBuffer = resizedImage; } return finalImageBuffer; @@ -75,15 +76,7 @@ async function resize(buffer) { // when converting PNG to JPG we lose alpha channel, this is replaced by white to match Trilium white background image.background(0xFFFFFFFF); - // getBuffer doesn't support promises so this workaround - return await new Promise((resolve, reject) => image.getBuffer(jimp.MIME_JPEG, (err, data) => { - if (err) { - reject(err); - } - else { - resolve(data); - } - })); + return image.getBufferAsync(jimp.MIME_JPEG); } async function optimize(buffer) { diff --git a/src/services/import/enex.js b/src/services/import/enex.js index 4625d62bd..69ab19343 100644 --- a/src/services/import/enex.js +++ b/src/services/import/enex.js @@ -6,6 +6,7 @@ const log = require("../log"); const utils = require("../utils"); const noteService = require("../notes"); const imageService = require("../image"); +const protectedSessionService = require('../protected_session'); // date format is e.g. 20181121T193703Z function parseDate(text) { @@ -31,7 +32,8 @@ async function importEnex(importContext, file, parentNote) { // root note is new note into all ENEX/notebook's notes will be imported const rootNote = (await noteService.createNote(parentNote.noteId, rootNoteTitle, "", { type: 'text', - mime: 'text/html' + mime: 'text/html', + isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), })).note; // we're persisting notes as we parse the document, but these are run asynchronously and may not be finished @@ -215,7 +217,8 @@ async function importEnex(importContext, file, parentNote) { attributes, dateCreated, type: 'text', - mime: 'text/html' + mime: 'text/html', + isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), })).note; importContext.increaseProgressCount(); @@ -237,7 +240,8 @@ async function importEnex(importContext, file, parentNote) { const resourceNote = (await noteService.createNote(noteEntity.noteId, resource.title, resource.content, { attributes: resource.attributes, type: 'file', - mime: resource.mime + mime: resource.mime, + isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), })).note; importContext.increaseProgressCount(); diff --git a/src/services/import/opml.js b/src/services/import/opml.js index af256e92e..45f66891a 100644 --- a/src/services/import/opml.js +++ b/src/services/import/opml.js @@ -2,6 +2,7 @@ const noteService = require('../../services/notes'); const parseString = require('xml2js').parseString; +const protectedSessionService = require('../protected_session'); /** * @param {ImportContext} importContext @@ -43,7 +44,9 @@ async function importOpml(importContext, fileBuffer, parentNote) { throw new Error("Unrecognized OPML version " + opmlVersion); } - const {note} = await noteService.createNote(parentNoteId, title, content); + const {note} = await noteService.createNote(parentNoteId, title, content, { + isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), + }); importContext.increaseProgressCount(); diff --git a/src/services/import/single.js b/src/services/import/single.js index c1864c8f1..703e55a4a 100644 --- a/src/services/import/single.js +++ b/src/services/import/single.js @@ -1,30 +1,124 @@ "use strict"; const noteService = require('../../services/notes'); +const imageService = require('../../services/image'); +const protectedSessionService = require('../protected_session'); const commonmark = require('commonmark'); const path = require('path'); +const CODE_MIME_TYPES = { + 'text/plain': true, + 'text/x-csrc': true, + 'text/x-c++src': true, + 'text/x-csharp': true, + 'text/x-clojure': true, + 'text/css': true, + 'text/x-dockerfile': true, + 'text/x-erlang': true, + 'text/x-feature': true, + 'text/x-go': true, + 'text/x-groovy': true, + 'text/x-haskell': true, + 'text/html': true, + 'message/http': true, + 'text/x-java': true, + 'application/javascript': 'application/javascript;env=frontend', + 'application/x-javascript': 'application/javascript;env=frontend', + 'application/json': true, + 'text/x-kotlin': true, + 'text/x-stex': true, + 'text/x-lua': true, + 'text/x-markdown': true, + 'text/x-objectivec': true, + 'text/x-pascal': true, + 'text/x-perl': true, + 'text/x-php': true, + 'text/x-python': true, + 'text/x-ruby': true, + 'text/x-rustsrc': true, + 'text/x-scala': true, + 'text/x-sh': true, + 'text/x-sql': true, + 'text/x-swift': true, + 'text/xml': true, + 'text/x-yaml': true +}; + async function importSingleFile(importContext, file, parentNote) { if (importContext.textImportedAsText) { if (file.mimetype === 'text/html') { - return importHtml(importContext, file, parentNote); + return await importHtml(importContext, file, parentNote); } else if (file.mimetype === 'text/markdown') { - return importMarkdown(importContext, file, parentNote); + return await importMarkdown(importContext, file, parentNote); } else if (file.mimetype === 'text/plain') { - return importPlainText(importContext, file, parentNote); + return await importPlainText(importContext, file, parentNote); } } + + if (importContext.codeImportedAsCode && file.mimetype in CODE_MIME_TYPES) { + return await importCodeNote(importContext, file, parentNote); + } + + if (["image/jpeg", "image/gif", "image/png"].includes(file.mimetype)) { + return await importImage(file, parentNote, importContext); + } + + return await importFile(importContext, file, parentNote); +} + +async function importImage(file, parentNote, importContext) { + const {note} = await imageService.saveImage(file.buffer, getFileNameWithoutExtension(file.originalname), parentNote.noteId, importContext.shrinkImages); + + importContext.increaseProgressCount(); + + return note; +} + +async function importFile(importContext, file, parentNote) { + const originalName = file.originalname; + const size = file.size; + + const {note} = await noteService.createNote(parentNote.noteId, originalName, file.buffer, { + target: 'into', + isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), + type: 'file', + mime: file.mimetype, + attributes: [ + { type: "label", name: "originalFileName", value: originalName }, + { type: "label", name: "fileSize", value: size } + ] + }); + + importContext.increaseProgressCount(); + + return note; +} + +async function importCodeNote(importContext, file, parentNote) { + const title = getFileNameWithoutExtension(file.originalname); + const content = file.buffer.toString("UTF-8"); + const mime = CODE_MIME_TYPES[file.mimetype] === true ? file.mimetype : CODE_MIME_TYPES[file.mimetype]; + + const {note} = await noteService.createNote(parentNote.noteId, title, content, { + type: 'code', + mime: mime, + isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable() + }); + + importContext.increaseProgressCount(); + + return note; } async function importPlainText(importContext, file, parentNote) { - const title = getFileNameWithoutExtension(file.originalname); const plainTextContent = file.buffer.toString("UTF-8"); const htmlContent = convertTextToHtml(plainTextContent); const {note} = await noteService.createNote(parentNote.noteId, title, htmlContent, { type: 'text', - mime: 'text/html' + mime: 'text/html', + isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), }); importContext.increaseProgressCount(); @@ -63,7 +157,8 @@ async function importMarkdown(importContext, file, parentNote) { const {note} = await noteService.createNote(parentNote.noteId, title, htmlContent, { type: 'text', - mime: 'text/html' + mime: 'text/html', + isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), }); importContext.increaseProgressCount(); @@ -77,7 +172,8 @@ async function importHtml(importContext, file, parentNote) { const {note} = await noteService.createNote(parentNote.noteId, title, content, { type: 'text', - mime: 'text/html' + mime: 'text/html', + isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), }); importContext.increaseProgressCount(); diff --git a/src/services/import/tar.js b/src/services/import/tar.js index 66821081c..b092c3cc0 100644 --- a/src/services/import/tar.js +++ b/src/services/import/tar.js @@ -14,6 +14,7 @@ const path = require('path'); const commonmark = require('commonmark'); const mimeTypes = require('mime-types'); const ImportContext = require('../import_context'); +const protectedSessionService = require('../protected_session'); /** * @param {ImportContext} importContext @@ -193,7 +194,8 @@ async function importTar(importContext, fileBuffer, importRootNote) { type: noteMeta ? noteMeta.type : 'text', mime: noteMeta ? noteMeta.mime : 'text/html', prefix: noteMeta ? noteMeta.prefix : '', - isExpanded: noteMeta ? noteMeta.isExpanded : false + isExpanded: noteMeta ? noteMeta.isExpanded : false, + isProtected: importRootNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), })); await saveAttributesAndLinks(note, noteMeta); @@ -271,7 +273,8 @@ async function importTar(importContext, fileBuffer, importRootNote) { mime, prefix: noteMeta ? noteMeta.prefix : '', isExpanded: noteMeta ? noteMeta.isExpanded : false, - notePosition: noteMeta ? noteMeta.notePosition : false + notePosition: noteMeta ? noteMeta.notePosition : false, + isProtected: importRootNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), })); await saveAttributesAndLinks(note, noteMeta); diff --git a/src/views/dialogs/import.ejs b/src/views/dialogs/import.ejs index edc6f46f3..ba0d7b026 100644 --- a/src/views/dialogs/import.ejs +++ b/src/views/dialogs/import.ejs @@ -26,7 +26,7 @@