1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-11-06 09:19:22 +02:00

Desktop: Add ENEX to HTML export (#1795)

* Add `escape` to go back from Dropbox Login screen

* Add .vscode/ to .gitignore

* Remove call to enexXmlToMd

* The 2 enex importers have distinct functionality!

* Add tmp #deleteAllNotebooks

* checkbox state still not persisting

* images now fixed, but checkboxes still broken

* Figured out that #ipcProxySendToHost is important for handling checkbox

* cleanup closing br and en-todo tags + add notes

* Handle en-media, add NOTEs & TODOs, & format html

* Clean up some of the logging

* cleanHtml is a nice beautifier, but callback hell ensues...

* Rm #htmlFormat

* Recreating the xml actually seems to work

* Add test (not functional rn)

* Add test for checkboxes

* Add test for image en-media

* Separate tests into 2 function calls

* Clean up test

* Add `en-media-audio` test

* Add bad resource test

* Misc cleanup

* Rm SlateEditor files

* Misc cleanup

* Remove #deleteAllNotebooks button

* Add names to tests

* Extract resourceUtils

* Rm DropboxLoginScreen esc behavior, part of another PR

* Misc cleanup

* Improve audioElement, add attachment import support

* Misc cleanup

* Add svg test for enex_to_html

* Clean up test

* Set markup_language to MARKUP_LANGUAGE_HTML to tell renderer that the content is only HTML

* Rename to newModuleByFormat_ for clarity

* Add comment to clarify newModuleFromPath_
This commit is contained in:
Devon Zuegel
2019-09-17 13:19:32 -07:00
committed by Laurent Cozic
parent 52ace55db0
commit 2f14832c34
25 changed files with 749 additions and 85 deletions

View File

@@ -13,8 +13,7 @@ const { toTitleCase } = require('lib/string-utils');
class InteropService {
constructor() {
this.modules_ = null;
}
this.modules_ = null; }
modules() {
if (this.modules_) return this.modules_;
@@ -42,7 +41,16 @@ class InteropService {
format: 'enex',
fileExtensions: ['enex'],
sources: ['file'],
description: _('Evernote Export File'),
description: _('Evernote Export File (as Markdown)'),
importerClass: 'InteropService_Importer_EnexToMd',
},
{
format: 'enex',
fileExtensions: ['enex'],
sources: ['file'],
description: _('Evernote Export File (as HTML)'),
// TODO: Consider doing this the same way as the multiple `md` importers are handled
importerClass: 'InteropService_Importer_EnexToHtml',
},
];
@@ -71,7 +79,7 @@ class InteropService {
];
importModules = importModules.map(a => {
const className = 'InteropService_Importer_' + toTitleCase(a.format);
const className = a.importerClass || 'InteropService_Importer_' + toTitleCase(a.format);
const output = Object.assign(
{},
{
@@ -112,8 +120,9 @@ class InteropService {
return this.modules_;
}
moduleByFormat_(type, format) {
findModuleByFormat_(type, format) {
const modules = this.modules();
// console.log(JSON.stringify({modules}, null, 2))
for (let i = 0; i < modules.length; i++) {
const m = modules[i];
if (m.format === format && m.type === type) return modules[i];
@@ -121,8 +130,8 @@ class InteropService {
return null;
}
newModule_(type, format) {
const module = this.moduleByFormat_(type, format);
newModuleByFormat_(type, format) {
const module = this.findModuleByFormat_(type, format);
if (!module) throw new Error(_('Cannot load "%s" module for format "%s"', type, format));
const ModuleClass = require(module.path);
const output = new ModuleClass();
@@ -130,6 +139,26 @@ class InteropService {
return output;
}
/**
* The existing `newModuleByFormat_` fn would load by the input format. This
* was fine when there was a 1-1 mapping of input formats to output formats,
* but now that we have 2 possible outputs for an `enex` input, we need to be
* explicit with which importer we want to use.
*
* In the long run, it might make sense to simply move all the existing
* formatters to the `newModuleFromPath_` approach, so that there's only one
* way to do this mapping.
*
* https://github.com/laurent22/joplin/pull/1795#pullrequestreview-281574417
*/
newModuleFromPath_(options) {
if (!options || !options.modulePath) throw new Error('Cannot load module without a defined path to load from.');
const ModuleClass = require(options.modulePath);
const output = new ModuleClass();
output.setMetadata(options); // TODO: Check that this metadata is equivalent to module above
return output;
}
moduleByFileExtension_(type, ext) {
ext = ext.toLowerCase();
@@ -173,7 +202,10 @@ class InteropService {
let result = { warnings: [] };
const importer = this.newModule_('importer', options.format);
// console.log('options passed to InteropService:');
// console.log(JSON.stringify({options}, null, 2));
const importer = this.newModuleFromPath_(options);
await importer.init(options.path, options);
result = await importer.exec(result);
@@ -248,7 +280,7 @@ class InteropService {
await queueExportItem(BaseModel.TYPE_TAG, exportedTagIds[i]);
}
const exporter = this.newModule_('exporter', exportFormat);
const exporter = this.newModuleByFormat_('exporter', exportFormat);
await exporter.init(exportPath);
const typeOrder = [BaseModel.TYPE_FOLDER, BaseModel.TYPE_RESOURCE, BaseModel.TYPE_NOTE, BaseModel.TYPE_TAG, BaseModel.TYPE_NOTE_TAG];

View File

@@ -0,0 +1,22 @@
const InteropService_Importer_Base = require('lib/services/InteropService_Importer_Base');
const Folder = require('lib/models/Folder.js');
const { filename } = require('lib/path-utils.js');
class InteropService_Importer_EnexToHtml extends InteropService_Importer_Base {
async exec(result) {
const { importEnex } = require('lib/import-enex');
let folder = this.options_.destinationFolder;
if (!folder) {
const folderTitle = await Folder.findUniqueItemTitle(filename(this.sourcePath_));
folder = await Folder.save({ title: folderTitle });
}
await importEnex(folder.id, this.sourcePath_, {...this.options_, outputFormat: 'html'});
return result;
}
}
module.exports = InteropService_Importer_EnexToHtml;

View File

@@ -2,7 +2,7 @@ const InteropService_Importer_Base = require('lib/services/InteropService_Import
const Folder = require('lib/models/Folder.js');
const { filename } = require('lib/path-utils.js');
class InteropService_Importer_Enex extends InteropService_Importer_Base {
class InteropService_Importer_EnexToMd extends InteropService_Importer_Base {
async exec(result) {
const { importEnex } = require('lib/import-enex');
@@ -19,4 +19,4 @@ class InteropService_Importer_Enex extends InteropService_Importer_Base {
}
}
module.exports = InteropService_Importer_Enex;
module.exports = InteropService_Importer_EnexToMd;