mirror of
https://github.com/laurent22/joplin.git
synced 2025-03-26 21:12:59 +02:00
All: Resolves #734: Allow exporting to a hierarchy of Markdown files, and fixed a few issues related to exporting notebooks
This commit is contained in:
parent
81ec8eaf83
commit
eaf3eef2d3
@ -11,7 +11,7 @@ class InteropServiceHelper {
|
||||
|
||||
if (module.target === 'file') {
|
||||
path = bridge().showSaveDialog({
|
||||
filters: [{ name: module.description, extensions: module.fileExtension}]
|
||||
filters: [{ name: module.description, extensions: module.fileExtensions}]
|
||||
});
|
||||
} else {
|
||||
path = bridge().showOpenDialog({
|
||||
|
@ -238,14 +238,22 @@ class SideBarComponent extends React.Component {
|
||||
|
||||
const InteropService = require("lib/services/InteropService.js");
|
||||
|
||||
const exportMenu = new Menu();
|
||||
const ioService = new InteropService();
|
||||
const ioModules = ioService.modules();
|
||||
for (let i = 0; i < ioModules.length; i++) {
|
||||
const module = ioModules[i];
|
||||
if (module.type !== 'exporter') continue;
|
||||
|
||||
exportMenu.append(new MenuItem({ label: module.fullLabel() , click: async () => {
|
||||
await InteropServiceHelper.export(this.props.dispatch.bind(this), module, { sourceFolderIds: [itemId] });
|
||||
}}));
|
||||
}
|
||||
|
||||
menu.append(
|
||||
new MenuItem({
|
||||
label: _("Export"),
|
||||
click: async () => {
|
||||
const ioService = new InteropService();
|
||||
const module = ioService.moduleByFormat_("exporter", "jex");
|
||||
await InteropServiceHelper.export(this.props.dispatch.bind(this), module, { sourceFolderIds: [itemId] });
|
||||
},
|
||||
submenu: exportMenu,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -40,9 +40,11 @@ function safeFileExtension(e) {
|
||||
return e.replace(/[^a-zA-Z0-9]/g, '')
|
||||
}
|
||||
|
||||
function safeFilename(e, maxLength = 32) {
|
||||
function safeFilename(e, maxLength = null, allowSpaces = false) {
|
||||
if (maxLength === null) maxLength = 32;
|
||||
if (!e || !e.replace) return '';
|
||||
let output = e.replace(/[^a-zA-Z0-9\-_\(\)\.]/g, '_')
|
||||
const regex = allowSpaces ? /[^a-zA-Z0-9\-_\(\)\. ]/g : /[^a-zA-Z0-9\-_\(\)\.]/g
|
||||
let output = e.replace(regex, '_')
|
||||
return output.substr(0, maxLength);
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,10 @@ class InteropService {
|
||||
format: 'raw',
|
||||
target: 'directory',
|
||||
description: _('Joplin Export Directory'),
|
||||
}, {
|
||||
format: 'md',
|
||||
target: 'directory',
|
||||
description: _('Markdown'),
|
||||
},
|
||||
];
|
||||
|
||||
|
58
ReactNativeClient/lib/services/InteropService_Exporter_Md.js
Normal file
58
ReactNativeClient/lib/services/InteropService_Exporter_Md.js
Normal file
@ -0,0 +1,58 @@
|
||||
const InteropService_Exporter_Base = require('lib/services/InteropService_Exporter_Base');
|
||||
const { basename, filename, safeFilename } = require('lib/path-utils.js');
|
||||
const BaseModel = require('lib/BaseModel');
|
||||
const Folder = require('lib/models/Folder');
|
||||
const Note = require('lib/models/Note');
|
||||
const { shim } = require('lib/shim');
|
||||
|
||||
class InteropService_Exporter_Md extends InteropService_Exporter_Base {
|
||||
|
||||
async init(destDir) {
|
||||
this.destDir_ = destDir;
|
||||
this.resourceDir_ = destDir ? destDir + '/_resources' : null;
|
||||
this.createdDirs_ = [];
|
||||
|
||||
await shim.fsDriver().mkdir(this.destDir_);
|
||||
await shim.fsDriver().mkdir(this.resourceDir_);
|
||||
}
|
||||
|
||||
async makeDirPath_(item) {
|
||||
let output = '';
|
||||
while (true) {
|
||||
if (item.type_ === BaseModel.TYPE_FOLDER) {
|
||||
output = safeFilename(item.title, null, true) + '/' + output;
|
||||
}
|
||||
if (!item.parent_id) return output;
|
||||
item = await Folder.load(item.parent_id);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
async processItem(ItemClass, item) {
|
||||
if ([BaseModel.TYPE_NOTE, BaseModel.TYPE_FOLDER].indexOf(item.type_) < 0) return;
|
||||
|
||||
const filename = safeFilename(item.title, null, true);
|
||||
const dirPath = this.destDir_ + '/' + (await this.makeDirPath_(item));
|
||||
|
||||
if (this.createdDirs_.indexOf(dirPath) < 0) {
|
||||
await shim.fsDriver().mkdir(dirPath);
|
||||
this.createdDirs_.push(dirPath);
|
||||
}
|
||||
|
||||
if (item.type_ === BaseModel.TYPE_NOTE) {
|
||||
const noteFilePath = dirPath + '/' + safeFilename(item.title, null, true) + '.md';
|
||||
const noteContent = await Note.serializeForEdit(item);
|
||||
await shim.fsDriver().writeFile(noteFilePath, noteContent, 'utf-8');
|
||||
}
|
||||
}
|
||||
|
||||
async processResource(resource, filePath) {
|
||||
const destResourcePath = this.resourceDir_ + '/' + basename(filePath);
|
||||
await shim.fsDriver().copy(filePath, destResourcePath);
|
||||
}
|
||||
|
||||
async close() {}
|
||||
|
||||
}
|
||||
|
||||
module.exports = InteropService_Exporter_Md;
|
Loading…
x
Reference in New Issue
Block a user