diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index a6819ce9..743b59a6 100755 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -208,6 +208,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) @@ -297,58 +298,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() + htmlContentFormatter (noteContent, exportTasks, targetDir) { + 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' + 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' + }) + }) + + 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() + }) }) }) - - let styles = '' - files.forEach(file => { - styles += `` - }) - - return ` - - - - - ${styles} - - ${body} - ` }) } @@ -490,6 +510,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) } @@ -527,6 +548,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 15535186..8fe0a855 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 3ed61eb7..cf3be072 100755 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -201,6 +201,10 @@ class MarkdownNoteDetail extends React.Component { ee.emit('export:save-html') } + exportAsPdf () { + ee.emit('export:save-pdf') + } + handleKeyDown (e) { switch (e.keyCode) { // tab key @@ -426,6 +430,7 @@ class MarkdownNoteDetail extends React.Component { exportAsHtml={this.exportAsHtml} exportAsMd={this.exportAsMd} exportAsTxt={this.exportAsTxt} + exportAsPdf={this.exportAsPdf} />
@@ -492,6 +497,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 11d8ac2a..80378793 100644 --- a/browser/main/Detail/SnippetNoteDetail.js +++ b/browser/main/Detail/SnippetNoteDetail.js @@ -657,6 +657,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] @@ -770,6 +771,7 @@ class SnippetNoteDetail extends React.Component { exportAsMd={this.showWarning} exportAsTxt={this.showWarning} exportAsHtml={this.showWarning} + exportAsPdf={this.showWarning} /> @@ -818,6 +820,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 9d62e717..e1816015 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -496,6 +496,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 771f77dc..8f15b147 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 b358e548..75c451c1 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 dcd85217..f20f1e90 100644 --- a/lib/main-menu.js +++ b/lib/main-menu.js @@ -141,6 +141,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 da5843f3..5d1a392b 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 1b90ab63..9177adec 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 fe7931da..831789c1 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 8b2da1b7..3bd2cb49 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 18bef679..8f702767 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 ea5a1c05..35d2f3c8 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 77bdb2ab..e76f06c9 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 05f454f3..69ddd380 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 e7295360..931dc4d1 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -22,6 +22,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 9a8bf8c7..59ffe7b9 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 2d6c92f5..66109a34 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 68719aef..577f46e6 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 273466eb..d4c75d46 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 774919a2..5beb18dd 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 793e1511..c4e9e1a2 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 e4cc01ac..80f737a3 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 49d8e7cd..358d49ab 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 03a9791d..077fa1e4 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 88a969b3..855c9abc 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 6e3066ad..310a9bbe 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": "儲存空間",