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

Fix: Evernote .enex image import #7785

Merged
merged 11 commits into from Oct 15, 2023
73 changes: 58 additions & 15 deletions plugins/tiddlywiki/evernote/modules/enex-deserializer.js
Expand Up @@ -23,8 +23,7 @@ exports["application/enex+xml"] = function(text,fields) {
// Collect output tiddlers in an array
var results = [];
// Parse the XML document
var parser = new DOMParser(),
doc = parser.parseFromString(text,"application/xml");
var doc = new DOMParser().parseFromString(text,"application/xml");
// Output a report tiddler with information about the import
var enex = doc.querySelector("en-export");
results.push({
Expand All @@ -34,12 +33,48 @@ exports["application/enex+xml"] = function(text,fields) {
// Get all the "note" nodes
var noteNodes = doc.querySelectorAll("note");
$tw.utils.each(noteNodes,function(noteNode) {
var noteTitle = getTextContent(noteNode,"title");
// get real note content node
var contentNode = noteNode.querySelector("content")
var contentText = (contentNode.textContent || "").replace(/ /g, ' ').trim();
if(contentText) {
// The final content will be HTML instead of xml. And we will save it as wikitext, to make wiki syntax work, and remaining HTML will also work.
try {
// may error if content is not valid XML
contentNode = new DOMParser().parseFromString(contentText,"application/xml").querySelector("en-note") || contentNode;
} catch(e) {
// ignore
}
}
// process resources (images, PDFs, etc.)
$tw.utils.each(noteNode.querySelectorAll("resource"),function(resourceNode) {
// hash generated by applying https://github.com/vzhd1701/evernote-backup/pull/54
var hash = resourceNode.querySelector("data").getAttribute("hash");
var text = getTextContent(resourceNode,"data");
var mimeType = getTextContent(resourceNode,"mime");
var contentTypeInfo = $tw.config.contentTypeInfo[mimeType] || {extension:""};
// a few resources don't have title, use a random title
var title = getTextContent(resourceNode,"resource-attributes>file-name") || (noteTitle + String(Math.random()).replace("0.", "") + contentTypeInfo.extension);
results.push({
title: title,
type: mimeType,
width: getTextContent(resourceNode,"width"),
height: getTextContent(resourceNode,"height"),
text: text
});
if(hash) {
fixAttachmentReference(contentNode, hash, mimeType, title);
}
});
// process main content and metadata, and save as wikitext tiddler.
var result = {
title: getTextContent(noteNode,"title"),
type: "text/html",
title: noteTitle,
tags: [],
text: getTextContent(noteNode,"content"),
// export mixed content of wikitext and HTML
text: contentNode.innerHTML,
modified: convertDate(getTextContent(noteNode,"created")),
modifier: getTextContent(noteNode,"author"),
creator: getTextContent(noteNode,"author"),
created: convertDate(getTextContent(noteNode,"created"))

};
Expand All @@ -55,26 +90,34 @@ exports["application/enex+xml"] = function(text,fields) {
result[attrNode.tagName] = attrNode.textContent;
});
results.push(result);
$tw.utils.each(noteNode.querySelectorAll("resource"),function(resourceNode) {
results.push({
title: getTextContent(resourceNode,"resource-attributes>file-name"),
type: getTextContent(resourceNode,"mime"),
width: getTextContent(resourceNode,"width"),
height: getTextContent(resourceNode,"height"),
text: getTextContent(resourceNode,"data")
});
});
});
// Return the output tiddlers
return results;
};

function getTextContent(node,selector) {
return (node.querySelector(selector) || {}).textContent;
return (node.querySelector(selector) || {}).textContent || "";
}

function convertDate(isoDate) {
return (isoDate || "").replace("T","").replace("Z","") + "000"
}

function fixAttachmentReference(contentNode, md5Hash, mimeType, name) {
if(!contentNode) return;
var mediaNode = contentNode.querySelector('en-media[hash="' + md5Hash + '"]');
if(!name) {
throw new Error("name is empty for resource hash" + md5Hash);
}
if(!mediaNode) return;
if(mimeType.indexOf("image/") === 0) {
// find en-media node, replace with image syntax
mediaNode.parentNode.replaceChild($tw.utils.domMaker("p", {text: "[img["+ name + "]]"}), mediaNode);
} else {
// For other than image attachments, we make a link to the tiddler
mediaNode.parentNode.replaceChild($tw.utils.domMaker("p", {text: "[["+ name + "]]"}), mediaNode);
}
}


})();