|
|
|
@ -1,7 +1,6 @@
|
|
|
|
const sax = require("sax");
|
|
|
|
const sax = require("sax");
|
|
|
|
const fileType = require('file-type');
|
|
|
|
const fileType = require('file-type');
|
|
|
|
const stream = require('stream');
|
|
|
|
const stream = require('stream');
|
|
|
|
const xml2js = require('xml2js');
|
|
|
|
|
|
|
|
const log = require("../log");
|
|
|
|
const log = require("../log");
|
|
|
|
const utils = require("../utils");
|
|
|
|
const utils = require("../utils");
|
|
|
|
const noteService = require("../notes");
|
|
|
|
const noteService = require("../notes");
|
|
|
|
@ -22,8 +21,6 @@ let resource;
|
|
|
|
|
|
|
|
|
|
|
|
async function importEnex(taskContext, file, parentNote) {
|
|
|
|
async function importEnex(taskContext, file, parentNote) {
|
|
|
|
const saxStream = sax.createStream(true);
|
|
|
|
const saxStream = sax.createStream(true);
|
|
|
|
const xmlBuilder = new xml2js.Builder({ headless: true });
|
|
|
|
|
|
|
|
const parser = new xml2js.Parser({ explicitArray: true });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const rootNoteTitle = file.originalname.toLowerCase().endsWith(".enex")
|
|
|
|
const rootNoteTitle = file.originalname.toLowerCase().endsWith(".enex")
|
|
|
|
? file.originalname.substr(0, file.originalname.length - 5)
|
|
|
|
? file.originalname.substr(0, file.originalname.length - 5)
|
|
|
|
@ -43,28 +40,20 @@ async function importEnex(taskContext, file, parentNote) {
|
|
|
|
// when we finish parsing. We use this to be sure that all saving has been finished before returning successfully.
|
|
|
|
// when we finish parsing. We use this to be sure that all saving has been finished before returning successfully.
|
|
|
|
const saveNotePromises = [];
|
|
|
|
const saveNotePromises = [];
|
|
|
|
|
|
|
|
|
|
|
|
async function parseXml(text) {
|
|
|
|
function extractContent(content) {
|
|
|
|
return new Promise(function(resolve, reject)
|
|
|
|
const openingNoteIndex = content.indexOf('<en-note>');
|
|
|
|
{
|
|
|
|
|
|
|
|
parser.parseString(text, function (err, result) {
|
|
|
|
if (openingNoteIndex !== -1) {
|
|
|
|
if (err) {
|
|
|
|
content = content.substr(openingNoteIndex + 9);
|
|
|
|
reject(err);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
|
|
|
resolve(result);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function extractContent(enNote) {
|
|
|
|
const closingNoteIndex = content.lastIndexOf('</en-note>');
|
|
|
|
// [] thing is workaround for https://github.com/Leonidas-from-XIV/node-xml2js/issues/484
|
|
|
|
|
|
|
|
let content = xmlBuilder.buildObject([enNote]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const endOfFirstTagIndex = content.indexOf('>');
|
|
|
|
if (closingNoteIndex !== -1) {
|
|
|
|
|
|
|
|
content = content.substr(0, closingNoteIndex);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// strip the <0> and </0> tags
|
|
|
|
content = content.trim();
|
|
|
|
content = content.substr(endOfFirstTagIndex + 1, content.length - endOfFirstTagIndex - 5).trim();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// workaround for https://github.com/ckeditor/ckeditor5-list/issues/116
|
|
|
|
// workaround for https://github.com/ckeditor/ckeditor5-list/issues/116
|
|
|
|
content = content.replace(/<li>\s+<div>/g, "<li>");
|
|
|
|
content = content.replace(/<li>\s+<div>/g, "<li>");
|
|
|
|
@ -205,10 +194,7 @@ async function importEnex(taskContext, file, parentNote) {
|
|
|
|
// make a copy because stream continues with the next async call and note gets overwritten
|
|
|
|
// make a copy because stream continues with the next async call and note gets overwritten
|
|
|
|
let {title, content, attributes, resources, utcDateCreated} = note;
|
|
|
|
let {title, content, attributes, resources, utcDateCreated} = note;
|
|
|
|
|
|
|
|
|
|
|
|
const xmlObject = await parseXml(content);
|
|
|
|
content = extractContent(content);
|
|
|
|
|
|
|
|
|
|
|
|
// following is workaround for this issue: https://github.com/Leonidas-from-XIV/node-xml2js/issues/484
|
|
|
|
|
|
|
|
content = extractContent(xmlObject['en-note']);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const noteEntity = (await noteService.createNewNote({
|
|
|
|
const noteEntity = (await noteService.createNewNote({
|
|
|
|
parentNoteId: rootNote.noteId,
|
|
|
|
parentNoteId: rootNote.noteId,
|
|
|
|
@ -220,8 +206,8 @@ async function importEnex(taskContext, file, parentNote) {
|
|
|
|
isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(),
|
|
|
|
isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(),
|
|
|
|
})).note;
|
|
|
|
})).note;
|
|
|
|
|
|
|
|
|
|
|
|
for (const attr of resource.attributes) {
|
|
|
|
for (const attr of attributes) {
|
|
|
|
await note.addAttribute(attr.type, attr.name, attr.value);
|
|
|
|
await noteEntity.addAttribute(attr.type, attr.name, attr.value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
taskContext.increaseProgressCount();
|
|
|
|
taskContext.increaseProgressCount();
|
|
|
|
@ -250,7 +236,7 @@ async function importEnex(taskContext, file, parentNote) {
|
|
|
|
})).note;
|
|
|
|
})).note;
|
|
|
|
|
|
|
|
|
|
|
|
for (const attr of resource.attributes) {
|
|
|
|
for (const attr of resource.attributes) {
|
|
|
|
await note.addAttribute(attr.type, attr.name, attr.value);
|
|
|
|
await noteEntity.addAttribute(attr.type, attr.name, attr.value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
taskContext.increaseProgressCount();
|
|
|
|
taskContext.increaseProgressCount();
|
|
|
|
|