import and export fixes

This commit is contained in:
zadam
2023-07-13 23:54:47 +02:00
parent a748710b01
commit ca41806bc2
6 changed files with 621 additions and 55 deletions

View File

@@ -65,6 +65,23 @@ function exportSingleNote(taskContext, branch, format, res) {
}
function inlineAttachments(content) {
content = content.replace(/src="[^"]*api\/images\/([a-zA-Z0-9_]+)\/?[^"]+"/g, (match, noteId) => {
const note = becca.getNote(noteId);
if (!note || !note.mime.startsWith('image/')) {
return match;
}
const imageContent = note.getContent();
if (!Buffer.isBuffer(imageContent)) {
return match;
}
const base64Content = imageContent.toString('base64');
const srcValue = `data:${note.mime};base64,${base64Content}`;
return `src="${srcValue}"`;
});
content = content.replace(/src="[^"]*api\/attachments\/([a-zA-Z0-9_]+)\/image\/?[^"]+"/g, (match, attachmentId) => {
const attachment = becca.getAttachment(attachmentId);
if (!attachment || !attachment.mime.startsWith('image/')) {

View File

@@ -267,9 +267,7 @@ async function importZip(taskContext, fileBuffer, importRootNote) {
return noteId;
}
/**
* @returns {{attachmentId: string}|{noteId: string}}
*/
/** @returns {{attachmentId: string}|{noteId: string}} */
function getEntityIdFromRelativeUrl(url, filePath) {
while (url.startsWith("./")) {
url = url.substr(2);
@@ -293,7 +291,8 @@ async function importZip(taskContext, fileBuffer, importRootNote) {
if (attachmentMeta) {
return {
attachmentId: getNewAttachmentId(attachmentMeta.attachmentId)
attachmentId: getNewAttachmentId(attachmentMeta.attachmentId),
noteId: getNewNoteId(noteMeta.noteId)
};
} else { // don't check for noteMeta since it's not mandatory for notes
return {
@@ -343,10 +342,10 @@ async function importZip(taskContext, fileBuffer, importRootNote) {
const target = getEntityIdFromRelativeUrl(url, filePath);
if (target.noteId) {
return `src="api/images/${target.noteId}/${path.basename(url)}"`;
} else if (target.attachmentId) {
if (target.attachmentId) {
return `src="api/attachments/${target.attachmentId}/image/${path.basename(url)}"`;
} else if (target.noteId) {
return `src="api/images/${target.noteId}/${path.basename(url)}"`;
} else {
return match;
}
@@ -367,13 +366,13 @@ async function importZip(taskContext, fileBuffer, importRootNote) {
const target = getEntityIdFromRelativeUrl(url, filePath);
if (!target.noteId) {
if (target.attachmentId) {
return `href="#root/${target.noteId}?viewMode=attachments&attachmentId=${target.attachmentId}"`;
} else if (target.noteId) {
return `href="#root/${target.noteId}"`;
} else {
return match;
}
// FIXME for linking attachments
return `href="#root/${target.noteId}"`;
});
if (noteMeta) {

View File

@@ -22,6 +22,7 @@ const ValidationError = require("../errors/validation_error");
const noteTypesService = require("./note_types");
const fs = require("fs");
const ws = require("./ws");
const html2plaintext = require('html2plaintext')
/** @param {BNote} parentNote */
function getNewNotePosition(parentNote) {
@@ -504,10 +505,6 @@ function replaceUrl(content, url, attachment) {
}
function downloadImages(noteId, content) {
if (!optionService.getOptionBool("downloadImagesAutomatically")) {
return content;
}
const imageRe = /<img[^>]*?\ssrc=['"]([^'">]+)['"]/ig;
let imageMatch;
@@ -520,16 +517,20 @@ function downloadImages(noteId, content) {
const imageBuffer = Buffer.from(imageBase64, 'base64');
const imageService = require('../services/image');
const {note} = imageService.saveImage(noteId, imageBuffer, "inline image", true, true);
const attachment = imageService.saveImageToAttachment(noteId, imageBuffer, "inline image", true, true);
const sanitizedTitle = note.title.replace(/[^a-z0-9-.]/gi, "");
const sanitizedTitle = attachment.title.replace(/[^a-z0-9-.]/gi, "");
content = `${content.substr(0, imageMatch.index)}<img src="api/images/${note.noteId}/${sanitizedTitle}"${content.substr(imageMatch.index + imageMatch[0].length)}`;
content = `${content.substr(0, imageMatch.index)}<img src="api/attachments/${attachment.attachmentId}/image/${sanitizedTitle}"${content.substr(imageMatch.index + imageMatch[0].length)}`;
}
else if (!url.includes('api/images/') && !/api\/attachments\/.+\/image\/?.*/.test(url)
// this is an exception for the web clipper's "imageId"
&& (url.length !== 20 || url.toLowerCase().startsWith('http'))) {
if (!optionService.getOptionBool("downloadImagesAutomatically")) {
continue;
}
if (url in imageUrlToAttachmentIdMapping) {
const attachment = becca.getAttachment(imageUrlToAttachmentIdMapping[url]);
@@ -599,6 +600,39 @@ function downloadImages(noteId, content) {
return content;
}
/**
* @param {BNote} note
* @param {string} content
*/
function saveAttachments(note, content) {
const inlineAttachmentRe = /<a[^>]*?\shref=['"]data:([^;'">]+);base64,([^'">]+)['"][^>]*>(.*?)<\/a>/igm;
let attachmentMatch;
while (attachmentMatch = inlineAttachmentRe.exec(content)) {
const mime = attachmentMatch[1].toLowerCase();
const base64data = attachmentMatch[2];
const buffer = Buffer.from(base64data, 'base64');
const title = html2plaintext(attachmentMatch[3]);
const attachment = note.saveAttachment({
role: 'file',
mime: mime,
title: title,
content: buffer
});
content = `${content.substr(0, attachmentMatch.index)}<a class="reference-link" href="#root/${note.noteId}?viewMode=attachments&attachmentId=${attachment.attachmentId}">${title}</a>${content.substr(attachmentMatch.index + attachmentMatch[0].length)}`;
}
return content;
}
/**
* @param {BNote} note
* @param {string} content
*/
function saveLinks(note, content) {
if ((note.type !== 'text' && note.type !== 'relationMap')
|| (note.isProtected && !protectedSessionService.isProtectedSessionAvailable())) {
@@ -613,6 +647,7 @@ function saveLinks(note, content) {
if (note.type === 'text') {
content = downloadImages(note.noteId, content);
content = saveAttachments(note, content);
content = findImageLinks(content, foundLinks);
content = findInternalLinks(content, foundLinks);