From fe6f19e611b47a8cb1d17b48765e0dc1440b0d97 Mon Sep 17 00:00:00 2001 From: zadam Date: Sat, 31 Aug 2019 22:39:25 +0200 Subject: [PATCH] imported notes from tar now have correct links even without meta file --- src/services/export/tar.js | 8 ++-- src/services/import/tar.js | 97 ++++++++++++++++++++++++++++++-------- src/services/notes.js | 5 -- 3 files changed, 81 insertions(+), 29 deletions(-) diff --git a/src/services/export/tar.js b/src/services/export/tar.js index b01963061..3bdb13946 100644 --- a/src/services/export/tar.js +++ b/src/services/export/tar.js @@ -187,16 +187,16 @@ async function exportToTar(exportContext, branch, format, res) { } function findLinks(content, noteMeta) { - content = content.replace(/src="[^"]*api\/images\/([a-zA-Z0-9]+)\/[^"]*"/g, (_, targetNoteId) => { + content = content.replace(/src="[^"]*api\/images\/([a-zA-Z0-9]+)\/[^"]*"/g, (match, targetNoteId) => { const url = getTargetUrl(targetNoteId, noteMeta); - return `src="${url}"`; + return url ? `src="${encodeURIComponent(url)}"` : match; }); - content = content.replace(/href="[^"]*#root[a-zA-Z0-9\/]*\/([a-zA-Z0-9]+)\/?"/g, (_, targetNoteId) => { + content = content.replace(/href="[^"]*#root[a-zA-Z0-9\/]*\/([a-zA-Z0-9]+)\/?"/g, (match, targetNoteId) => { const url = getTargetUrl(targetNoteId, noteMeta); - return `href="${url}"`; + return url ? `href="${encodeURIComponent(url)}"` : match; }); return content; diff --git a/src/services/import/tar.js b/src/services/import/tar.js index 6ca3cd2f7..bc4477c42 100644 --- a/src/services/import/tar.js +++ b/src/services/import/tar.js @@ -113,19 +113,27 @@ async function importTar(importContext, fileBuffer, importRootNote) { } function getNoteId(noteMeta, filePath) { + let noteId; + if (noteMeta) { - return getNewNoteId(noteMeta.noteId); + noteId = getNewNoteId(noteMeta.noteId); + + createdPaths[filePath] = noteId; } else { const filePathNoExt = getTextFileWithoutExtension(filePath); if (filePathNoExt in createdPaths) { - return createdPaths[filePathNoExt]; + noteId = createdPaths[filePathNoExt]; } else { - return utils.newEntityId(); + noteId = utils.newEntityId(); } + + createdPaths[filePathNoExt] = noteId; } + + return noteId; } function detectFileTypeAndMime(filePath) { @@ -197,8 +205,6 @@ async function importTar(importContext, fileBuffer, importRootNote) { firstNote = note; } - createdPaths[filePath] = noteId; - return noteId; } @@ -213,6 +219,31 @@ async function importTar(importContext, fileBuffer, importRootNote) { } } + function getNoteIdFromRelativeUrl(url, filePath) { + while (url.startsWith("./")) { + url = url.substr(2); + } + + let absUrl = path.dirname(filePath); + + while (url.startsWith("../")) { + absUrl = path.dirname(absUrl); + + url = url.substr(3); + } + + if (absUrl === '.') { + absUrl = ''; + } + + absUrl += (absUrl.length > 0 ? '/' : '') + url; + + console.log("absUrl", absUrl); + + const targetNoteId = getNoteId(null, absUrl); + return targetNoteId; + } + async function saveNote(filePath, content) { const {parentNoteMeta, noteMeta} = getMeta(filePath); @@ -235,19 +266,6 @@ async function importTar(importContext, fileBuffer, importRootNote) { if (type !== 'file' && type !== 'image') { content = content.toString("UTF-8"); - - if (noteMeta) { - const internalLinks = (noteMeta.attributes || []) - .filter(attr => attr.type === 'relation' && - ['internal-link', 'relation-map-link', 'image-link'].includes(attr.name)); - - // this will replace all internal links ( and ) inside the body - // links pointing outside the export will be broken and changed (ctx.getNewNoteId() will still assign new noteId) - for (const link of internalLinks) { - // no need to escape the regexp find string since it's a noteId which doesn't contain any special characters - content = content.replace(new RegExp(link.value, "g"), getNewNoteId(link.value)); - } - } } if ((noteMeta && noteMeta.format === 'markdown') || (!noteMeta && ['text/markdown', 'text/x-markdown'].includes(mime))) { @@ -255,6 +273,47 @@ async function importTar(importContext, fileBuffer, importRootNote) { content = mdWriter.render(parsed); } + if (type === 'text') { + function isUrlAbsolute(url) { + return /^(?:[a-z]+:)?\/\//i.test(url); + } + + content = content.replace(/src="([^"]*)"/g, (match, url) => { + url = decodeURIComponent(url); + + if (isUrlAbsolute(url) || url.startsWith("/")) { + return match; + } + + const targetNoteId = getNoteIdFromRelativeUrl(url, filePath); + + return `src="api/images/${targetNoteId}/${path.basename(url)}"`; + }); + + content = content.replace(/href="([^"]*)"/g, (match, url) => { + url = decodeURIComponent(url); + + if (isUrlAbsolute(url)) { + return match; + } + + const targetNoteId = getNoteIdFromRelativeUrl(url, filePath); + + return `href="#root/${targetNoteId}"`; + }); + } + + if (type === 'relation-map' && noteMeta) { + const relationMapLinks = (noteMeta.attributes || []) + .filter(attr => attr.type === 'relation' && attr.name === 'relation-map-link'); + + // this will replace relation map links + for (const link of relationMapLinks) { + // no need to escape the regexp find string since it's a noteId which doesn't contain any special characters + content = content.replace(new RegExp(link.value, "g"), getNewNoteId(link.value)); + } + } + let note = await repository.getNote(noteId); if (note) { @@ -298,8 +357,6 @@ async function importTar(importContext, fileBuffer, importRootNote) { if (type === 'text') { filePath = getTextFileWithoutExtension(filePath); } - - createdPaths[filePath] = noteId; } } diff --git a/src/services/notes.js b/src/services/notes.js index 86cfcb67b..3ab688f4b 100644 --- a/src/services/notes.js +++ b/src/services/notes.js @@ -415,11 +415,6 @@ async function deleteNote(branch) { await relation.save(); } - for (const link of await note.getTargetLinks()) { - link.isDeleted = true; - await link.save(); - } - return true; } else {