mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 17:56:25 +00:00
Right now there are only two export types that are using a special output formatter, pdf and html. Both of these formatters currently populate the `/html/head/base` portion of the associated html document with the name of the target directory for the file that the user is exporting. In order for internal links within the exported document to work correctly, the value of base must also include the filename. This fix removes the call to `path.dirname`, which gets rid of the necessary filename.
114 lines
3.0 KiB
JavaScript
Executable File
114 lines
3.0 KiB
JavaScript
Executable File
import copyFile from 'browser/main/lib/dataApi/copyFile'
|
||
import { findStorage } from 'browser/lib/findStorage'
|
||
|
||
const fs = require('fs')
|
||
const path = require('path')
|
||
|
||
const attachmentManagement = require('./attachmentManagement')
|
||
|
||
/**
|
||
* Export note together with attachments
|
||
*
|
||
* If attachments are stored in the storage, creates 'attachments' subfolder in target directory
|
||
* and copies attachments to it. Changes links to images in the content of the note
|
||
*
|
||
* @param {String} nodeKey key of the node that should be exported
|
||
* @param {String} storageKey or storage path
|
||
* @param {String} noteContent Content to export
|
||
* @param {String} targetPath Path to exported file
|
||
* @param {function} outputFormatter
|
||
* @return {Promise.<*[]>}
|
||
*/
|
||
function exportNote (nodeKey, storageKey, noteContent, targetPath, outputFormatter) {
|
||
const storagePath = path.isAbsolute(storageKey) ? storageKey : findStorage(storageKey).path
|
||
const exportTasks = []
|
||
|
||
if (!storagePath) {
|
||
throw new Error('Storage path is not found')
|
||
}
|
||
const attachmentsAbsolutePaths = attachmentManagement.getAbsolutePathsOfAttachmentsInContent(
|
||
noteContent,
|
||
storagePath
|
||
)
|
||
attachmentsAbsolutePaths.forEach(attachment => {
|
||
exportTasks.push({
|
||
src: attachment,
|
||
dst: attachmentManagement.DESTINATION_FOLDER
|
||
})
|
||
})
|
||
|
||
let exportedData = attachmentManagement.removeStorageAndNoteReferences(
|
||
noteContent,
|
||
nodeKey
|
||
)
|
||
|
||
if (outputFormatter) {
|
||
exportedData = outputFormatter(exportedData, exportTasks, targetPath)
|
||
} else {
|
||
exportedData = Promise.resolve(exportedData)
|
||
}
|
||
|
||
const tasks = prepareTasks(exportTasks, storagePath, path.dirname(targetPath))
|
||
|
||
return Promise.all(tasks.map((task) => copyFile(task.src, task.dst)))
|
||
.then(() => exportedData)
|
||
.then(data => {
|
||
return saveToFile(data, targetPath)
|
||
}).catch((err) => {
|
||
rollbackExport(tasks)
|
||
throw err
|
||
})
|
||
}
|
||
|
||
function prepareTasks (tasks, storagePath, targetPath) {
|
||
return tasks.map((task) => {
|
||
if (!path.isAbsolute(task.src)) {
|
||
task.src = path.join(storagePath, task.src)
|
||
}
|
||
|
||
if (!path.isAbsolute(task.dst)) {
|
||
task.dst = path.join(targetPath, task.dst)
|
||
}
|
||
|
||
return task
|
||
})
|
||
}
|
||
|
||
function saveToFile (data, filename) {
|
||
return new Promise((resolve, reject) => {
|
||
fs.writeFile(filename, data, (err) => {
|
||
if (err) return reject(err)
|
||
|
||
resolve(filename)
|
||
})
|
||
})
|
||
}
|
||
|
||
/**
|
||
* Remove exported files
|
||
* @param tasks Array of copy task objects. Object consists of two mandatory fields – `src` and `dst`
|
||
*/
|
||
function rollbackExport (tasks) {
|
||
const folders = new Set()
|
||
tasks.forEach((task) => {
|
||
let fullpath = task.dst
|
||
|
||
if (!path.extname(task.dst)) {
|
||
fullpath = path.join(task.dst, path.basename(task.src))
|
||
}
|
||
|
||
if (fs.existsSync(fullpath)) {
|
||
fs.unlink(fullpath)
|
||
folders.add(path.dirname(fullpath))
|
||
}
|
||
})
|
||
|
||
folders.forEach((folder) => {
|
||
if (fs.readdirSync(folder).length === 0) {
|
||
fs.rmdir(folder)
|
||
}
|
||
})
|
||
}
|
||
|
||
export default exportNote
|