From 4e08adb76f12df3c014e8f346ce0138b9a1f4056 Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Tue, 17 Nov 2020 14:50:28 +0000 Subject: [PATCH] Plugins: Added command to export folders and notes --- .eslintignore | 6 +++ .gitignore | 6 +++ joplin.code-workspace | 1 + packages/app-desktop/InteropServiceHelper.ts | 2 +- packages/app-desktop/app.ts | 22 +++++---- .../app-desktop/commands/exportFolders.ts | 22 +++++++++ packages/app-desktop/commands/exportNotes.ts | 22 +++++++++ .../lib/services/interop/InteropService.ts | 49 +++++++++++++------ packages/lib/services/interop/types.ts | 6 +-- packages/lib/services/plugins/api/types.ts | 2 +- 10 files changed, 108 insertions(+), 30 deletions(-) create mode 100644 packages/app-desktop/commands/exportFolders.ts create mode 100644 packages/app-desktop/commands/exportNotes.ts diff --git a/.eslintignore b/.eslintignore index bc8a6c042..3b3522696 100644 --- a/.eslintignore +++ b/.eslintignore @@ -325,6 +325,12 @@ packages/app-desktop/bridge.js.map packages/app-desktop/commands/copyDevCommand.d.ts packages/app-desktop/commands/copyDevCommand.js packages/app-desktop/commands/copyDevCommand.js.map +packages/app-desktop/commands/exportFolders.d.ts +packages/app-desktop/commands/exportFolders.js +packages/app-desktop/commands/exportFolders.js.map +packages/app-desktop/commands/exportNotes.d.ts +packages/app-desktop/commands/exportNotes.js +packages/app-desktop/commands/exportNotes.js.map packages/app-desktop/commands/focusElement.d.ts packages/app-desktop/commands/focusElement.js packages/app-desktop/commands/focusElement.js.map diff --git a/.gitignore b/.gitignore index 61a8dcf05..fc1561de0 100644 --- a/.gitignore +++ b/.gitignore @@ -317,6 +317,12 @@ packages/app-desktop/bridge.js.map packages/app-desktop/commands/copyDevCommand.d.ts packages/app-desktop/commands/copyDevCommand.js packages/app-desktop/commands/copyDevCommand.js.map +packages/app-desktop/commands/exportFolders.d.ts +packages/app-desktop/commands/exportFolders.js +packages/app-desktop/commands/exportFolders.js.map +packages/app-desktop/commands/exportNotes.d.ts +packages/app-desktop/commands/exportNotes.js +packages/app-desktop/commands/exportNotes.js.map packages/app-desktop/commands/focusElement.d.ts packages/app-desktop/commands/focusElement.js packages/app-desktop/commands/focusElement.js.map diff --git a/joplin.code-workspace b/joplin.code-workspace index 45b7408c0..b564ae02d 100644 --- a/joplin.code-workspace +++ b/joplin.code-workspace @@ -310,6 +310,7 @@ "packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/sanitize_html.js": true, "packages/app-mobile/lib/rnInjectedJs/": true, "packages/app-mobile/lib/sql-extensions/spellfix.so": true, + "packages/generator-joplin/generators/app/templates/api/": true, "packages/app-mobile/node_modules/": true, "phpunit.xml": true, "Server/db*.sqlite/": true, diff --git a/packages/app-desktop/InteropServiceHelper.ts b/packages/app-desktop/InteropServiceHelper.ts index d42ea7f12..33770a38f 100644 --- a/packages/app-desktop/InteropServiceHelper.ts +++ b/packages/app-desktop/InteropServiceHelper.ts @@ -161,7 +161,7 @@ export default class InteropServiceHelper { const exportOptions: ExportOptions = {}; exportOptions.path = path; exportOptions.format = module.format; - exportOptions.modulePath = module.path; + // exportOptions.modulePath = module.path; exportOptions.target = module.target; exportOptions.includeConflicts = !!options.includeConflicts; if (options.sourceFolderIds) exportOptions.sourceFolderIds = options.sourceFolderIds; diff --git a/packages/app-desktop/app.ts b/packages/app-desktop/app.ts index 83094e533..baf246909 100644 --- a/packages/app-desktop/app.ts +++ b/packages/app-desktop/app.ts @@ -42,15 +42,17 @@ const CssUtils = require('@joplin/lib/CssUtils'); // const populateDatabase = require('@joplin/lib/services/debug/populateDatabase').default; const commands = [ - require('./gui/NoteListControls/commands/focusSearch'), require('./gui/MainScreen/commands/editAlarm'), require('./gui/MainScreen/commands/exportPdf'), require('./gui/MainScreen/commands/hideModalMessage'), require('./gui/MainScreen/commands/moveToFolder'), - require('./gui/MainScreen/commands/newNote'), require('./gui/MainScreen/commands/newFolder'), + require('./gui/MainScreen/commands/newNote'), require('./gui/MainScreen/commands/newSubFolder'), require('./gui/MainScreen/commands/newTodo'), + require('./gui/MainScreen/commands/openFolder'), + require('./gui/MainScreen/commands/openNote'), + require('./gui/MainScreen/commands/openTag'), require('./gui/MainScreen/commands/print'), require('./gui/MainScreen/commands/renameFolder'), require('./gui/MainScreen/commands/renameTag'), @@ -62,34 +64,34 @@ const commands = [ require('./gui/MainScreen/commands/showNoteProperties'), require('./gui/MainScreen/commands/showShareNoteDialog'), require('./gui/MainScreen/commands/showSpellCheckerMenu'), + require('./gui/MainScreen/commands/toggleEditors'), + require('./gui/MainScreen/commands/toggleLayoutMoveMode'), require('./gui/MainScreen/commands/toggleNoteList'), require('./gui/MainScreen/commands/toggleSideBar'), require('./gui/MainScreen/commands/toggleVisiblePanes'), - require('./gui/MainScreen/commands/toggleEditors'), - require('./gui/MainScreen/commands/openNote'), - require('./gui/MainScreen/commands/openFolder'), - require('./gui/MainScreen/commands/openTag'), - require('./gui/MainScreen/commands/toggleLayoutMoveMode'), require('./gui/NoteEditor/commands/focusElementNoteBody'), require('./gui/NoteEditor/commands/focusElementNoteTitle'), require('./gui/NoteEditor/commands/showLocalSearch'), require('./gui/NoteEditor/commands/showRevisions'), require('./gui/NoteList/commands/focusElementNoteList'), + require('./gui/NoteListControls/commands/focusSearch'), require('./gui/SideBar/commands/focusElementSideBar'), ]; // Commands that are not tied to any particular component. // The runtime for these commands can be loaded when the app starts. const globalCommands = [ + require('./commands/copyDevCommand'), + require('./commands/exportFolders'), + require('./commands/exportNotes'), require('./commands/focusElement'), + require('./commands/openProfileDirectory'), require('./commands/startExternalEditing'), require('./commands/stopExternalEditing'), require('./commands/toggleExternalEditing'), - require('./commands/copyDevCommand'), - require('./commands/openProfileDirectory'), - require('@joplin/lib/commands/synchronize'), require('@joplin/lib/commands/historyBackward'), require('@joplin/lib/commands/historyForward'), + require('@joplin/lib/commands/synchronize'), ]; const editorCommandDeclarations = require('./gui/NoteEditor/commands/editorCommandDeclarations').default; diff --git a/packages/app-desktop/commands/exportFolders.ts b/packages/app-desktop/commands/exportFolders.ts new file mode 100644 index 000000000..e48e1c4eb --- /dev/null +++ b/packages/app-desktop/commands/exportFolders.ts @@ -0,0 +1,22 @@ +import { CommandRuntime, CommandDeclaration } from '@joplin/lib/services/CommandService'; +import InteropService from '@joplin/lib/services/interop/InteropService'; +import { ExportOptions, FileSystemItem } from '@joplin/lib/services/interop/types'; + +export const declaration: CommandDeclaration = { + name: 'exportFolders', +}; + +export const runtime = (): CommandRuntime => { + return { + execute: async (_context: any, folderIds: string[], format: string, targetDirectoryPath: string) => { + const exportOptions: ExportOptions = { + sourceFolderIds: folderIds, + path: targetDirectoryPath, + format: format, + target: FileSystemItem.Directory, + }; + + return InteropService.instance().export(exportOptions); + }, + }; +}; diff --git a/packages/app-desktop/commands/exportNotes.ts b/packages/app-desktop/commands/exportNotes.ts new file mode 100644 index 000000000..cbf355dd2 --- /dev/null +++ b/packages/app-desktop/commands/exportNotes.ts @@ -0,0 +1,22 @@ +import { CommandRuntime, CommandDeclaration } from '@joplin/lib/services/CommandService'; +import InteropService from '@joplin/lib/services/interop/InteropService'; +import { ExportOptions, FileSystemItem } from '@joplin/lib/services/interop/types'; + +export const declaration: CommandDeclaration = { + name: 'exportNotes', +}; + +export const runtime = (): CommandRuntime => { + return { + execute: async (_context: any, noteIds: string[], format: string, targetDirectoryPath: string) => { + const exportOptions: ExportOptions = { + path: targetDirectoryPath, + format: format, + target: FileSystemItem.Directory, + sourceNoteIds: noteIds, + }; + + return InteropService.instance().export(exportOptions); + }, + }; +}; diff --git a/packages/lib/services/interop/InteropService.ts b/packages/lib/services/interop/InteropService.ts index ebd5d62a9..9baf82c5c 100644 --- a/packages/lib/services/interop/InteropService.ts +++ b/packages/lib/services/interop/InteropService.ts @@ -216,21 +216,15 @@ export default class InteropService { * https://github.com/laurent22/joplin/pull/1795#pullrequestreview-281574417 */ newModuleFromPath_(type: ModuleType, options: any) { - let modulePath = options && options.modulePath ? options.modulePath : ''; - - if (!modulePath) { - const moduleMetadata = this.findModuleByFormat_(type, options.format, options.target); - if (!moduleMetadata) throw new Error(_('Cannot load "%s" module for format "%s" and target "%s"', type, options.format, options.target)); - modulePath = this.modulePath(moduleMetadata); - } - const moduleMetadata = this.findModuleByFormat_(type, options.format, options.target); + if (!moduleMetadata) throw new Error(_('Cannot load "%s" module for format "%s" and target "%s"', type, options.format, options.target)); let output = null; if (moduleMetadata.isCustom) { output = this.newModuleFromCustomFactory(moduleMetadata); } else { + const modulePath = this.modulePath(moduleMetadata); const ModuleClass = require(modulePath).default; output = new ModuleClass(); } @@ -238,6 +232,29 @@ export default class InteropService { output.setMetadata({ options, ...moduleMetadata }); return output; + + // let modulePath = options && options.modulePath ? options.modulePath : ''; + + // if (!modulePath) { + // const moduleMetadata = this.findModuleByFormat_(type, options.format, options.target); + // if (!moduleMetadata) throw new Error(_('Cannot load "%s" module for format "%s" and target "%s"', type, options.format, options.target)); + // modulePath = this.modulePath(moduleMetadata); + // } + + // const moduleMetadata = this.findModuleByFormat_(type, options.format, options.target); + + // let output = null; + + // if (moduleMetadata.isCustom) { + // output = this.newModuleFromCustomFactory(moduleMetadata); + // } else { + // const ModuleClass = require(modulePath).default; + // output = new ModuleClass(); + // } + + // output.setMetadata({ options, ...moduleMetadata }); + + // return output; } moduleByFileExtension_(type: ModuleType, ext: string) { @@ -280,15 +297,17 @@ export default class InteropService { let result: ImportExportResult = { warnings: [] }; - let importer = null; - + // let importer = null; + // // Not certain the "modulePath" property still has any use at this point. Modules should be looked up // based on their format and outputFormat. - if (options.modulePath) { - importer = this.newModuleFromPath_(ModuleType.Importer, options); - } else { - importer = this.newModuleByFormat_(ModuleType.Importer, options.format, options.outputFormat); - } + // if (options.modulePath) { + // importer = this.newModuleFromPath_(ModuleType.Importer, options); + // } else { + // importer = this.newModuleByFormat_(ModuleType.Importer, options.format, options.outputFormat); + // } + + const importer = this.newModuleByFormat_(ModuleType.Importer, options.format, options.outputFormat); await importer.init(options.path, options); result = await importer.exec(result); diff --git a/packages/lib/services/interop/types.ts b/packages/lib/services/interop/types.ts index b6d2eaf2c..ab4326769 100644 --- a/packages/lib/services/interop/types.ts +++ b/packages/lib/services/interop/types.ts @@ -38,7 +38,7 @@ export interface Module { format: string; fileExtensions: string[]; description: string; - path?: string; + // path?: string; // Only applies to single file exporters or importers // It tells whether the format can package multiple notes into one file. @@ -80,7 +80,7 @@ export interface Module { export interface ImportOptions { path?: string; format?: string; - modulePath?: string; + // modulePath?: string; destinationFolderId?: string; destinationFolder?: any; outputFormat?: ImportModuleOutputFormat; @@ -91,7 +91,7 @@ export interface ExportOptions { path?: string; sourceFolderIds?: string[]; sourceNoteIds?: string[]; - modulePath?: string; + // modulePath?: string; target?: FileSystemItem; includeConflicts?: boolean; } diff --git a/packages/lib/services/plugins/api/types.ts b/packages/lib/services/plugins/api/types.ts index d58bca6c3..dbe4b6d57 100644 --- a/packages/lib/services/plugins/api/types.ts +++ b/packages/lib/services/plugins/api/types.ts @@ -161,7 +161,7 @@ export interface ExportOptions { path?: string; sourceFolderIds?: string[]; sourceNoteIds?: string[]; - modulePath?: string; + // modulePath?: string; target?: FileSystemItem; }