diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index 17d2cb82d..d5df8de48 100755 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -205,6 +205,7 @@ export default class MarkdownPreview extends React.Component { this.saveAsTextHandler = () => this.handleSaveAsText() this.saveAsMdHandler = () => this.handleSaveAsMd() this.saveAsHtmlHandler = () => this.handleSaveAsHtml() + this.saveAsPdfHandler = () => this.handleSaveAsPdf() this.printHandler = () => this.handlePrint() this.linkClickHandler = this.handlelinkClick.bind(this) @@ -294,58 +295,77 @@ export default class MarkdownPreview extends React.Component { this.exportAsDocument('md') } - handleSaveAsHtml () { - this.exportAsDocument('html', (noteContent, exportTasks) => { - const { - fontFamily, - fontSize, - codeBlockFontFamily, - lineNumber, - codeBlockTheme, - scrollPastEnd, - theme, - allowCustomCSS, - customCSS - } = this.getStyleParams() - - const inlineStyles = buildStyle( - fontFamily, - fontSize, - codeBlockFontFamily, - lineNumber, - scrollPastEnd, - theme, - allowCustomCSS, - customCSS - ) - let body = this.markdown.render(noteContent) - const files = [this.GetCodeThemeLink(codeBlockTheme), ...CSS_FILES] - files.forEach(file => { - if (global.process.platform === 'win32') { - file = file.replace('file:///', '') - } else { - file = file.replace('file://', '') - } - exportTasks.push({ - src: file, - dst: 'css' - }) - }) + htmlContentFormatter (noteContent, exportTasks, targetDir) { + const { + fontFamily, + fontSize, + codeBlockFontFamily, + lineNumber, + codeBlockTheme, + scrollPastEnd, + theme, + allowCustomCSS, + customCSS + } = this.getStyleParams() - let styles = '' - files.forEach(file => { - styles += `` + const inlineStyles = buildStyle( + fontFamily, + fontSize, + codeBlockFontFamily, + lineNumber, + scrollPastEnd, + theme, + allowCustomCSS, + customCSS + ) + let body = this.markdown.render(noteContent) + const files = [this.GetCodeThemeLink(codeBlockTheme), ...CSS_FILES] + files.forEach(file => { + if (global.process.platform === 'win32') { + file = file.replace('file:///', '') + } else { + file = file.replace('file://', '') + } + exportTasks.push({ + src: file, + dst: 'css' }) + }) - return ` - - - - - ${styles} - - ${body} - ` + let styles = '' + files.forEach(file => { + styles += `` + }) + + return ` + + + + + + ${styles} + + ${body} + ` + } + + handleSaveAsHtml () { + this.exportAsDocument('html', (noteContent, exportTasks, targetDir) => Promise.resolve(this.htmlContentFormatter(noteContent, exportTasks, targetDir))) + } + + handleSaveAsPdf () { + this.exportAsDocument('pdf', (noteContent, exportTasks, targetDir) => { + const printout = new remote.BrowserWindow({show: false, webPreferences: {webSecurity: false}}) + printout.loadURL('data:text/html;charset=UTF-8,' + this.htmlContentFormatter(noteContent, exportTasks, targetDir)) + return new Promise((resolve, reject) => { + printout.webContents.on('did-finish-load', () => { + printout.webContents.printToPDF({}, (err, data) => { + if (err) reject(err) + else resolve(data) + printout.destroy() + }) + }) + }) }) } @@ -460,6 +480,7 @@ export default class MarkdownPreview extends React.Component { eventEmitter.on('export:save-text', this.saveAsTextHandler) eventEmitter.on('export:save-md', this.saveAsMdHandler) eventEmitter.on('export:save-html', this.saveAsHtmlHandler) + eventEmitter.on('export:save-pdf', this.saveAsPdfHandler) eventEmitter.on('print', this.printHandler) } @@ -495,6 +516,7 @@ export default class MarkdownPreview extends React.Component { eventEmitter.off('export:save-text', this.saveAsTextHandler) eventEmitter.off('export:save-md', this.saveAsMdHandler) eventEmitter.off('export:save-html', this.saveAsHtmlHandler) + eventEmitter.off('export:save-pdf', this.saveAsPdfHandler) eventEmitter.off('print', this.printHandler) } diff --git a/browser/main/Detail/InfoPanel.js b/browser/main/Detail/InfoPanel.js index 15535186a..8fe0a8554 100644 --- a/browser/main/Detail/InfoPanel.js +++ b/browser/main/Detail/InfoPanel.js @@ -14,7 +14,7 @@ class InfoPanel extends React.Component { render () { const { - storageName, folderName, noteLink, updatedAt, createdAt, exportAsMd, exportAsTxt, exportAsHtml, wordCount, letterCount, type, print + storageName, folderName, noteLink, updatedAt, createdAt, exportAsMd, exportAsTxt, exportAsHtml, exportAsPdf, wordCount, letterCount, type, print } = this.props return (
@@ -85,6 +85,11 @@ class InfoPanel extends React.Component {

{i18n.__('.html')}

+ + - @@ -61,7 +61,8 @@ InfoPanelTrashed.propTypes = { createdAt: PropTypes.string.isRequired, exportAsMd: PropTypes.func.isRequired, exportAsTxt: PropTypes.func.isRequired, - exportAsHtml: PropTypes.func.isRequired + exportAsHtml: PropTypes.func.isRequired, + exportAsPdf: PropTypes.func.isRequired } export default CSSModules(InfoPanelTrashed, styles) diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index b4e7a5b34..08d8bfbdf 100755 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -190,6 +190,10 @@ class MarkdownNoteDetail extends React.Component { ee.emit('export:save-html') } + exportAsPdf () { + ee.emit('export:save-pdf') + } + handleKeyDown (e) { switch (e.keyCode) { // tab key @@ -411,6 +415,7 @@ class MarkdownNoteDetail extends React.Component { exportAsHtml={this.exportAsHtml} exportAsMd={this.exportAsMd} exportAsTxt={this.exportAsTxt} + exportAsPdf={this.exportAsPdf} />
@@ -476,6 +481,7 @@ class MarkdownNoteDetail extends React.Component { exportAsMd={this.exportAsMd} exportAsTxt={this.exportAsTxt} exportAsHtml={this.exportAsHtml} + exportAsPdf={this.exportAsPdf} wordCount={note.content.split(' ').length} letterCount={note.content.replace(/\r?\n/g, '').length} type={note.type} diff --git a/browser/main/Detail/SnippetNoteDetail.js b/browser/main/Detail/SnippetNoteDetail.js index 4a5076da5..2e93ea25a 100644 --- a/browser/main/Detail/SnippetNoteDetail.js +++ b/browser/main/Detail/SnippetNoteDetail.js @@ -650,6 +650,7 @@ class SnippetNoteDetail extends React.Component { 'export-txt': 'Text export', 'export-md': 'Markdown export', 'export-html': 'HTML export', + 'export-pdf': 'PDF export', 'print': 'Print' })[msg] @@ -757,6 +758,7 @@ class SnippetNoteDetail extends React.Component { exportAsMd={this.showWarning} exportAsTxt={this.showWarning} exportAsHtml={this.showWarning} + exportAsPdf={this.showWarning} /> @@ -808,6 +810,7 @@ class SnippetNoteDetail extends React.Component { exportAsMd={this.showWarning} exportAsTxt={this.showWarning} exportAsHtml={this.showWarning} + exportAsPdf={this.showWarning} type={note.type} print={this.showWarning} /> diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index 31efaede5..b5748fd4d 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -500,6 +500,7 @@ class NoteList extends React.Component { 'export-txt': 'Text export', 'export-md': 'Markdown export', 'export-html': 'HTML export', + 'export-pdf': 'PDF export', 'print': 'Print' })[msg] diff --git a/browser/main/lib/dataApi/exportFolder.js b/browser/main/lib/dataApi/exportFolder.js index 771f77dcd..8f15b147c 100644 --- a/browser/main/lib/dataApi/exportFolder.js +++ b/browser/main/lib/dataApi/exportFolder.js @@ -43,19 +43,18 @@ function exportFolder (storageKey, folderKey, fileType, exportDir) { .then(function exportNotes (data) { const { storage, notes } = data - notes + return Promise.all(notes .filter(note => note.folder === folderKey && note.isTrashed === false && note.type === 'MARKDOWN_NOTE') - .forEach(note => { + .map(note => { const notePath = path.join(exportDir, `${filenamify(note.title, {replacement: '_'})}.${fileType}`) - exportNote(note.key, storage.path, note.content, notePath, null) + return exportNote(note.key, storage.path, note.content, notePath, null) }) - - return { + ).then(() => ({ storage, folderKey, fileType, exportDir - } + })) }) } diff --git a/browser/main/lib/dataApi/exportNote.js b/browser/main/lib/dataApi/exportNote.js index b358e5481..75c451c13 100755 --- a/browser/main/lib/dataApi/exportNote.js +++ b/browser/main/lib/dataApi/exportNote.js @@ -43,14 +43,17 @@ function exportNote (nodeKey, storageKey, noteContent, targetPath, outputFormatt ) if (outputFormatter) { - exportedData = outputFormatter(exportedData, exportTasks) + exportedData = outputFormatter(exportedData, exportTasks, path.dirname(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(() => { - return saveToFile(exportedData, targetPath) + .then(() => exportedData) + .then(data => { + return saveToFile(data, targetPath) }).catch((err) => { rollbackExport(tasks) throw err diff --git a/lib/main-menu.js b/lib/main-menu.js index eb08273a4..012c9ea37 100644 --- a/lib/main-menu.js +++ b/lib/main-menu.js @@ -116,6 +116,13 @@ const file = { mainWindow.webContents.send('list:isMarkdownNote', 'export-html') mainWindow.webContents.send('export:save-html') } + }, + { + label: 'PDF (.pdf)', + click () { + mainWindow.webContents.send('list:isMarkdownNote', 'export-pdf') + mainWindow.webContents.send('export:save-pdf') + } } ] }, diff --git a/locales/da.json b/locales/da.json index da5843f31..5d1a392b8 100644 --- a/locales/da.json +++ b/locales/da.json @@ -18,6 +18,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "Print", "Your preferences for Boostnote": "Your preferences for Boostnote", "Storage Locations": "Storage Locations", diff --git a/locales/de.json b/locales/de.json index 1b90ab635..9177adec6 100644 --- a/locales/de.json +++ b/locales/de.json @@ -18,6 +18,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "Drucken", "Your preferences for Boostnote": "Boostnote Einstellungen", "Storage Locations": "Speicherverwaltung", diff --git a/locales/en.json b/locales/en.json index fe7931da5..831789c1e 100644 --- a/locales/en.json +++ b/locales/en.json @@ -19,6 +19,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "Print", "Your preferences for Boostnote": "Your preferences for Boostnote", "Help": "Help", diff --git a/locales/es-ES.json b/locales/es-ES.json index 8b2da1b79..3bd2cb494 100644 --- a/locales/es-ES.json +++ b/locales/es-ES.json @@ -18,6 +18,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "Imprimir", "Your preferences for Boostnote": "Tus preferencias para Boostnote", "Storage Locations": "Almacenamientos", diff --git a/locales/fa.json b/locales/fa.json index 18bef679d..8f702767a 100644 --- a/locales/fa.json +++ b/locales/fa.json @@ -18,6 +18,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "پرینت", "Your preferences for Boostnote": "تنظیمات شما برای boostnote", "Storage Locations": "ذخیره سازی", diff --git a/locales/fr.json b/locales/fr.json index ea5a1c057..35d2f3c8b 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -18,6 +18,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "Imprimer", "Your preferences for Boostnote": "Vos préférences pour Boostnote", "Storage Locations": "Stockages", diff --git a/locales/hu.json b/locales/hu.json index 77bdb2abf..e76f06c9f 100644 --- a/locales/hu.json +++ b/locales/hu.json @@ -19,6 +19,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "Nyomtatás", "Your preferences for Boostnote": "Boostnote beállításaid", "Help": "Súgó", diff --git a/locales/it.json b/locales/it.json index 05f454f36..69ddd380f 100644 --- a/locales/it.json +++ b/locales/it.json @@ -18,6 +18,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "Stampa", "Your preferences for Boostnote": "Le tue preferenze per Boostnote", "Storage Locations": "Posizioni", diff --git a/locales/ja.json b/locales/ja.json index e33bbaa63..b96183813 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -19,6 +19,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "印刷", "Your preferences for Boostnote": "Boostnoteの個人設定", "Help": "ヘルプ", diff --git a/locales/ko.json b/locales/ko.json index 9a8bf8c75..59ffe7b9c 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -18,6 +18,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "인쇄", "Your preferences for Boostnote": "Boostnote 설정", "Storage Locations": "저장소", diff --git a/locales/no.json b/locales/no.json index 2d6c92f54..66109a34b 100644 --- a/locales/no.json +++ b/locales/no.json @@ -18,6 +18,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "Print", "Your preferences for Boostnote": "Your preferences for Boostnote", "Storage Locations": "Storage Locations", diff --git a/locales/pl.json b/locales/pl.json index 68719aef0..577f46e68 100644 --- a/locales/pl.json +++ b/locales/pl.json @@ -19,6 +19,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "Drukuj", "Help": "Pomoc", "Your preferences for Boostnote": "Twoje ustawienia dla Boostnote", diff --git a/locales/pt-BR.json b/locales/pt-BR.json index 6b3126cce..6072b0236 100644 --- a/locales/pt-BR.json +++ b/locales/pt-BR.json @@ -18,6 +18,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "Imprimir", "Your preferences for Boostnote": "Suas preferências para o Boostnote", "Storage Locations": "Armazenamentos", diff --git a/locales/pt-PT.json b/locales/pt-PT.json index 774919a25..5beb18dd4 100644 --- a/locales/pt-PT.json +++ b/locales/pt-PT.json @@ -18,6 +18,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "Imprimir", "Your preferences for Boostnote": "As tuas definiçōes para Boostnote", "Storage Locations": "Locais de Armazenamento", diff --git a/locales/ru.json b/locales/ru.json index 793e15116..c4e9e1a20 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -18,6 +18,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "Print", "Your preferences for Boostnote": "Настройки Boostnote", "Storage Locations": "Хранилища", diff --git a/locales/sq.json b/locales/sq.json index e4cc01ac9..80f737a34 100644 --- a/locales/sq.json +++ b/locales/sq.json @@ -18,6 +18,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "Print", "Your preferences for Boostnote": "Your preferences for Boostnote", "Storage Locations": "Storage Locations", diff --git a/locales/th.json b/locales/th.json index 49d8e7cd7..358d49ab4 100644 --- a/locales/th.json +++ b/locales/th.json @@ -19,6 +19,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "พิมพ์", "Your preferences for Boostnote": "การตั้งค่าของคุณสำหรับ Boostnote", "Help": "ช่วยเหลือ", diff --git a/locales/tr.json b/locales/tr.json index 03a9791de..077fa1e4e 100644 --- a/locales/tr.json +++ b/locales/tr.json @@ -18,6 +18,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "Yazdır", "Your preferences for Boostnote": "Boostnote tercihleriniz", "Storage Locations": "Saklama Alanları", diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 2e12323e3..8e5537d26 100755 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -18,6 +18,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "打印", "Your preferences for Boostnote": "个性设置", "Storage Locations": "本地存储", diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 93a8afd51..add73073b 100755 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -18,6 +18,7 @@ ".md": ".md", ".txt": ".txt", ".html": ".html", + ".pdf": ".pdf", "Print": "列印", "Your preferences for Boostnote": "Boostnote 偏好設定", "Storage Locations": "儲存空間",