mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-17 19:51:42 +00:00
Compare commits
43 Commits
v0.16.0
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bfc56f2a80 | ||
|
|
789926bc76 | ||
|
|
006795b4d0 | ||
|
|
3e5d78d322 | ||
|
|
58c4a78be1 | ||
|
|
2603dfc1ed | ||
|
|
2df590600b | ||
|
|
ef20a8f3e5 | ||
|
|
3e405e1abf | ||
|
|
553832bdfa | ||
|
|
18d65d999a | ||
|
|
3b5eff582a | ||
|
|
85d09b3b3d | ||
|
|
8958e67fcf | ||
|
|
47b796909a | ||
|
|
67d76abdfa | ||
|
|
d75d68ba72 | ||
|
|
323be6b72d | ||
|
|
031a113338 | ||
|
|
b50c5386a6 | ||
|
|
65777b1d56 | ||
|
|
fe728874ac | ||
|
|
bd9b1306b1 | ||
|
|
0ca18d8ca5 | ||
|
|
87a530612f | ||
|
|
f4259bb4d0 | ||
|
|
aa8b589569 | ||
|
|
febc98c101 | ||
|
|
b678c3bd89 | ||
|
|
80b8948433 | ||
|
|
5414fe3384 | ||
|
|
db4016385d | ||
|
|
9d43e34cfa | ||
|
|
fa157f6f76 | ||
|
|
d6a54b8a26 | ||
|
|
9813412c8e | ||
|
|
d76b7235db | ||
|
|
418a789568 | ||
|
|
2d941c3ea3 | ||
|
|
e723d4cd59 | ||
|
|
9e770ef357 | ||
|
|
c796b3b30e | ||
|
|
168fe212f5 |
@@ -63,7 +63,7 @@ export default class CodeEditor extends React.Component {
|
|||||||
this.focusHandler = () => {
|
this.focusHandler = () => {
|
||||||
ipcRenderer.send('editor:focused', true)
|
ipcRenderer.send('editor:focused', true)
|
||||||
}
|
}
|
||||||
const debouncedDeletionOfAttachments = _.debounce(
|
this.debouncedDeletionOfAttachments = _.debounce(
|
||||||
attachmentManagement.deleteAttachmentsNotPresentInNote,
|
attachmentManagement.deleteAttachmentsNotPresentInNote,
|
||||||
30000
|
30000
|
||||||
)
|
)
|
||||||
@@ -80,7 +80,7 @@ export default class CodeEditor extends React.Component {
|
|||||||
this.props.onBlur != null && this.props.onBlur(e)
|
this.props.onBlur != null && this.props.onBlur(e)
|
||||||
const { storageKey, noteKey } = this.props
|
const { storageKey, noteKey } = this.props
|
||||||
if (this.props.deleteUnusedAttachments === true) {
|
if (this.props.deleteUnusedAttachments === true) {
|
||||||
debouncedDeletionOfAttachments(
|
this.debouncedDeletionOfAttachments(
|
||||||
this.editor.getValue(),
|
this.editor.getValue(),
|
||||||
storageKey,
|
storageKey,
|
||||||
noteKey
|
noteKey
|
||||||
@@ -810,6 +810,8 @@ export default class CodeEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleChange(editor, changeObject) {
|
handleChange(editor, changeObject) {
|
||||||
|
this.debouncedDeletionOfAttachments.cancel()
|
||||||
|
|
||||||
spellcheck.handleChange(editor, changeObject)
|
spellcheck.handleChange(editor, changeObject)
|
||||||
|
|
||||||
// The current note contains an toc. We'll check for changes on headlines.
|
// The current note contains an toc. We'll check for changes on headlines.
|
||||||
|
|||||||
@@ -323,6 +323,7 @@ class MarkdownEditor extends React.Component {
|
|||||||
storageKey,
|
storageKey,
|
||||||
noteKey,
|
noteKey,
|
||||||
linesHighlighted,
|
linesHighlighted,
|
||||||
|
getNote,
|
||||||
RTL
|
RTL
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
@@ -426,6 +427,8 @@ class MarkdownEditor extends React.Component {
|
|||||||
customCSS={config.preview.customCSS}
|
customCSS={config.preview.customCSS}
|
||||||
allowCustomCSS={config.preview.allowCustomCSS}
|
allowCustomCSS={config.preview.allowCustomCSS}
|
||||||
lineThroughCheckbox={config.preview.lineThroughCheckbox}
|
lineThroughCheckbox={config.preview.lineThroughCheckbox}
|
||||||
|
getNote={getNote}
|
||||||
|
export={config.export}
|
||||||
onDrop={e => this.handleDropImage(e)}
|
onDrop={e => this.handleDropImage(e)}
|
||||||
RTL={RTL}
|
RTL={RTL}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -18,258 +18,30 @@ import convertModeName from 'browser/lib/convertModeName'
|
|||||||
import copy from 'copy-to-clipboard'
|
import copy from 'copy-to-clipboard'
|
||||||
import mdurl from 'mdurl'
|
import mdurl from 'mdurl'
|
||||||
import exportNote from 'browser/main/lib/dataApi/exportNote'
|
import exportNote from 'browser/main/lib/dataApi/exportNote'
|
||||||
import { escapeHtmlCharacters } from 'browser/lib/utils'
|
import formatMarkdown from 'browser/main/lib/dataApi/formatMarkdown'
|
||||||
|
import formatHTML, {
|
||||||
|
CSS_FILES,
|
||||||
|
buildStyle,
|
||||||
|
getCodeThemeLink,
|
||||||
|
getStyleParams,
|
||||||
|
escapeHtmlCharactersInCodeTag
|
||||||
|
} from 'browser/main/lib/dataApi/formatHTML'
|
||||||
|
import formatPDF from 'browser/main/lib/dataApi/formatPDF'
|
||||||
import yaml from 'js-yaml'
|
import yaml from 'js-yaml'
|
||||||
|
import i18n from 'browser/lib/i18n'
|
||||||
|
import path from 'path'
|
||||||
|
import { remote, shell } from 'electron'
|
||||||
|
import attachmentManagement from '../main/lib/dataApi/attachmentManagement'
|
||||||
|
import filenamify from 'filenamify'
|
||||||
import { render } from 'react-dom'
|
import { render } from 'react-dom'
|
||||||
import Carousel from 'react-image-carousel'
|
import Carousel from 'react-image-carousel'
|
||||||
import { push } from 'connected-react-router'
|
import { push } from 'connected-react-router'
|
||||||
import ConfigManager from '../main/lib/ConfigManager'
|
import ConfigManager from '../main/lib/ConfigManager'
|
||||||
import uiThemes from 'browser/lib/ui-themes'
|
import uiThemes from 'browser/lib/ui-themes'
|
||||||
import i18n from 'browser/lib/i18n'
|
import { buildMarkdownPreviewContextMenu } from 'browser/lib/contextMenuBuilder'
|
||||||
|
|
||||||
const { remote, shell } = require('electron')
|
|
||||||
const attachmentManagement = require('../main/lib/dataApi/attachmentManagement')
|
|
||||||
const buildMarkdownPreviewContextMenu = require('browser/lib/contextMenuBuilder')
|
|
||||||
.buildMarkdownPreviewContextMenu
|
|
||||||
|
|
||||||
const { app } = remote
|
|
||||||
const path = require('path')
|
|
||||||
const fileUrl = require('file-url')
|
|
||||||
|
|
||||||
const dialog = remote.dialog
|
const dialog = remote.dialog
|
||||||
|
|
||||||
const markdownStyle = require('!!css!stylus?sourceMap!./markdown.styl')[0][1]
|
|
||||||
const appPath = fileUrl(
|
|
||||||
process.env.NODE_ENV === 'production' ? app.getAppPath() : path.resolve()
|
|
||||||
)
|
|
||||||
const CSS_FILES = [
|
|
||||||
`${appPath}/node_modules/katex/dist/katex.min.css`,
|
|
||||||
`${appPath}/node_modules/codemirror/lib/codemirror.css`,
|
|
||||||
`${appPath}/node_modules/react-image-carousel/lib/css/main.min.css`
|
|
||||||
]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Object} opts
|
|
||||||
* @param {String} opts.fontFamily
|
|
||||||
* @param {Numberl} opts.fontSize
|
|
||||||
* @param {String} opts.codeBlockFontFamily
|
|
||||||
* @param {String} opts.theme
|
|
||||||
* @param {Boolean} [opts.lineNumber] Should show line number
|
|
||||||
* @param {Boolean} [opts.scrollPastEnd]
|
|
||||||
* @param {Boolean} [opts.allowCustomCSS] Should add custom css
|
|
||||||
* @param {String} [opts.customCSS] Will be added to bottom, only if `opts.allowCustomCSS` is truthy
|
|
||||||
* @returns {String}
|
|
||||||
*/
|
|
||||||
function buildStyle(opts) {
|
|
||||||
const {
|
|
||||||
fontFamily,
|
|
||||||
fontSize,
|
|
||||||
codeBlockFontFamily,
|
|
||||||
lineNumber,
|
|
||||||
scrollPastEnd,
|
|
||||||
theme,
|
|
||||||
allowCustomCSS,
|
|
||||||
customCSS,
|
|
||||||
RTL
|
|
||||||
} = opts
|
|
||||||
return `
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Lato';
|
|
||||||
src: url('${appPath}/resources/fonts/Lato-Regular.woff2') format('woff2'), /* Modern Browsers */
|
|
||||||
url('${appPath}/resources/fonts/Lato-Regular.woff') format('woff'), /* Modern Browsers */
|
|
||||||
url('${appPath}/resources/fonts/Lato-Regular.ttf') format('truetype');
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: normal;
|
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Lato';
|
|
||||||
src: url('${appPath}/resources/fonts/Lato-Black.woff2') format('woff2'), /* Modern Browsers */
|
|
||||||
url('${appPath}/resources/fonts/Lato-Black.woff') format('woff'), /* Modern Browsers */
|
|
||||||
url('${appPath}/resources/fonts/Lato-Black.ttf') format('truetype');
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 700;
|
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Material Icons';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
src: local('Material Icons'),
|
|
||||||
local('MaterialIcons-Regular'),
|
|
||||||
url('${appPath}/resources/fonts/MaterialIcons-Regular.woff2') format('woff2'),
|
|
||||||
url('${appPath}/resources/fonts/MaterialIcons-Regular.woff') format('woff'),
|
|
||||||
url('${appPath}/resources/fonts/MaterialIcons-Regular.ttf') format('truetype');
|
|
||||||
}
|
|
||||||
|
|
||||||
${markdownStyle}
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-family: '${fontFamily.join("','")}';
|
|
||||||
font-size: ${fontSize}px;
|
|
||||||
|
|
||||||
${
|
|
||||||
scrollPastEnd
|
|
||||||
? `
|
|
||||||
padding-bottom: 90vh;
|
|
||||||
box-sizing: border-box;
|
|
||||||
`
|
|
||||||
: ''
|
|
||||||
}
|
|
||||||
${RTL ? 'direction: rtl;' : ''}
|
|
||||||
${RTL ? 'text-align: right;' : ''}
|
|
||||||
}
|
|
||||||
@media print {
|
|
||||||
body {
|
|
||||||
padding-bottom: initial;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
code {
|
|
||||||
font-family: '${codeBlockFontFamily.join("','")}';
|
|
||||||
background-color: rgba(0,0,0,0.04);
|
|
||||||
text-align: left;
|
|
||||||
direction: ltr;
|
|
||||||
}
|
|
||||||
|
|
||||||
p code,
|
|
||||||
li code,
|
|
||||||
td code
|
|
||||||
{
|
|
||||||
padding: 2px;
|
|
||||||
border-width: 1px;
|
|
||||||
border-style: solid;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
[data-theme="default"] p code,
|
|
||||||
[data-theme="default"] li code,
|
|
||||||
[data-theme="default"] td code
|
|
||||||
{
|
|
||||||
background-color: #F4F4F4;
|
|
||||||
border-color: #d9d9d9;
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
[data-theme="white"] p code,
|
|
||||||
[data-theme="white"] li code,
|
|
||||||
[data-theme="white"] td code
|
|
||||||
{
|
|
||||||
background-color: #F4F4F4;
|
|
||||||
border-color: #d9d9d9;
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
[data-theme="dark"] p code,
|
|
||||||
[data-theme="dark"] li code,
|
|
||||||
[data-theme="dark"] td code
|
|
||||||
{
|
|
||||||
background-color: #444444;
|
|
||||||
border-color: #555;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
[data-theme="dracula"] p code,
|
|
||||||
[data-theme="dracula"] li code,
|
|
||||||
[data-theme="dracula"] td code
|
|
||||||
{
|
|
||||||
background-color: #444444;
|
|
||||||
border-color: #555;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
[data-theme="monokai"] p code,
|
|
||||||
[data-theme="monokai"] li code,
|
|
||||||
[data-theme="monokai"] td code
|
|
||||||
{
|
|
||||||
background-color: #444444;
|
|
||||||
border-color: #555;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
[data-theme="nord"] p code,
|
|
||||||
[data-theme="nord"] li code,
|
|
||||||
[data-theme="nord"] td code
|
|
||||||
{
|
|
||||||
background-color: #444444;
|
|
||||||
border-color: #555;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
[data-theme="solarized-dark"] p code,
|
|
||||||
[data-theme="solarized-dark"] li code,
|
|
||||||
[data-theme="solarized-dark"] td code
|
|
||||||
{
|
|
||||||
background-color: #444444;
|
|
||||||
border-color: #555;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
[data-theme="vulcan"] p code,
|
|
||||||
[data-theme="vulcan"] li code,
|
|
||||||
[data-theme="vulcan"] td code
|
|
||||||
{
|
|
||||||
background-color: #444444;
|
|
||||||
border-color: #555;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lineNumber {
|
|
||||||
${lineNumber && 'display: block !important;'}
|
|
||||||
font-family: '${codeBlockFontFamily.join("','")}';
|
|
||||||
}
|
|
||||||
|
|
||||||
.clipboardButton {
|
|
||||||
color: rgba(147,147,149,0.8);;
|
|
||||||
fill: rgba(147,147,149,1);;
|
|
||||||
border-radius: 50%;
|
|
||||||
margin: 0px 10px;
|
|
||||||
border: none;
|
|
||||||
background-color: transparent;
|
|
||||||
outline: none;
|
|
||||||
height: 15px;
|
|
||||||
width: 15px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.clipboardButton:hover {
|
|
||||||
transition: 0.2s;
|
|
||||||
color: #939395;
|
|
||||||
fill: #939395;
|
|
||||||
background-color: rgba(0,0,0,0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
h1, h2 {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
margin: 1em 0 0.8em;
|
|
||||||
}
|
|
||||||
|
|
||||||
h4, h5, h6 {
|
|
||||||
margin: 1.1em 0 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
padding: 0.2em 0 0.2em;
|
|
||||||
margin: 1em 0 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
padding: 0.2em 0 0.2em;
|
|
||||||
margin: 1em 0 0.7em;
|
|
||||||
}
|
|
||||||
|
|
||||||
body p {
|
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media print {
|
|
||||||
body[data-theme="${theme}"] {
|
|
||||||
color: #000;
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
.clipboardButton {
|
|
||||||
display: none
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
${allowCustomCSS ? customCSS : ''}
|
|
||||||
`
|
|
||||||
}
|
|
||||||
|
|
||||||
const scrollBarStyle = `
|
const scrollBarStyle = `
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
${config.get().ui.showScrollBar ? '' : 'display: none;'}
|
${config.get().ui.showScrollBar ? '' : 'display: none;'}
|
||||||
@@ -301,22 +73,6 @@ const scrollBarDarkStyle = `
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const OSX = global.process.platform === 'darwin'
|
|
||||||
|
|
||||||
const defaultFontFamily = ['helvetica', 'arial', 'sans-serif']
|
|
||||||
if (!OSX) {
|
|
||||||
defaultFontFamily.unshift('Microsoft YaHei')
|
|
||||||
defaultFontFamily.unshift('meiryo')
|
|
||||||
}
|
|
||||||
const defaultCodeBlockFontFamily = [
|
|
||||||
'Monaco',
|
|
||||||
'Menlo',
|
|
||||||
'Ubuntu Mono',
|
|
||||||
'Consolas',
|
|
||||||
'source-code-pro',
|
|
||||||
'monospace'
|
|
||||||
]
|
|
||||||
|
|
||||||
// return the line number of the line that used to generate the specified element
|
// return the line number of the line that used to generate the specified element
|
||||||
// return -1 if the line is not found
|
// return -1 if the line is not found
|
||||||
function getSourceLineNumberByElement(element) {
|
function getSourceLineNumberByElement(element) {
|
||||||
@@ -430,94 +186,15 @@ class MarkdownPreview extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleSaveAsMd() {
|
handleSaveAsMd() {
|
||||||
this.exportAsDocument('md')
|
this.exportAsDocument('md', formatMarkdown(this.props))
|
||||||
}
|
|
||||||
|
|
||||||
htmlContentFormatter(noteContent, exportTasks, targetDir) {
|
|
||||||
const {
|
|
||||||
fontFamily,
|
|
||||||
fontSize,
|
|
||||||
codeBlockFontFamily,
|
|
||||||
lineNumber,
|
|
||||||
codeBlockTheme,
|
|
||||||
scrollPastEnd,
|
|
||||||
theme,
|
|
||||||
allowCustomCSS,
|
|
||||||
customCSS,
|
|
||||||
RTL
|
|
||||||
} = this.getStyleParams()
|
|
||||||
|
|
||||||
const inlineStyles = buildStyle({
|
|
||||||
fontFamily,
|
|
||||||
fontSize,
|
|
||||||
codeBlockFontFamily,
|
|
||||||
lineNumber,
|
|
||||||
scrollPastEnd,
|
|
||||||
theme,
|
|
||||||
allowCustomCSS,
|
|
||||||
customCSS,
|
|
||||||
RTL
|
|
||||||
})
|
|
||||||
let body = this.refs.root.contentWindow.document.body.innerHTML
|
|
||||||
body = attachmentManagement.fixLocalURLS(body, this.props.storagePath)
|
|
||||||
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 += `<link rel="stylesheet" href="../css/${path.basename(file)}">`
|
|
||||||
})
|
|
||||||
|
|
||||||
return `<html>
|
|
||||||
<head>
|
|
||||||
<base href="file://${targetDir}/">
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name = "viewport" content = "width = device-width, initial-scale = 1, maximum-scale = 1">
|
|
||||||
<style id="style">${inlineStyles}</style>
|
|
||||||
${styles}
|
|
||||||
</head>
|
|
||||||
<body>${body}</body>
|
|
||||||
</html>`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSaveAsHtml() {
|
handleSaveAsHtml() {
|
||||||
this.exportAsDocument('html', (noteContent, exportTasks, targetDir) =>
|
this.exportAsDocument('html', formatHTML(this.props))
|
||||||
Promise.resolve(
|
|
||||||
this.htmlContentFormatter(noteContent, exportTasks, targetDir)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSaveAsPdf() {
|
handleSaveAsPdf() {
|
||||||
this.exportAsDocument('pdf', (noteContent, exportTasks, targetDir) => {
|
this.exportAsDocument('pdf', formatPDF(this.props))
|
||||||
const printout = new remote.BrowserWindow({
|
|
||||||
show: false,
|
|
||||||
webPreferences: { webSecurity: false, javascript: 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()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePrint() {
|
handlePrint() {
|
||||||
@@ -525,18 +202,21 @@ class MarkdownPreview extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
exportAsDocument(fileType, contentFormatter) {
|
exportAsDocument(fileType, contentFormatter) {
|
||||||
|
const note = this.props.getNote()
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
|
defaultPath: filenamify(note.title, {
|
||||||
|
replacement: '_'
|
||||||
|
}),
|
||||||
filters: [{ name: 'Documents', extensions: [fileType] }],
|
filters: [{ name: 'Documents', extensions: [fileType] }],
|
||||||
properties: ['openFile', 'createDirectory']
|
properties: ['openFile', 'createDirectory']
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.showSaveDialog(remote.getCurrentWindow(), options, filename => {
|
dialog.showSaveDialog(remote.getCurrentWindow(), options, filename => {
|
||||||
if (filename) {
|
if (filename) {
|
||||||
const content = this.props.value
|
const storagePath = this.props.storagePath
|
||||||
const storage = this.props.storagePath
|
|
||||||
const nodeKey = this.props.noteKey
|
|
||||||
|
|
||||||
exportNote(nodeKey, storage, content, filename, contentFormatter)
|
exportNote(storagePath, note, filename, contentFormatter)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
dialog.showMessageBox(remote.getCurrentWindow(), {
|
dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||||
type: 'info',
|
type: 'info',
|
||||||
@@ -567,32 +247,6 @@ class MarkdownPreview extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @description Convert special characters between three ```
|
|
||||||
* @param {string[]} splitWithCodeTag Array of HTML strings separated by three ```
|
|
||||||
* @returns {string} HTML in which special characters between three ``` have been converted
|
|
||||||
*/
|
|
||||||
escapeHtmlCharactersInCodeTag(splitWithCodeTag) {
|
|
||||||
for (let index = 0; index < splitWithCodeTag.length; index++) {
|
|
||||||
const codeTagRequired =
|
|
||||||
splitWithCodeTag[index] !== '```' && index < splitWithCodeTag.length - 1
|
|
||||||
if (codeTagRequired) {
|
|
||||||
splitWithCodeTag.splice(index + 1, 0, '```')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let inCodeTag = false
|
|
||||||
let result = ''
|
|
||||||
for (let content of splitWithCodeTag) {
|
|
||||||
if (content === '```') {
|
|
||||||
inCodeTag = !inCodeTag
|
|
||||||
} else if (inCodeTag) {
|
|
||||||
content = escapeHtmlCharacters(content)
|
|
||||||
}
|
|
||||||
result += content
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
getScrollBarStyle() {
|
getScrollBarStyle() {
|
||||||
const { theme } = this.props
|
const { theme } = this.props
|
||||||
|
|
||||||
@@ -743,47 +397,6 @@ class MarkdownPreview extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getStyleParams() {
|
|
||||||
const {
|
|
||||||
fontSize,
|
|
||||||
lineNumber,
|
|
||||||
codeBlockTheme,
|
|
||||||
scrollPastEnd,
|
|
||||||
theme,
|
|
||||||
allowCustomCSS,
|
|
||||||
customCSS,
|
|
||||||
RTL
|
|
||||||
} = this.props
|
|
||||||
let { fontFamily, codeBlockFontFamily } = this.props
|
|
||||||
fontFamily =
|
|
||||||
_.isString(fontFamily) && fontFamily.trim().length > 0
|
|
||||||
? fontFamily
|
|
||||||
.split(',')
|
|
||||||
.map(fontName => fontName.trim())
|
|
||||||
.concat(defaultFontFamily)
|
|
||||||
: defaultFontFamily
|
|
||||||
codeBlockFontFamily =
|
|
||||||
_.isString(codeBlockFontFamily) && codeBlockFontFamily.trim().length > 0
|
|
||||||
? codeBlockFontFamily
|
|
||||||
.split(',')
|
|
||||||
.map(fontName => fontName.trim())
|
|
||||||
.concat(defaultCodeBlockFontFamily)
|
|
||||||
: defaultCodeBlockFontFamily
|
|
||||||
|
|
||||||
return {
|
|
||||||
fontFamily,
|
|
||||||
fontSize,
|
|
||||||
codeBlockFontFamily,
|
|
||||||
lineNumber,
|
|
||||||
codeBlockTheme,
|
|
||||||
scrollPastEnd,
|
|
||||||
theme,
|
|
||||||
allowCustomCSS,
|
|
||||||
customCSS,
|
|
||||||
RTL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
applyStyle() {
|
applyStyle() {
|
||||||
const {
|
const {
|
||||||
fontFamily,
|
fontFamily,
|
||||||
@@ -796,12 +409,13 @@ class MarkdownPreview extends React.Component {
|
|||||||
allowCustomCSS,
|
allowCustomCSS,
|
||||||
customCSS,
|
customCSS,
|
||||||
RTL
|
RTL
|
||||||
} = this.getStyleParams()
|
} = getStyleParams(this.props)
|
||||||
|
|
||||||
this.getWindow().document.getElementById(
|
this.getWindow().document.getElementById(
|
||||||
'codeTheme'
|
'codeTheme'
|
||||||
).href = this.getCodeThemeLink(codeBlockTheme)
|
).href = getCodeThemeLink(codeBlockTheme)
|
||||||
this.getWindow().document.getElementById('style').innerHTML = buildStyle({
|
|
||||||
|
this.getWindow().document.getElementById('style').innerHTML = buildStyle(
|
||||||
fontFamily,
|
fontFamily,
|
||||||
fontSize,
|
fontSize,
|
||||||
codeBlockFontFamily,
|
codeBlockFontFamily,
|
||||||
@@ -811,15 +425,7 @@ class MarkdownPreview extends React.Component {
|
|||||||
allowCustomCSS,
|
allowCustomCSS,
|
||||||
customCSS,
|
customCSS,
|
||||||
RTL
|
RTL
|
||||||
})
|
)
|
||||||
}
|
|
||||||
|
|
||||||
getCodeThemeLink(name) {
|
|
||||||
const theme = consts.THEMES.find(theme => theme.name === name)
|
|
||||||
|
|
||||||
return theme != null
|
|
||||||
? theme.path
|
|
||||||
: `${appPath}/node_modules/codemirror/theme/elegant.css`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rewriteIframe() {
|
rewriteIframe() {
|
||||||
@@ -853,7 +459,7 @@ class MarkdownPreview extends React.Component {
|
|||||||
this.refs.root.contentWindow.document.body.setAttribute('data-theme', theme)
|
this.refs.root.contentWindow.document.body.setAttribute('data-theme', theme)
|
||||||
if (sanitize === 'NONE') {
|
if (sanitize === 'NONE') {
|
||||||
const splitWithCodeTag = value.split('```')
|
const splitWithCodeTag = value.split('```')
|
||||||
value = this.escapeHtmlCharactersInCodeTag(splitWithCodeTag)
|
value = escapeHtmlCharactersInCodeTag(splitWithCodeTag)
|
||||||
}
|
}
|
||||||
const renderedHTML = this.markdown.render(value)
|
const renderedHTML = this.markdown.render(value)
|
||||||
attachmentManagement.migrateAttachments(value, storagePath, noteKey)
|
attachmentManagement.migrateAttachments(value, storagePath, noteKey)
|
||||||
@@ -916,13 +522,9 @@ class MarkdownPreview extends React.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const opts = {}
|
const opts = {}
|
||||||
// if (this.props.theme === 'dark') {
|
|
||||||
// opts['font-color'] = '#DDD'
|
|
||||||
// opts['line-color'] = '#DDD'
|
|
||||||
// opts['element-color'] = '#DDD'
|
|
||||||
// opts['fill'] = '#3A404C'
|
|
||||||
// }
|
|
||||||
_.forEach(
|
_.forEach(
|
||||||
this.refs.root.contentWindow.document.querySelectorAll('.flowchart'),
|
this.refs.root.contentWindow.document.querySelectorAll('.flowchart'),
|
||||||
el => {
|
el => {
|
||||||
|
|||||||
@@ -336,6 +336,7 @@ class MarkdownSplitEditor extends React.Component {
|
|||||||
storageKey,
|
storageKey,
|
||||||
noteKey,
|
noteKey,
|
||||||
linesHighlighted,
|
linesHighlighted,
|
||||||
|
getNote,
|
||||||
isStacking,
|
isStacking,
|
||||||
RTL
|
RTL
|
||||||
} = this.props
|
} = this.props
|
||||||
@@ -470,6 +471,7 @@ class MarkdownSplitEditor extends React.Component {
|
|||||||
codeBlockTheme={config.preview.codeBlockTheme}
|
codeBlockTheme={config.preview.codeBlockTheme}
|
||||||
codeBlockFontFamily={config.editor.fontFamily}
|
codeBlockFontFamily={config.editor.fontFamily}
|
||||||
lineNumber={config.preview.lineNumber}
|
lineNumber={config.preview.lineNumber}
|
||||||
|
indentSize={editorIndentSize}
|
||||||
scrollPastEnd={config.preview.scrollPastEnd}
|
scrollPastEnd={config.preview.scrollPastEnd}
|
||||||
smartQuotes={config.preview.smartQuotes}
|
smartQuotes={config.preview.smartQuotes}
|
||||||
smartArrows={config.preview.smartArrows}
|
smartArrows={config.preview.smartArrows}
|
||||||
@@ -486,6 +488,8 @@ class MarkdownSplitEditor extends React.Component {
|
|||||||
customCSS={config.preview.customCSS}
|
customCSS={config.preview.customCSS}
|
||||||
allowCustomCSS={config.preview.allowCustomCSS}
|
allowCustomCSS={config.preview.allowCustomCSS}
|
||||||
lineThroughCheckbox={config.preview.lineThroughCheckbox}
|
lineThroughCheckbox={config.preview.lineThroughCheckbox}
|
||||||
|
getNote={getNote}
|
||||||
|
export={config.export}
|
||||||
RTL={RTL}
|
RTL={RTL}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import markdownItTocAndAnchor from '@hikerpig/markdown-it-toc-and-anchor'
|
|||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import ConfigManager from 'browser/main/lib/ConfigManager'
|
import ConfigManager from 'browser/main/lib/ConfigManager'
|
||||||
import katex from 'katex'
|
import katex from 'katex'
|
||||||
import { lastFindInArray } from './utils'
|
import { escapeHtmlCharacters, lastFindInArray } from './utils'
|
||||||
|
|
||||||
function createGutter(str, firstLineNumber) {
|
function createGutter(str, firstLineNumber) {
|
||||||
if (Number.isNaN(firstLineNumber)) firstLineNumber = 1
|
if (Number.isNaN(firstLineNumber)) firstLineNumber = 1
|
||||||
@@ -31,7 +31,8 @@ class Markdown {
|
|||||||
html: true,
|
html: true,
|
||||||
xhtmlOut: true,
|
xhtmlOut: true,
|
||||||
breaks: config.preview.breaks,
|
breaks: config.preview.breaks,
|
||||||
sanitize: 'STRICT'
|
sanitize: 'STRICT',
|
||||||
|
onFence: () => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedOptions = Object.assign(defaultOptions, options)
|
const updatedOptions = Object.assign(defaultOptions, options)
|
||||||
@@ -266,6 +267,8 @@ class Markdown {
|
|||||||
token.parameters.format = 'yaml'
|
token.parameters.format = 'yaml'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updatedOptions.onFence('chart', token.parameters.format)
|
||||||
|
|
||||||
return `<pre class="fence" data-line="${token.map[0]}">
|
return `<pre class="fence" data-line="${token.map[0]}">
|
||||||
<span class="filename">${token.fileName}</span>
|
<span class="filename">${token.fileName}</span>
|
||||||
<div class="chart" data-height="${
|
<div class="chart" data-height="${
|
||||||
@@ -276,6 +279,8 @@ class Markdown {
|
|||||||
</pre>`
|
</pre>`
|
||||||
},
|
},
|
||||||
flowchart: token => {
|
flowchart: token => {
|
||||||
|
updatedOptions.onFence('flowchart')
|
||||||
|
|
||||||
return `<pre class="fence" data-line="${token.map[0]}">
|
return `<pre class="fence" data-line="${token.map[0]}">
|
||||||
<span class="filename">${token.fileName}</span>
|
<span class="filename">${token.fileName}</span>
|
||||||
<div class="flowchart" data-height="${token.parameters.height}">${
|
<div class="flowchart" data-height="${token.parameters.height}">${
|
||||||
@@ -305,6 +310,8 @@ class Markdown {
|
|||||||
</pre>`
|
</pre>`
|
||||||
},
|
},
|
||||||
mermaid: token => {
|
mermaid: token => {
|
||||||
|
updatedOptions.onFence('mermaid')
|
||||||
|
|
||||||
return `<pre class="fence" data-line="${token.map[0]}">
|
return `<pre class="fence" data-line="${token.map[0]}">
|
||||||
<span class="filename">${token.fileName}</span>
|
<span class="filename">${token.fileName}</span>
|
||||||
<div class="mermaid" data-height="${token.parameters.height}">${
|
<div class="mermaid" data-height="${token.parameters.height}">${
|
||||||
@@ -313,6 +320,8 @@ class Markdown {
|
|||||||
</pre>`
|
</pre>`
|
||||||
},
|
},
|
||||||
sequence: token => {
|
sequence: token => {
|
||||||
|
updatedOptions.onFence('sequence')
|
||||||
|
|
||||||
return `<pre class="fence" data-line="${token.map[0]}">
|
return `<pre class="fence" data-line="${token.map[0]}">
|
||||||
<span class="filename">${token.fileName}</span>
|
<span class="filename">${token.fileName}</span>
|
||||||
<div class="sequence" data-height="${token.parameters.height}">${
|
<div class="sequence" data-height="${token.parameters.height}">${
|
||||||
@@ -322,6 +331,8 @@ class Markdown {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
token => {
|
token => {
|
||||||
|
updatedOptions.onFence('code', token.langType)
|
||||||
|
|
||||||
return `<pre class="code CodeMirror" data-line="${token.map[0]}">
|
return `<pre class="code CodeMirror" data-line="${token.map[0]}">
|
||||||
<span class="filename">${token.fileName}</span>
|
<span class="filename">${token.fileName}</span>
|
||||||
${createGutter(token.content, token.firstLineNumber)}
|
${createGutter(token.content, token.firstLineNumber)}
|
||||||
@@ -468,6 +479,16 @@ class Markdown {
|
|||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.md.renderer.rules.code_inline = function(tokens, idx) {
|
||||||
|
const token = tokens[idx]
|
||||||
|
|
||||||
|
return (
|
||||||
|
'<code class="inline">' +
|
||||||
|
escapeHtmlCharacters(token.content) +
|
||||||
|
'</code>'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (config.preview.smartArrows) {
|
if (config.preview.smartArrows) {
|
||||||
this.md.use(smartArrows)
|
this.md.use(smartArrows)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,10 +57,11 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
|
|
||||||
this.dispatchTimer = null
|
this.dispatchTimer = null
|
||||||
|
|
||||||
this.toggleLockButton = this.handleToggleLockButton.bind(this)
|
|
||||||
this.generateToc = this.handleGenerateToc.bind(this)
|
this.generateToc = this.handleGenerateToc.bind(this)
|
||||||
|
this.toggleLockButton = this.handleToggleLockButton.bind(this)
|
||||||
this.handleUpdateContent = this.handleUpdateContent.bind(this)
|
this.handleUpdateContent = this.handleUpdateContent.bind(this)
|
||||||
this.handleSwitchStackDirection = this.handleSwitchStackDirection.bind(this)
|
this.handleSwitchStackDirection = this.handleSwitchStackDirection.bind(this)
|
||||||
|
this.getNote = this.getNote.bind(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
focus() {
|
focus() {
|
||||||
@@ -441,6 +442,10 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
this.updateNote(note)
|
this.updateNote(note)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getNote() {
|
||||||
|
return this.state.note
|
||||||
|
}
|
||||||
|
|
||||||
renderEditor() {
|
renderEditor() {
|
||||||
const { config, ignorePreviewPointerEvents } = this.props
|
const { config, ignorePreviewPointerEvents } = this.props
|
||||||
const { note, isStacking } = this.state
|
const { note, isStacking } = this.state
|
||||||
@@ -456,8 +461,8 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
noteKey={note.key}
|
noteKey={note.key}
|
||||||
linesHighlighted={note.linesHighlighted}
|
linesHighlighted={note.linesHighlighted}
|
||||||
onChange={this.handleUpdateContent}
|
onChange={this.handleUpdateContent}
|
||||||
isLocked={this.state.isLocked}
|
|
||||||
ignorePreviewPointerEvents={ignorePreviewPointerEvents}
|
ignorePreviewPointerEvents={ignorePreviewPointerEvents}
|
||||||
|
getNote={this.getNote}
|
||||||
RTL={config.editor.rtlEnabled && this.state.RTL}
|
RTL={config.editor.rtlEnabled && this.state.RTL}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@@ -473,6 +478,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
linesHighlighted={note.linesHighlighted}
|
linesHighlighted={note.linesHighlighted}
|
||||||
onChange={this.handleUpdateContent}
|
onChange={this.handleUpdateContent}
|
||||||
ignorePreviewPointerEvents={ignorePreviewPointerEvents}
|
ignorePreviewPointerEvents={ignorePreviewPointerEvents}
|
||||||
|
getNote={this.getNote}
|
||||||
RTL={config.editor.rtlEnabled && this.state.RTL}
|
RTL={config.editor.rtlEnabled && this.state.RTL}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { getLocales } from 'browser/lib/Languages'
|
|||||||
import applyShortcuts from 'browser/main/lib/shortcutManager'
|
import applyShortcuts from 'browser/main/lib/shortcutManager'
|
||||||
import { chooseTheme, applyTheme } from 'browser/main/lib/ThemeManager'
|
import { chooseTheme, applyTheme } from 'browser/main/lib/ThemeManager'
|
||||||
import { push } from 'connected-react-router'
|
import { push } from 'connected-react-router'
|
||||||
|
import { ipcRenderer } from 'electron'
|
||||||
|
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
@@ -184,6 +185,7 @@ class Main extends React.Component {
|
|||||||
this.toggleMenuBarVisible.bind(this)
|
this.toggleMenuBarVisible.bind(this)
|
||||||
)
|
)
|
||||||
eventEmitter.on('dispatch:push', this.changeRoutePush.bind(this))
|
eventEmitter.on('dispatch:push', this.changeRoutePush.bind(this))
|
||||||
|
eventEmitter.on('update', () => ipcRenderer.send('update-check', 'manual'))
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import Markdown from '../../lib/markdown'
|
|||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
import { confirmDeleteNote } from 'browser/lib/confirmDeleteNote'
|
import { confirmDeleteNote } from 'browser/lib/confirmDeleteNote'
|
||||||
import context from 'browser/lib/context'
|
import context from 'browser/lib/context'
|
||||||
|
import filenamify from 'filenamify'
|
||||||
import queryString from 'query-string'
|
import queryString from 'query-string'
|
||||||
|
|
||||||
const { remote } = require('electron')
|
const { remote } = require('electron')
|
||||||
@@ -634,6 +635,38 @@ class NoteList extends React.Component {
|
|||||||
this.selectNextNote()
|
this.selectNextNote()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleExportClick(e, note, fileType) {
|
||||||
|
const options = {
|
||||||
|
defaultPath: filenamify(note.title, {
|
||||||
|
replacement: '_'
|
||||||
|
}),
|
||||||
|
filters: [{ name: 'Documents', extensions: [fileType] }],
|
||||||
|
properties: ['openFile', 'createDirectory']
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.showSaveDialog(remote.getCurrentWindow(), options, filename => {
|
||||||
|
if (filename) {
|
||||||
|
const { config } = this.props
|
||||||
|
|
||||||
|
dataApi
|
||||||
|
.exportNoteAs(note, filename, fileType, config)
|
||||||
|
.then(res => {
|
||||||
|
dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||||
|
type: 'info',
|
||||||
|
message: `Exported to ${filename}`
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
dialog.showErrorBox(
|
||||||
|
'Export error',
|
||||||
|
err ? err.message || err : 'Unexpected error during export'
|
||||||
|
)
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
handleNoteContextMenu(e, uniqueKey) {
|
handleNoteContextMenu(e, uniqueKey) {
|
||||||
const { location } = this.props
|
const { location } = this.props
|
||||||
const { selectedNoteKeys } = this.state
|
const { selectedNoteKeys } = this.state
|
||||||
@@ -689,9 +722,40 @@ class NoteList extends React.Component {
|
|||||||
click: this.copyNoteLink.bind(this, note)
|
click: this.copyNoteLink.bind(this, note)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if (note.type === 'MARKDOWN_NOTE') {
|
if (note.type === 'MARKDOWN_NOTE') {
|
||||||
|
templates.push(
|
||||||
|
{
|
||||||
|
type: 'separator'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.__('Export Note'),
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
label: i18n.__('Export as Plain Text (.txt)'),
|
||||||
|
click: e => this.handleExportClick(e, note, 'txt')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.__('Export as Markdown (.md)'),
|
||||||
|
click: e => this.handleExportClick(e, note, 'md')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.__('Export as HTML (.html)'),
|
||||||
|
click: e => this.handleExportClick(e, note, 'html')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.__('Export as PDF (.pdf)'),
|
||||||
|
click: e => this.handleExportClick(e, note, 'pdf')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
if (note.blog && note.blog.blogLink && note.blog.blogId) {
|
if (note.blog && note.blog.blogLink && note.blog.blogId) {
|
||||||
templates.push(
|
templates.push(
|
||||||
|
{
|
||||||
|
type: 'separator'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: updateLabel,
|
label: updateLabel,
|
||||||
click: this.publishMarkdown.bind(this)
|
click: this.publishMarkdown.bind(this)
|
||||||
@@ -702,10 +766,15 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
templates.push({
|
templates.push(
|
||||||
|
{
|
||||||
|
type: 'separator'
|
||||||
|
},
|
||||||
|
{
|
||||||
label: publishLabel,
|
label: publishLabel,
|
||||||
click: this.publishMarkdown.bind(this)
|
click: this.publishMarkdown.bind(this)
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,12 +43,20 @@ class StorageItem extends React.Component {
|
|||||||
label: i18n.__('Export Storage'),
|
label: i18n.__('Export Storage'),
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
label: i18n.__('Export as txt'),
|
label: i18n.__('Export as Plain Text (.txt)'),
|
||||||
click: e => this.handleExportStorageClick(e, 'txt')
|
click: e => this.handleExportStorageClick(e, 'txt')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: i18n.__('Export as md'),
|
label: i18n.__('Export as Markdown (.md)'),
|
||||||
click: e => this.handleExportStorageClick(e, 'md')
|
click: e => this.handleExportStorageClick(e, 'md')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.__('Export as HTML (.html)'),
|
||||||
|
click: e => this.handleExportStorageClick(e, 'html')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.__('Export as PDF (.pdf)'),
|
||||||
|
click: e => this.handleExportStorageClick(e, 'pdf')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -97,14 +105,28 @@ class StorageItem extends React.Component {
|
|||||||
}
|
}
|
||||||
dialog.showOpenDialog(remote.getCurrentWindow(), options, paths => {
|
dialog.showOpenDialog(remote.getCurrentWindow(), options, paths => {
|
||||||
if (paths && paths.length === 1) {
|
if (paths && paths.length === 1) {
|
||||||
const { storage, dispatch } = this.props
|
const { storage, dispatch, config } = this.props
|
||||||
dataApi.exportStorage(storage.key, fileType, paths[0]).then(data => {
|
dataApi
|
||||||
|
.exportStorage(storage.key, fileType, paths[0], config)
|
||||||
|
.then(data => {
|
||||||
|
dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||||
|
type: 'info',
|
||||||
|
message: `Exported to ${paths[0]}`
|
||||||
|
})
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'EXPORT_STORAGE',
|
type: 'EXPORT_STORAGE',
|
||||||
storage: data.storage,
|
storage: data.storage,
|
||||||
fileType: data.fileType
|
fileType: data.fileType
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
.catch(error => {
|
||||||
|
dialog.showErrorBox(
|
||||||
|
'Export error',
|
||||||
|
error ? error.message || error : 'Unexpected error during export'
|
||||||
|
)
|
||||||
|
throw error
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -166,12 +188,20 @@ class StorageItem extends React.Component {
|
|||||||
label: i18n.__('Export Folder'),
|
label: i18n.__('Export Folder'),
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
label: i18n.__('Export as txt'),
|
label: i18n.__('Export as Plain Text (.txt)'),
|
||||||
click: e => this.handleExportFolderClick(e, folder, 'txt')
|
click: e => this.handleExportFolderClick(e, folder, 'txt')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: i18n.__('Export as md'),
|
label: i18n.__('Export as Markdown (.md)'),
|
||||||
click: e => this.handleExportFolderClick(e, folder, 'md')
|
click: e => this.handleExportFolderClick(e, folder, 'md')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.__('Export as HTML (.html)'),
|
||||||
|
click: e => this.handleExportFolderClick(e, folder, 'html')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.__('Export as PDF (.pdf)'),
|
||||||
|
click: e => this.handleExportFolderClick(e, folder, 'pdf')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -202,30 +232,28 @@ class StorageItem extends React.Component {
|
|||||||
}
|
}
|
||||||
dialog.showOpenDialog(remote.getCurrentWindow(), options, paths => {
|
dialog.showOpenDialog(remote.getCurrentWindow(), options, paths => {
|
||||||
if (paths && paths.length === 1) {
|
if (paths && paths.length === 1) {
|
||||||
const { storage, dispatch } = this.props
|
const { storage, dispatch, config } = this.props
|
||||||
dataApi
|
dataApi
|
||||||
.exportFolder(storage.key, folder.key, fileType, paths[0])
|
.exportFolder(storage.key, folder.key, fileType, paths[0], config)
|
||||||
.then(data => {
|
.then(data => {
|
||||||
|
dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||||
|
type: 'info',
|
||||||
|
message: `Exported to ${paths[0]}`
|
||||||
|
})
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'EXPORT_FOLDER',
|
type: 'EXPORT_FOLDER',
|
||||||
storage: data.storage,
|
storage: data.storage,
|
||||||
folderKey: data.folderKey,
|
folderKey: data.folderKey,
|
||||||
fileType: data.fileType
|
fileType: data.fileType
|
||||||
})
|
})
|
||||||
return data
|
|
||||||
})
|
})
|
||||||
.then(data => {
|
.catch(error => {
|
||||||
dialog.showMessageBox(remote.getCurrentWindow(), {
|
|
||||||
type: 'info',
|
|
||||||
message: 'Exported to "' + data.exportDir + '"'
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
dialog.showErrorBox(
|
dialog.showErrorBox(
|
||||||
'Export error',
|
'Export error',
|
||||||
err ? err.message || err : 'Unexpected error during export'
|
error ? error.message || error : 'Unexpected error during export'
|
||||||
)
|
)
|
||||||
throw err
|
throw error
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import { confirmDeleteNote } from 'browser/lib/confirmDeleteNote'
|
|||||||
import ColorPicker from 'browser/components/ColorPicker'
|
import ColorPicker from 'browser/components/ColorPicker'
|
||||||
import { every, sortBy } from 'lodash'
|
import { every, sortBy } from 'lodash'
|
||||||
|
|
||||||
|
const { dialog } = remote
|
||||||
|
|
||||||
function matchActiveTags(tags, activeTags) {
|
function matchActiveTags(tags, activeTags) {
|
||||||
return every(activeTags, v => tags.indexOf(v) >= 0)
|
return every(activeTags, v => tags.indexOf(v) >= 0)
|
||||||
}
|
}
|
||||||
@@ -63,15 +65,12 @@ class SideNav extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deleteTag(tag) {
|
deleteTag(tag) {
|
||||||
const selectedButton = remote.dialog.showMessageBox(
|
const selectedButton = dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||||
remote.getCurrentWindow(),
|
|
||||||
{
|
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
message: i18n.__('Confirm tag deletion'),
|
message: i18n.__('Confirm tag deletion'),
|
||||||
detail: i18n.__('This will permanently remove this tag.'),
|
detail: i18n.__('This will permanently remove this tag.'),
|
||||||
buttons: [i18n.__('Confirm'), i18n.__('Cancel')]
|
buttons: [i18n.__('Confirm'), i18n.__('Cancel')]
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
|
||||||
if (selectedButton === 0) {
|
if (selectedButton === 0) {
|
||||||
const {
|
const {
|
||||||
@@ -155,28 +154,80 @@ class SideNav extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleTagContextMenu(e, tag) {
|
handleTagContextMenu(e, tag) {
|
||||||
const menu = []
|
context.popup([
|
||||||
|
{
|
||||||
menu.push({
|
label: i18n.__('Rename Tag'),
|
||||||
label: i18n.__('Delete Tag'),
|
click: this.handleRenameTagClick.bind(this, tag)
|
||||||
click: this.deleteTag.bind(this, tag)
|
},
|
||||||
})
|
{
|
||||||
|
|
||||||
menu.push({
|
|
||||||
label: i18n.__('Customize Color'),
|
label: i18n.__('Customize Color'),
|
||||||
click: this.displayColorPicker.bind(
|
click: this.displayColorPicker.bind(
|
||||||
this,
|
this,
|
||||||
tag,
|
tag,
|
||||||
e.target.getBoundingClientRect()
|
e.target.getBoundingClientRect()
|
||||||
)
|
)
|
||||||
})
|
},
|
||||||
|
{
|
||||||
|
type: 'separator'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.__('Export Tag'),
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
label: i18n.__('Export as Plain Text (.txt)'),
|
||||||
|
click: e => this.handleExportTagClick(e, tag, 'txt')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.__('Export as Markdown (.md)'),
|
||||||
|
click: e => this.handleExportTagClick(e, tag, 'md')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.__('Export as HTML (.html)'),
|
||||||
|
click: e => this.handleExportTagClick(e, tag, 'html')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.__('Export as PDF (.pdf)'),
|
||||||
|
click: e => this.handleExportTagClick(e, tag, 'pdf')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'separator'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.__('Delete Tag'),
|
||||||
|
click: this.deleteTag.bind(this, tag)
|
||||||
|
}
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
menu.push({
|
handleExportTagClick(e, tag, fileType) {
|
||||||
label: i18n.__('Rename Tag'),
|
const options = {
|
||||||
click: this.handleRenameTagClick.bind(this, tag)
|
properties: ['openDirectory', 'createDirectory'],
|
||||||
|
buttonLabel: i18n.__('Select directory'),
|
||||||
|
title: i18n.__('Select a folder to export the files to'),
|
||||||
|
multiSelections: false
|
||||||
|
}
|
||||||
|
dialog.showOpenDialog(remote.getCurrentWindow(), options, paths => {
|
||||||
|
if (paths && paths.length === 1) {
|
||||||
|
const { data, config } = this.props
|
||||||
|
dataApi
|
||||||
|
.exportTag(data, tag, fileType, paths[0], config)
|
||||||
|
.then(data => {
|
||||||
|
dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||||
|
type: 'info',
|
||||||
|
message: `Exported to ${paths[0]}`
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
dialog.showErrorBox(
|
||||||
|
'Export error',
|
||||||
|
error ? error.message || error : 'Unexpected error during export'
|
||||||
|
)
|
||||||
|
throw error
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
context.popup(menu)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dismissColorPicker() {
|
dismissColorPicker() {
|
||||||
@@ -330,6 +381,7 @@ class SideNav extends React.Component {
|
|||||||
dispatch={dispatch}
|
dispatch={dispatch}
|
||||||
onSortEnd={this.onSortEnd.bind(this)(storage)}
|
onSortEnd={this.onSortEnd.bind(this)(storage)}
|
||||||
useDragHandle
|
useDragHandle
|
||||||
|
config={config}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import DevTools from './DevTools'
|
|||||||
require('./lib/ipcClient')
|
require('./lib/ipcClient')
|
||||||
require('../lib/customMeta')
|
require('../lib/customMeta')
|
||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
|
import ConfigManager from './lib/ConfigManager'
|
||||||
|
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
|
|
||||||
@@ -107,6 +108,22 @@ function updateApp() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function downloadUpdate() {
|
||||||
|
const index = dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||||
|
type: 'warning',
|
||||||
|
message: i18n.__('Update Boostnote'),
|
||||||
|
detail: i18n.__('New Boostnote is ready to be downloaded.'),
|
||||||
|
buttons: [i18n.__('Download now'), i18n.__('Ignore updates')]
|
||||||
|
})
|
||||||
|
|
||||||
|
if (index === 0) {
|
||||||
|
ipcRenderer.send('update-download-confirm')
|
||||||
|
} else if (index === 1) {
|
||||||
|
ipcRenderer.send('update-cancel')
|
||||||
|
ConfigManager.set({ autoUpdateEnabled: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<ConnectedRouter history={history}>
|
<ConnectedRouter history={history}>
|
||||||
@@ -147,8 +164,12 @@ ReactDOM.render(
|
|||||||
})
|
})
|
||||||
|
|
||||||
ipcRenderer.on('update-found', function() {
|
ipcRenderer.on('update-found', function() {
|
||||||
notify('Update found!', {
|
downloadUpdate()
|
||||||
body: 'Preparing to update...'
|
})
|
||||||
|
|
||||||
|
ipcRenderer.on('update-not-found', function(_, msg) {
|
||||||
|
notify('Update not found!', {
|
||||||
|
body: msg
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ const DEFAULT_MARKDOWN_LINT_CONFIG = `{
|
|||||||
|
|
||||||
const DEFAULT_CSS_CONFIG = `
|
const DEFAULT_CSS_CONFIG = `
|
||||||
/* Drop Your Custom CSS Code Here */
|
/* Drop Your Custom CSS Code Here */
|
||||||
[data-theme="default"] p code,
|
[data-theme="default"] p code.inline,
|
||||||
[data-theme="default"] li code,
|
[data-theme="default"] li code.inline,
|
||||||
[data-theme="default"] td code
|
[data-theme="default"] td code.inline
|
||||||
{
|
{
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
@@ -144,6 +144,11 @@ export const DEFAULT_CONFIG = {
|
|||||||
username: '',
|
username: '',
|
||||||
password: ''
|
password: ''
|
||||||
},
|
},
|
||||||
|
export: {
|
||||||
|
metadata: 'DONT_EXPORT', // 'DONT_EXPORT', 'MERGE_HEADER', 'MERGE_VARIABLE'
|
||||||
|
variable: 'boostnote',
|
||||||
|
prefixAttachmentFolder: false
|
||||||
|
},
|
||||||
coloredTags: {},
|
coloredTags: {},
|
||||||
wakatime: {
|
wakatime: {
|
||||||
key: null
|
key: null
|
||||||
|
|||||||
@@ -706,14 +706,15 @@ function replaceNoteKeyWithNewNoteKey(noteContent, oldNoteKey, newNoteKey) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Deletes all :storage and noteKey references from the given input.
|
* @description replace all :storage references with given destination folder.
|
||||||
* @param input Input in which the references should be deleted
|
* @param input Input in which the references should be replaced
|
||||||
* @param noteKey Key of the current note
|
* @param noteKey Key of the current note
|
||||||
|
* @param destinationFolder Destination folder of the attachements
|
||||||
* @returns {String} Input without the references
|
* @returns {String} Input without the references
|
||||||
*/
|
*/
|
||||||
function removeStorageAndNoteReferences(input, noteKey) {
|
function replaceStorageReferences(input, noteKey, destinationFolder) {
|
||||||
return input.replace(
|
return input.replace(
|
||||||
new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER + '.*?("|\\))', 'g'),
|
new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER + '[^"\\)<\\s]+', 'g'),
|
||||||
function(match) {
|
function(match) {
|
||||||
return match
|
return match
|
||||||
.replace(new RegExp(mdurl.encode(path.win32.sep), 'g'), path.posix.sep)
|
.replace(new RegExp(mdurl.encode(path.win32.sep), 'g'), path.posix.sep)
|
||||||
@@ -735,7 +736,7 @@ function removeStorageAndNoteReferences(input, noteKey) {
|
|||||||
')?',
|
')?',
|
||||||
'g'
|
'g'
|
||||||
),
|
),
|
||||||
DESTINATION_FOLDER
|
destinationFolder
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -1101,8 +1102,8 @@ module.exports = {
|
|||||||
getAttachmentsInMarkdownContent,
|
getAttachmentsInMarkdownContent,
|
||||||
getAbsolutePathsOfAttachmentsInContent,
|
getAbsolutePathsOfAttachmentsInContent,
|
||||||
importAttachments,
|
importAttachments,
|
||||||
removeStorageAndNoteReferences,
|
|
||||||
removeAttachmentsByPaths,
|
removeAttachmentsByPaths,
|
||||||
|
replaceStorageReferences,
|
||||||
deleteAttachmentFolder,
|
deleteAttachmentFolder,
|
||||||
deleteAttachmentsNotPresentInNote,
|
deleteAttachmentsNotPresentInNote,
|
||||||
getAttachmentsPathAndStatus,
|
getAttachmentsPathAndStatus,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const fs = require('fs')
|
import fs from 'fs'
|
||||||
const path = require('path')
|
import fx from 'fs-extra'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Copy a file from source to destination
|
* @description Copy a file from source to destination
|
||||||
@@ -14,7 +15,8 @@ function copyFile(srcPath, dstPath) {
|
|||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const dstFolder = path.dirname(dstPath)
|
const dstFolder = path.dirname(dstPath)
|
||||||
if (!fs.existsSync(dstFolder)) fs.mkdirSync(dstFolder)
|
|
||||||
|
fx.ensureDirSync(dstFolder)
|
||||||
|
|
||||||
const input = fs.createReadStream(decodeURI(srcPath))
|
const input = fs.createReadStream(decodeURI(srcPath))
|
||||||
const output = fs.createWriteStream(dstPath)
|
const output = fs.createWriteStream(dstPath)
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
import { findStorage } from 'browser/lib/findStorage'
|
import { findStorage } from 'browser/lib/findStorage'
|
||||||
import resolveStorageData from './resolveStorageData'
|
import resolveStorageData from './resolveStorageData'
|
||||||
import resolveStorageNotes from './resolveStorageNotes'
|
import resolveStorageNotes from './resolveStorageNotes'
|
||||||
|
import getFilename from './getFilename'
|
||||||
import exportNote from './exportNote'
|
import exportNote from './exportNote'
|
||||||
import filenamify from 'filenamify'
|
import getContentFormatter from './getContentFormatter'
|
||||||
import * as path from 'path'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {String} storageKey
|
* @param {String} storageKey
|
||||||
* @param {String} folderKey
|
* @param {String} folderKey
|
||||||
* @param {String} fileType
|
* @param {String} fileType
|
||||||
* @param {String} exportDir
|
* @param {String} exportDir
|
||||||
|
* @param {Object} config
|
||||||
*
|
*
|
||||||
* @return {Object}
|
* @return {Object}
|
||||||
* ```
|
* ```
|
||||||
@@ -22,7 +23,7 @@ import * as path from 'path'
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function exportFolder(storageKey, folderKey, fileType, exportDir) {
|
function exportFolder(storageKey, folderKey, fileType, exportDir, config) {
|
||||||
let targetStorage
|
let targetStorage
|
||||||
try {
|
try {
|
||||||
targetStorage = findStorage(storageKey)
|
targetStorage = findStorage(storageKey)
|
||||||
@@ -30,38 +31,33 @@ function exportFolder(storageKey, folderKey, fileType, exportDir) {
|
|||||||
return Promise.reject(e)
|
return Promise.reject(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolveStorageData(targetStorage)
|
const deduplicator = {}
|
||||||
.then(function assignNotes(storage) {
|
|
||||||
return resolveStorageNotes(storage).then(notes => {
|
|
||||||
return {
|
|
||||||
storage,
|
|
||||||
notes
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.then(function exportNotes(data) {
|
|
||||||
const { storage, notes } = data
|
|
||||||
|
|
||||||
return Promise.all(
|
return resolveStorageData(targetStorage)
|
||||||
notes
|
.then(storage => {
|
||||||
.filter(
|
return resolveStorageNotes(storage).then(notes => ({
|
||||||
|
storage,
|
||||||
|
notes: notes.filter(
|
||||||
note =>
|
note =>
|
||||||
note.folder === folderKey &&
|
note.folder === folderKey &&
|
||||||
note.isTrashed === false &&
|
!note.isTrashed &&
|
||||||
note.type === 'MARKDOWN_NOTE'
|
note.type === 'MARKDOWN_NOTE'
|
||||||
)
|
)
|
||||||
.map(note => {
|
}))
|
||||||
const notePath = path.join(
|
})
|
||||||
|
.then(({ storage, notes }) => {
|
||||||
|
const contentFormatter = getContentFormatter(storage, fileType, config)
|
||||||
|
|
||||||
|
return Promise.all(
|
||||||
|
notes.map(note => {
|
||||||
|
const targetPath = getFilename(
|
||||||
|
note,
|
||||||
|
fileType,
|
||||||
exportDir,
|
exportDir,
|
||||||
`${filenamify(note.title, { replacement: '_' })}.${fileType}`
|
deduplicator
|
||||||
)
|
|
||||||
return exportNote(
|
|
||||||
note.key,
|
|
||||||
storage.path,
|
|
||||||
note.content,
|
|
||||||
notePath,
|
|
||||||
null
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return exportNote(storage.key, note, targetPath, contentFormatter)
|
||||||
})
|
})
|
||||||
).then(() => ({
|
).then(() => ({
|
||||||
storage,
|
storage,
|
||||||
|
|||||||
@@ -4,58 +4,35 @@ import { findStorage } from 'browser/lib/findStorage'
|
|||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
||||||
const attachmentManagement = require('./attachmentManagement')
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export note together with attachments
|
* Export note together with attachments
|
||||||
*
|
*
|
||||||
* If attachments are stored in the storage, creates 'attachments' subfolder in target directory
|
* 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
|
* 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} storageKey or storage path
|
||||||
* @param {String} noteContent Content to export
|
* @param {Object} note Note to export
|
||||||
* @param {String} targetPath Path to exported file
|
* @param {String} targetPath Path to exported file
|
||||||
* @param {function} outputFormatter
|
* @param {function} outputFormatter
|
||||||
* @return {Promise.<*[]>}
|
* @return {Promise.<*[]>}
|
||||||
*/
|
*/
|
||||||
function exportNote(
|
function exportNote(storageKey, note, targetPath, outputFormatter) {
|
||||||
nodeKey,
|
|
||||||
storageKey,
|
|
||||||
noteContent,
|
|
||||||
targetPath,
|
|
||||||
outputFormatter
|
|
||||||
) {
|
|
||||||
const storagePath = path.isAbsolute(storageKey)
|
const storagePath = path.isAbsolute(storageKey)
|
||||||
? storageKey
|
? storageKey
|
||||||
: findStorage(storageKey).path
|
: findStorage(storageKey).path
|
||||||
|
|
||||||
const exportTasks = []
|
const exportTasks = []
|
||||||
|
|
||||||
if (!storagePath) {
|
if (!storagePath) {
|
||||||
throw new Error('Storage path is not found')
|
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(
|
const exportedData = Promise.resolve(
|
||||||
noteContent,
|
outputFormatter
|
||||||
nodeKey
|
? outputFormatter(note, targetPath, exportTasks)
|
||||||
|
: note.content
|
||||||
)
|
)
|
||||||
|
|
||||||
if (outputFormatter) {
|
|
||||||
exportedData = outputFormatter(exportedData, exportTasks, targetPath)
|
|
||||||
} else {
|
|
||||||
exportedData = Promise.resolve(exportedData)
|
|
||||||
}
|
|
||||||
|
|
||||||
const tasks = prepareTasks(exportTasks, storagePath, path.dirname(targetPath))
|
const tasks = prepareTasks(exportTasks, storagePath, path.dirname(targetPath))
|
||||||
|
|
||||||
return Promise.all(tasks.map(task => copyFile(task.src, task.dst)))
|
return Promise.all(tasks.map(task => copyFile(task.src, task.dst)))
|
||||||
@@ -63,9 +40,9 @@ function exportNote(
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
return saveToFile(data, targetPath)
|
return saveToFile(data, targetPath)
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(error => {
|
||||||
rollbackExport(tasks)
|
rollbackExport(tasks)
|
||||||
throw err
|
throw error
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,14 +84,14 @@ function rollbackExport(tasks) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fs.existsSync(fullpath)) {
|
if (fs.existsSync(fullpath)) {
|
||||||
fs.unlink(fullpath)
|
fs.unlinkSync(fullpath)
|
||||||
folders.add(path.dirname(fullpath))
|
folders.add(path.dirname(fullpath))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
folders.forEach(folder => {
|
folders.forEach(folder => {
|
||||||
if (fs.readdirSync(folder).length === 0) {
|
if (fs.readdirSync(folder).length === 0) {
|
||||||
fs.rmdir(folder)
|
fs.rmdirSync(folder)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
19
browser/main/lib/dataApi/exportNoteAs.js
Normal file
19
browser/main/lib/dataApi/exportNoteAs.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { findStorage } from 'browser/lib/findStorage'
|
||||||
|
import exportNote from './exportNote'
|
||||||
|
import getContentFormatter from './getContentFormatter'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} note
|
||||||
|
* @param {String} filename
|
||||||
|
* @param {String} fileType
|
||||||
|
* @param {Object} config
|
||||||
|
*/
|
||||||
|
|
||||||
|
function exportNoteAs(note, filename, fileType, config) {
|
||||||
|
const storage = findStorage(note.storage)
|
||||||
|
const contentFormatter = getContentFormatter(storage, fileType, config)
|
||||||
|
|
||||||
|
return exportNote(storage.key, note, filename, contentFormatter)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exportNoteAs
|
||||||
@@ -2,13 +2,17 @@ import { findStorage } from 'browser/lib/findStorage'
|
|||||||
import resolveStorageData from './resolveStorageData'
|
import resolveStorageData from './resolveStorageData'
|
||||||
import resolveStorageNotes from './resolveStorageNotes'
|
import resolveStorageNotes from './resolveStorageNotes'
|
||||||
import filenamify from 'filenamify'
|
import filenamify from 'filenamify'
|
||||||
import * as path from 'path'
|
import path from 'path'
|
||||||
import * as fs from 'fs'
|
import fs from 'fs'
|
||||||
|
import exportNote from './exportNote'
|
||||||
|
import getContentFormatter from './getContentFormatter'
|
||||||
|
import getFilename from './getFilename'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {String} storageKey
|
* @param {String} storageKey
|
||||||
* @param {String} fileType
|
* @param {String} fileType
|
||||||
* @param {String} exportDir
|
* @param {String} exportDir
|
||||||
|
* @param {Object} config
|
||||||
*
|
*
|
||||||
* @return {Object}
|
* @return {Object}
|
||||||
* ```
|
* ```
|
||||||
@@ -20,7 +24,7 @@ import * as fs from 'fs'
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function exportStorage(storageKey, fileType, exportDir) {
|
function exportStorage(storageKey, fileType, exportDir, config) {
|
||||||
let targetStorage
|
let targetStorage
|
||||||
try {
|
try {
|
||||||
targetStorage = findStorage(storageKey)
|
targetStorage = findStorage(storageKey)
|
||||||
@@ -29,39 +33,52 @@ function exportStorage(storageKey, fileType, exportDir) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return resolveStorageData(targetStorage)
|
return resolveStorageData(targetStorage)
|
||||||
.then(storage =>
|
.then(storage => {
|
||||||
resolveStorageNotes(storage).then(notes => ({ storage, notes }))
|
return resolveStorageNotes(storage).then(notes => ({
|
||||||
|
storage,
|
||||||
|
notes: notes.filter(
|
||||||
|
note => !note.isTrashed && note.type === 'MARKDOWN_NOTE'
|
||||||
)
|
)
|
||||||
.then(function exportNotes(data) {
|
}))
|
||||||
const { storage, notes } = data
|
})
|
||||||
|
.then(({ storage, notes }) => {
|
||||||
|
const contentFormatter = getContentFormatter(storage, fileType, config)
|
||||||
|
|
||||||
const folderNamesMapping = {}
|
const folderNamesMapping = {}
|
||||||
|
const deduplicators = {}
|
||||||
|
|
||||||
storage.folders.forEach(folder => {
|
storage.folders.forEach(folder => {
|
||||||
const folderExportedDir = path.join(
|
const folderExportedDir = path.join(
|
||||||
exportDir,
|
exportDir,
|
||||||
filenamify(folder.name, { replacement: '_' })
|
filenamify(folder.name, { replacement: '_' })
|
||||||
)
|
)
|
||||||
|
|
||||||
folderNamesMapping[folder.key] = folderExportedDir
|
folderNamesMapping[folder.key] = folderExportedDir
|
||||||
|
|
||||||
// make sure directory exists
|
// make sure directory exists
|
||||||
try {
|
try {
|
||||||
fs.mkdirSync(folderExportedDir)
|
fs.mkdirSync(folderExportedDir)
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
})
|
|
||||||
notes
|
deduplicators[folder.key] = {}
|
||||||
.filter(note => !note.isTrashed && note.type === 'MARKDOWN_NOTE')
|
|
||||||
.forEach(markdownNote => {
|
|
||||||
const folderExportedDir = folderNamesMapping[markdownNote.folder]
|
|
||||||
const snippetName = `${filenamify(markdownNote.title, {
|
|
||||||
replacement: '_'
|
|
||||||
})}.${fileType}`
|
|
||||||
const notePath = path.join(folderExportedDir, snippetName)
|
|
||||||
fs.writeFileSync(notePath, markdownNote.content)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return Promise.all(
|
||||||
|
notes.map(note => {
|
||||||
|
const targetPath = getFilename(
|
||||||
|
note,
|
||||||
|
fileType,
|
||||||
|
folderNamesMapping[note.folder],
|
||||||
|
deduplicators[note.folder]
|
||||||
|
)
|
||||||
|
|
||||||
|
return exportNote(storage.key, note, targetPath, contentFormatter)
|
||||||
|
})
|
||||||
|
).then(() => ({
|
||||||
storage,
|
storage,
|
||||||
fileType,
|
fileType,
|
||||||
exportDir
|
exportDir
|
||||||
}
|
}))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
browser/main/lib/dataApi/exportTag.js
Normal file
28
browser/main/lib/dataApi/exportTag.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import exportNoteAs from './exportNoteAs'
|
||||||
|
import getFilename from './getFilename'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {String} tag
|
||||||
|
* @param {String} fileType
|
||||||
|
* @param {String} exportDir
|
||||||
|
* @param {Object} config
|
||||||
|
*/
|
||||||
|
|
||||||
|
function exportTag(data, tag, fileType, exportDir, config) {
|
||||||
|
const notes = data.noteMap
|
||||||
|
.map(note => note)
|
||||||
|
.filter(note => note.tags.indexOf(tag) !== -1)
|
||||||
|
|
||||||
|
const deduplicator = {}
|
||||||
|
|
||||||
|
return Promise.all(
|
||||||
|
notes.map(note => {
|
||||||
|
const filename = getFilename(note, fileType, exportDir, deduplicator)
|
||||||
|
|
||||||
|
return exportNoteAs(note, filename, fileType, config)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exportTag
|
||||||
796
browser/main/lib/dataApi/formatHTML.js
Normal file
796
browser/main/lib/dataApi/formatHTML.js
Normal file
@@ -0,0 +1,796 @@
|
|||||||
|
import path from 'path'
|
||||||
|
import fileUrl from 'file-url'
|
||||||
|
import fs from 'fs'
|
||||||
|
import { remote } from 'electron'
|
||||||
|
import consts from 'browser/lib/consts'
|
||||||
|
import Markdown from 'browser/lib/markdown'
|
||||||
|
import attachmentManagement from './attachmentManagement'
|
||||||
|
import { version as codemirrorVersion } from 'codemirror/package.json'
|
||||||
|
import { escapeHtmlCharacters } from 'browser/lib/utils'
|
||||||
|
|
||||||
|
const { app } = remote
|
||||||
|
const appPath = fileUrl(
|
||||||
|
process.env.NODE_ENV === 'production' ? app.getAppPath() : path.resolve()
|
||||||
|
)
|
||||||
|
|
||||||
|
let markdownStyle = ''
|
||||||
|
try {
|
||||||
|
markdownStyle = require('!!css!stylus?sourceMap!../../../components/markdown.styl')[0][1]
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
export const CSS_FILES = [
|
||||||
|
`${appPath}/node_modules/katex/dist/katex.min.css`,
|
||||||
|
`${appPath}/node_modules/codemirror/lib/codemirror.css`,
|
||||||
|
`${appPath}/node_modules/react-image-carousel/lib/css/main.min.css`
|
||||||
|
]
|
||||||
|
|
||||||
|
const macos = global.process.platform === 'darwin'
|
||||||
|
|
||||||
|
const defaultFontFamily = ['helvetica', 'arial', 'sans-serif']
|
||||||
|
if (!macos) {
|
||||||
|
defaultFontFamily.unshift('Microsoft YaHei')
|
||||||
|
defaultFontFamily.unshift('meiryo')
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultCodeBlockFontFamily = [
|
||||||
|
'Monaco',
|
||||||
|
'Menlo',
|
||||||
|
'Ubuntu Mono',
|
||||||
|
'Consolas',
|
||||||
|
'source-code-pro',
|
||||||
|
'monospace'
|
||||||
|
]
|
||||||
|
|
||||||
|
function unprefix(file) {
|
||||||
|
if (global.process.platform === 'win32') {
|
||||||
|
return file.replace('file:///', '')
|
||||||
|
} else {
|
||||||
|
return file.replace('file://', '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ```
|
||||||
|
* {
|
||||||
|
* fontFamily,
|
||||||
|
* fontSize,
|
||||||
|
* lineNumber,
|
||||||
|
* codeBlockFontFamily,
|
||||||
|
* codeBlockTheme,
|
||||||
|
* scrollPastEnd,
|
||||||
|
* theme,
|
||||||
|
* allowCustomCSS,
|
||||||
|
* customCSS
|
||||||
|
* smartQuotes,
|
||||||
|
* sanitize,
|
||||||
|
* breaks,
|
||||||
|
* storagePath,
|
||||||
|
* export,
|
||||||
|
* indentSize
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export default function formatHTML(props) {
|
||||||
|
const {
|
||||||
|
fontFamily,
|
||||||
|
fontSize,
|
||||||
|
codeBlockFontFamily,
|
||||||
|
lineNumber,
|
||||||
|
codeBlockTheme,
|
||||||
|
scrollPastEnd,
|
||||||
|
theme,
|
||||||
|
allowCustomCSS,
|
||||||
|
customCSS
|
||||||
|
} = getStyleParams(props)
|
||||||
|
|
||||||
|
const inlineStyles = buildStyle(
|
||||||
|
fontFamily,
|
||||||
|
fontSize,
|
||||||
|
codeBlockFontFamily,
|
||||||
|
lineNumber,
|
||||||
|
scrollPastEnd,
|
||||||
|
theme,
|
||||||
|
allowCustomCSS,
|
||||||
|
customCSS
|
||||||
|
)
|
||||||
|
|
||||||
|
const { smartQuotes, sanitize, breaks } = props
|
||||||
|
|
||||||
|
let indentSize = parseInt(props.indentSize, 10)
|
||||||
|
if (!(indentSize > 0 && indentSize < 132)) {
|
||||||
|
indentSize = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
const files = [getCodeThemeLink(codeBlockTheme), ...CSS_FILES]
|
||||||
|
|
||||||
|
return function(note, targetPath, exportTasks) {
|
||||||
|
const styles = files
|
||||||
|
.map(file => `<link rel="stylesheet" href="css/${path.basename(file)}">`)
|
||||||
|
.join('\n')
|
||||||
|
|
||||||
|
let inlineScripts = ''
|
||||||
|
let scripts = ''
|
||||||
|
|
||||||
|
let decodeEntities = false
|
||||||
|
function addDecodeEntities() {
|
||||||
|
if (decodeEntities) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
decodeEntities = true
|
||||||
|
|
||||||
|
inlineScripts += `
|
||||||
|
function decodeEntities (text) {
|
||||||
|
var entities = [
|
||||||
|
['apos', '\\''],
|
||||||
|
['amp', '&'],
|
||||||
|
['lt', '<'],
|
||||||
|
['gt', '>'],
|
||||||
|
['#63', '\\?'],
|
||||||
|
['#36', '\\$']
|
||||||
|
]
|
||||||
|
|
||||||
|
for (var i = 0, max = entities.length; i < max; ++i) {
|
||||||
|
text = text.replace(new RegExp(\`&\${entities[i][0]};\`, 'g'), entities[i][1])
|
||||||
|
}
|
||||||
|
|
||||||
|
return text
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
|
||||||
|
let lodash = false
|
||||||
|
function addLodash() {
|
||||||
|
if (lodash) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
lodash = true
|
||||||
|
|
||||||
|
exportTasks.push({
|
||||||
|
src: unprefix(`${appPath}/node_modules/lodash/lodash.min.js`),
|
||||||
|
dst: 'js'
|
||||||
|
})
|
||||||
|
|
||||||
|
scripts += `<script src="js/lodash.min.js"></script>`
|
||||||
|
}
|
||||||
|
|
||||||
|
let raphael = false
|
||||||
|
function addRaphael() {
|
||||||
|
if (raphael) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
raphael = true
|
||||||
|
|
||||||
|
exportTasks.push({
|
||||||
|
src: unprefix(`${appPath}/node_modules/raphael/raphael.min.js`),
|
||||||
|
dst: 'js'
|
||||||
|
})
|
||||||
|
|
||||||
|
scripts += `<script src="js/raphael.min.js"></script>`
|
||||||
|
}
|
||||||
|
|
||||||
|
let yaml = false
|
||||||
|
function addYAML() {
|
||||||
|
if (yaml) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
yaml = true
|
||||||
|
|
||||||
|
exportTasks.push({
|
||||||
|
src: unprefix(`${appPath}/node_modules/js-yaml/dist/js-yaml.min.js`),
|
||||||
|
dst: 'js'
|
||||||
|
})
|
||||||
|
|
||||||
|
scripts += `<script src="js/js-yaml.min.js"></script>`
|
||||||
|
}
|
||||||
|
|
||||||
|
let chart = false
|
||||||
|
function addChart() {
|
||||||
|
if (chart) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
chart = true
|
||||||
|
|
||||||
|
addLodash()
|
||||||
|
|
||||||
|
exportTasks.push({
|
||||||
|
src: unprefix(`${appPath}/node_modules/chart.js/dist/Chart.min.js`),
|
||||||
|
dst: 'js'
|
||||||
|
})
|
||||||
|
|
||||||
|
scripts += `<script src="js/Chart.min.js"></script>`
|
||||||
|
|
||||||
|
inlineScripts += `
|
||||||
|
function displayCharts() {
|
||||||
|
_.forEach(
|
||||||
|
document.querySelectorAll('.chart'),
|
||||||
|
el => {
|
||||||
|
try {
|
||||||
|
const format = el.attributes.getNamedItem('data-format').value
|
||||||
|
const chartConfig = format === 'yaml' ? jsyaml.load(el.innerHTML) : JSON.parse(el.innerHTML)
|
||||||
|
el.innerHTML = ''
|
||||||
|
|
||||||
|
const canvas = document.createElement('canvas')
|
||||||
|
el.appendChild(canvas)
|
||||||
|
|
||||||
|
const height = el.attributes.getNamedItem('data-height')
|
||||||
|
if (height && height.value !== 'undefined') {
|
||||||
|
el.style.height = height.value + 'vh'
|
||||||
|
canvas.height = height.value + 'vh'
|
||||||
|
}
|
||||||
|
|
||||||
|
const chart = new Chart(canvas, chartConfig)
|
||||||
|
} catch (e) {
|
||||||
|
el.className = 'chart-error'
|
||||||
|
el.innerHTML = 'chartjs diagram parse error: ' + e.message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', displayCharts);
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
let codemirror = false
|
||||||
|
function addCodeMirror() {
|
||||||
|
if (codemirror) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
codemirror = true
|
||||||
|
|
||||||
|
addDecodeEntities()
|
||||||
|
addLodash()
|
||||||
|
|
||||||
|
exportTasks.push(
|
||||||
|
{
|
||||||
|
src: unprefix(`${appPath}/node_modules/codemirror/lib/codemirror.js`),
|
||||||
|
dst: 'js/codemirror'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: unprefix(`${appPath}/node_modules/codemirror/mode/meta.js`),
|
||||||
|
dst: 'js/codemirror/mode'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: unprefix(
|
||||||
|
`${appPath}/node_modules/codemirror/addon/mode/loadmode.js`
|
||||||
|
),
|
||||||
|
dst: 'js/codemirror/addon/mode'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: unprefix(
|
||||||
|
`${appPath}/node_modules/codemirror/addon/runmode/runmode.js`
|
||||||
|
),
|
||||||
|
dst: 'js/codemirror/addon/runmode'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
scripts += `
|
||||||
|
<script src="js/codemirror/codemirror.js"></script>
|
||||||
|
<script src="js/codemirror/mode/meta.js"></script>
|
||||||
|
<script src="js/codemirror/addon/mode/loadmode.js"></script>
|
||||||
|
<script src="js/codemirror/addon/runmode/runmode.js"></script>
|
||||||
|
`
|
||||||
|
|
||||||
|
let className = `cm-s-${codeBlockTheme}`
|
||||||
|
if (codeBlockTheme.indexOf('solarized') === 0) {
|
||||||
|
const [refThema, color] = codeBlockTheme.split(' ')
|
||||||
|
className = `cm-s-${refThema} cm-s-${color}`
|
||||||
|
}
|
||||||
|
|
||||||
|
inlineScripts += `
|
||||||
|
CodeMirror.modeURL = 'https://cdn.jsdelivr.net/npm/codemirror@${codemirrorVersion}/mode/%N/%N.js';
|
||||||
|
|
||||||
|
function displayCodeBlocks() {
|
||||||
|
_.forEach(
|
||||||
|
document.querySelectorAll('.code code'),
|
||||||
|
el => {
|
||||||
|
el.parentNode.className += ' ${className}'
|
||||||
|
let syntax = CodeMirror.findModeByName(el.className)
|
||||||
|
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')
|
||||||
|
CodeMirror.requireMode(syntax.mode, () => {
|
||||||
|
const content = decodeEntities(el.innerHTML)
|
||||||
|
el.innerHTML = ''
|
||||||
|
CodeMirror.runMode(content, syntax.mime, el, {
|
||||||
|
tabSize: ${indentSize}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', displayCodeBlocks);
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
let flowchart = false
|
||||||
|
function addFlowchart() {
|
||||||
|
if (flowchart) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
flowchart = true
|
||||||
|
|
||||||
|
addDecodeEntities()
|
||||||
|
addLodash()
|
||||||
|
addRaphael()
|
||||||
|
|
||||||
|
exportTasks.push({
|
||||||
|
src: unprefix(
|
||||||
|
`${appPath}/node_modules/flowchart.js/release/flowchart.min.js`
|
||||||
|
),
|
||||||
|
dst: 'js'
|
||||||
|
})
|
||||||
|
|
||||||
|
scripts += `<script src="js/flowchart.min.js"></script>`
|
||||||
|
|
||||||
|
inlineScripts += `
|
||||||
|
function displayFlowcharts() {
|
||||||
|
_.forEach(
|
||||||
|
document.querySelectorAll('.flowchart'),
|
||||||
|
el => {
|
||||||
|
try {
|
||||||
|
const diagram = flowchart.parse(
|
||||||
|
decodeEntities(el.innerHTML)
|
||||||
|
)
|
||||||
|
el.innerHTML = ''
|
||||||
|
diagram.drawSVG(el)
|
||||||
|
} catch (e) {
|
||||||
|
el.className = 'flowchart-error'
|
||||||
|
el.innerHTML = 'Flowchart parse error: ' + e.message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', displayFlowcharts);
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
let mermaid = false
|
||||||
|
function addMermaid() {
|
||||||
|
if (mermaid) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mermaid = true
|
||||||
|
|
||||||
|
addLodash()
|
||||||
|
|
||||||
|
exportTasks.push({
|
||||||
|
src: unprefix(`${appPath}/node_modules/mermaid/dist/mermaid.min.js`),
|
||||||
|
dst: 'js'
|
||||||
|
})
|
||||||
|
|
||||||
|
scripts += `<script src="js/mermaid.min.js"></script>`
|
||||||
|
|
||||||
|
inlineScripts += `
|
||||||
|
function displayMermaids() {
|
||||||
|
_.forEach(
|
||||||
|
document.querySelectorAll('.mermaid'),
|
||||||
|
el => {
|
||||||
|
const height = el.attributes.getNamedItem('data-height')
|
||||||
|
if (height && height.value !== 'undefined') {
|
||||||
|
el.style.height = height.value + 'vh'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', displayMermaids);
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
let sequence = false
|
||||||
|
function addSequence() {
|
||||||
|
if (sequence) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sequence = true
|
||||||
|
|
||||||
|
addDecodeEntities()
|
||||||
|
addLodash()
|
||||||
|
addRaphael()
|
||||||
|
|
||||||
|
exportTasks.push({
|
||||||
|
src: unprefix(
|
||||||
|
`${appPath}/node_modules/@rokt33r/js-sequence-diagrams/dist/sequence-diagram-min.js`
|
||||||
|
),
|
||||||
|
dst: 'js'
|
||||||
|
})
|
||||||
|
|
||||||
|
scripts += `<script src="js/sequence-diagram-min.js"></script>`
|
||||||
|
|
||||||
|
inlineScripts += `
|
||||||
|
function displaySequences() {
|
||||||
|
_.forEach(
|
||||||
|
document.querySelectorAll('.sequence'),
|
||||||
|
el => {
|
||||||
|
try {
|
||||||
|
const diagram = Diagram.parse(
|
||||||
|
decodeEntities(el.innerHTML)
|
||||||
|
)
|
||||||
|
el.innerHTML = ''
|
||||||
|
diagram.drawSVG(el, { theme: 'simple' })
|
||||||
|
} catch (e) {
|
||||||
|
el.className = 'sequence-error'
|
||||||
|
el.innerHTML = 'Sequence diagram parse error: ' + e.message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', displaySequences);
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
const modes = {}
|
||||||
|
const markdown = new Markdown({
|
||||||
|
typographer: smartQuotes,
|
||||||
|
sanitize,
|
||||||
|
breaks,
|
||||||
|
onFence(type, mode) {
|
||||||
|
if (type === 'chart') {
|
||||||
|
addChart()
|
||||||
|
|
||||||
|
if (mode === 'yaml') {
|
||||||
|
addYAML()
|
||||||
|
}
|
||||||
|
} else if (type === 'code') {
|
||||||
|
addCodeMirror()
|
||||||
|
|
||||||
|
if (mode && modes[mode] !== true) {
|
||||||
|
const file = unprefix(
|
||||||
|
`${appPath}/node_modules/codemirror/mode/${mode}/${mode}.js`
|
||||||
|
)
|
||||||
|
|
||||||
|
if (fs.existsSync(file)) {
|
||||||
|
exportTasks.push({
|
||||||
|
src: file,
|
||||||
|
dst: `js/codemirror/mode/${mode}`
|
||||||
|
})
|
||||||
|
|
||||||
|
modes[mode] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (type === 'flowchart') {
|
||||||
|
addFlowchart()
|
||||||
|
} else if (type === 'mermaid') {
|
||||||
|
addMermaid()
|
||||||
|
} else if (type === 'sequence') {
|
||||||
|
addSequence()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
let body = note.content
|
||||||
|
|
||||||
|
if (sanitize === 'NONE') {
|
||||||
|
body = escapeHtmlCharactersInCodeTag(body.split('```'))
|
||||||
|
}
|
||||||
|
|
||||||
|
body = markdown.render(note.content)
|
||||||
|
|
||||||
|
const attachmentsAbsolutePaths = attachmentManagement.getAbsolutePathsOfAttachmentsInContent(
|
||||||
|
note.content,
|
||||||
|
props.storagePath
|
||||||
|
)
|
||||||
|
|
||||||
|
files.forEach(file => {
|
||||||
|
exportTasks.push({
|
||||||
|
src: unprefix(file),
|
||||||
|
dst: 'css'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const destinationFolder = props.export.prefixAttachmentFolder
|
||||||
|
? `${path.parse(targetPath).name} - ${
|
||||||
|
attachmentManagement.DESTINATION_FOLDER
|
||||||
|
}`
|
||||||
|
: attachmentManagement.DESTINATION_FOLDER
|
||||||
|
|
||||||
|
attachmentsAbsolutePaths.forEach(attachment => {
|
||||||
|
exportTasks.push({
|
||||||
|
src: attachment,
|
||||||
|
dst: destinationFolder
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
body = attachmentManagement.replaceStorageReferences(
|
||||||
|
body,
|
||||||
|
note.key,
|
||||||
|
destinationFolder
|
||||||
|
)
|
||||||
|
|
||||||
|
return `
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name = "viewport" content = "width = device-width, initial-scale = 1, maximum-scale = 1">
|
||||||
|
<style id="style">${inlineStyles}</style>
|
||||||
|
${styles}
|
||||||
|
${scripts}
|
||||||
|
<script>${inlineScripts}</script>
|
||||||
|
</head>
|
||||||
|
<body data-theme="${theme}">
|
||||||
|
${body}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getStyleParams(props) {
|
||||||
|
const {
|
||||||
|
fontSize,
|
||||||
|
lineNumber,
|
||||||
|
codeBlockTheme,
|
||||||
|
scrollPastEnd,
|
||||||
|
theme,
|
||||||
|
allowCustomCSS,
|
||||||
|
customCSS,
|
||||||
|
RTL
|
||||||
|
} = props
|
||||||
|
|
||||||
|
let { fontFamily, codeBlockFontFamily } = props
|
||||||
|
|
||||||
|
fontFamily =
|
||||||
|
_.isString(fontFamily) && fontFamily.trim().length > 0
|
||||||
|
? fontFamily
|
||||||
|
.split(',')
|
||||||
|
.map(fontName => fontName.trim())
|
||||||
|
.concat(defaultFontFamily)
|
||||||
|
: defaultFontFamily
|
||||||
|
|
||||||
|
codeBlockFontFamily =
|
||||||
|
_.isString(codeBlockFontFamily) && codeBlockFontFamily.trim().length > 0
|
||||||
|
? codeBlockFontFamily
|
||||||
|
.split(',')
|
||||||
|
.map(fontName => fontName.trim())
|
||||||
|
.concat(defaultCodeBlockFontFamily)
|
||||||
|
: defaultCodeBlockFontFamily
|
||||||
|
|
||||||
|
return {
|
||||||
|
fontFamily,
|
||||||
|
fontSize,
|
||||||
|
codeBlockFontFamily,
|
||||||
|
lineNumber,
|
||||||
|
codeBlockTheme,
|
||||||
|
scrollPastEnd,
|
||||||
|
theme,
|
||||||
|
allowCustomCSS,
|
||||||
|
customCSS,
|
||||||
|
RTL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCodeThemeLink(name) {
|
||||||
|
const theme = consts.THEMES.find(theme => theme.name === name)
|
||||||
|
|
||||||
|
return theme != null
|
||||||
|
? theme.path
|
||||||
|
: `${appPath}/node_modules/codemirror/theme/elegant.css`
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildStyle(
|
||||||
|
fontFamily,
|
||||||
|
fontSize,
|
||||||
|
codeBlockFontFamily,
|
||||||
|
lineNumber,
|
||||||
|
scrollPastEnd,
|
||||||
|
theme,
|
||||||
|
allowCustomCSS,
|
||||||
|
customCSS,
|
||||||
|
RTL
|
||||||
|
) {
|
||||||
|
return `
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Lato';
|
||||||
|
src: url('${appPath}/resources/fonts/Lato-Regular.woff2') format('woff2'), /* Modern Browsers */
|
||||||
|
url('${appPath}/resources/fonts/Lato-Regular.woff') format('woff'), /* Modern Browsers */
|
||||||
|
url('${appPath}/resources/fonts/Lato-Regular.ttf') format('truetype');
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Lato';
|
||||||
|
src: url('${appPath}/resources/fonts/Lato-Black.woff2') format('woff2'), /* Modern Browsers */
|
||||||
|
url('${appPath}/resources/fonts/Lato-Black.woff') format('woff'), /* Modern Browsers */
|
||||||
|
url('${appPath}/resources/fonts/Lato-Black.ttf') format('truetype');
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Material Icons';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Material Icons'),
|
||||||
|
local('MaterialIcons-Regular'),
|
||||||
|
url('${appPath}/resources/fonts/MaterialIcons-Regular.woff2') format('woff2'),
|
||||||
|
url('${appPath}/resources/fonts/MaterialIcons-Regular.woff') format('woff'),
|
||||||
|
url('${appPath}/resources/fonts/MaterialIcons-Regular.ttf') format('truetype');
|
||||||
|
}
|
||||||
|
${markdownStyle}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: '${fontFamily.join("','")}';
|
||||||
|
font-size: ${fontSize}px;
|
||||||
|
${scrollPastEnd && 'padding-bottom: 90vh;box-sizing: border-box;'}
|
||||||
|
${RTL && 'direction: rtl;text-align: right;'}
|
||||||
|
}
|
||||||
|
@media print {
|
||||||
|
body {
|
||||||
|
padding-bottom: initial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: '${codeBlockFontFamily.join("','")}';
|
||||||
|
background-color: rgba(0,0,0,0.04);
|
||||||
|
text-align: left;
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
|
||||||
|
p code.inline,
|
||||||
|
li code.inline,
|
||||||
|
td code.inline
|
||||||
|
{
|
||||||
|
padding: 2px;
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
[data-theme="default"] p code.inline,
|
||||||
|
[data-theme="default"] li code.inline,
|
||||||
|
[data-theme="default"] td code.inline
|
||||||
|
{
|
||||||
|
background-color: #F4F4F4;
|
||||||
|
border-color: #d9d9d9;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
[data-theme="white"] p code.inline,
|
||||||
|
[data-theme="white"] li code.inline,
|
||||||
|
[data-theme="white"] td code.inline
|
||||||
|
{
|
||||||
|
background-color: #F4F4F4;
|
||||||
|
border-color: #d9d9d9;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
[data-theme="dark"] p code.inline,
|
||||||
|
[data-theme="dark"] li code.inline,
|
||||||
|
[data-theme="dark"] td code.inline
|
||||||
|
{
|
||||||
|
background-color: #444444;
|
||||||
|
border-color: #555;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
[data-theme="dracula"] p code.inline,
|
||||||
|
[data-theme="dracula"] li code.inline,
|
||||||
|
[data-theme="dracula"] td code.inline
|
||||||
|
{
|
||||||
|
background-color: #444444;
|
||||||
|
border-color: #555;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
[data-theme="monokai"] p code.inline,
|
||||||
|
[data-theme="monokai"] li code.inline,
|
||||||
|
[data-theme="monokai"] td code.inline
|
||||||
|
{
|
||||||
|
background-color: #444444;
|
||||||
|
border-color: #555;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
[data-theme="nord"] p code.inline,
|
||||||
|
[data-theme="nord"] li code.inline,
|
||||||
|
[data-theme="nord"] td code.inline
|
||||||
|
{
|
||||||
|
background-color: #444444;
|
||||||
|
border-color: #555;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
[data-theme="solarized-dark"] p code.inline,
|
||||||
|
[data-theme="solarized-dark"] li code.inline,
|
||||||
|
[data-theme="solarized-dark"] td code.inline
|
||||||
|
{
|
||||||
|
background-color: #444444;
|
||||||
|
border-color: #555;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
[data-theme="vulcan"] p code.inline,
|
||||||
|
[data-theme="vulcan"] li code.inline,
|
||||||
|
[data-theme="vulcan"] td code.inline
|
||||||
|
{
|
||||||
|
background-color: #444444;
|
||||||
|
border-color: #555;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lineNumber {
|
||||||
|
${lineNumber && 'display: block !important;'}
|
||||||
|
font-family: '${codeBlockFontFamily.join("','")}';
|
||||||
|
}
|
||||||
|
|
||||||
|
.clipboardButton {
|
||||||
|
color: rgba(147,147,149,0.8);;
|
||||||
|
fill: rgba(147,147,149,1);;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin: 0px 10px;
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
outline: none;
|
||||||
|
height: 15px;
|
||||||
|
width: 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clipboardButton:hover {
|
||||||
|
transition: 0.2s;
|
||||||
|
color: #939395;
|
||||||
|
fill: #939395;
|
||||||
|
background-color: rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2 {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
padding-bottom: 4px;
|
||||||
|
margin: 1em 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
padding-bottom: 0.2em;
|
||||||
|
margin: 1em 0 0.37em;
|
||||||
|
}
|
||||||
|
|
||||||
|
body p {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
body[data-theme="${theme}"] {
|
||||||
|
color: #000;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
.clipboardButton {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
${allowCustomCSS ? customCSS : ''}
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Convert special characters between three ```
|
||||||
|
* @param {string[]} splitWithCodeTag Array of HTML strings separated by three ```
|
||||||
|
* @returns {string} HTML in which special characters between three ``` have been converted
|
||||||
|
*/
|
||||||
|
export function escapeHtmlCharactersInCodeTag(splitWithCodeTag) {
|
||||||
|
for (let index = 0; index < splitWithCodeTag.length; index++) {
|
||||||
|
const codeTagRequired =
|
||||||
|
splitWithCodeTag[index] !== '```' && index < splitWithCodeTag.length - 1
|
||||||
|
if (codeTagRequired) {
|
||||||
|
splitWithCodeTag.splice(index + 1, 0, '```')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let inCodeTag = false
|
||||||
|
let result = ''
|
||||||
|
for (let content of splitWithCodeTag) {
|
||||||
|
if (content === '```') {
|
||||||
|
inCodeTag = !inCodeTag
|
||||||
|
} else if (inCodeTag) {
|
||||||
|
content = escapeHtmlCharacters(content)
|
||||||
|
}
|
||||||
|
result += content
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
103
browser/main/lib/dataApi/formatMarkdown.js
Normal file
103
browser/main/lib/dataApi/formatMarkdown.js
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
import attachmentManagement from './attachmentManagement'
|
||||||
|
import yaml from 'js-yaml'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
const delimiterRegExp = /^\-{3}/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ```
|
||||||
|
* {
|
||||||
|
* storagePath,
|
||||||
|
* export
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export default function formatMarkdown(props) {
|
||||||
|
return function(note, targetPath, exportTasks) {
|
||||||
|
let result = note.content
|
||||||
|
|
||||||
|
if (props.storagePath && note.key) {
|
||||||
|
const attachmentsAbsolutePaths = attachmentManagement.getAbsolutePathsOfAttachmentsInContent(
|
||||||
|
result,
|
||||||
|
props.storagePath
|
||||||
|
)
|
||||||
|
|
||||||
|
const destinationFolder = props.export.prefixAttachmentFolder
|
||||||
|
? `${path.parse(targetPath).name} - ${
|
||||||
|
attachmentManagement.DESTINATION_FOLDER
|
||||||
|
}`
|
||||||
|
: attachmentManagement.DESTINATION_FOLDER
|
||||||
|
|
||||||
|
attachmentsAbsolutePaths.forEach(attachment => {
|
||||||
|
exportTasks.push({
|
||||||
|
src: attachment,
|
||||||
|
dst: destinationFolder
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
result = attachmentManagement.replaceStorageReferences(
|
||||||
|
result,
|
||||||
|
note.key,
|
||||||
|
destinationFolder
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.export.metadata === 'MERGE_HEADER') {
|
||||||
|
const metadata = getFrontMatter(result)
|
||||||
|
|
||||||
|
const values = Object.assign({}, note)
|
||||||
|
delete values.content
|
||||||
|
delete values.isTrashed
|
||||||
|
|
||||||
|
for (const key in values) {
|
||||||
|
metadata[key] = values[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
result = replaceFrontMatter(result, metadata)
|
||||||
|
} else if (props.export.metadata === 'MERGE_VARIABLE') {
|
||||||
|
const metadata = getFrontMatter(result)
|
||||||
|
|
||||||
|
const values = Object.assign({}, note)
|
||||||
|
delete values.content
|
||||||
|
delete values.isTrashed
|
||||||
|
|
||||||
|
if (props.export.variable) {
|
||||||
|
metadata[props.export.variable] = values
|
||||||
|
} else {
|
||||||
|
for (const key in values) {
|
||||||
|
metadata[key] = values[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = replaceFrontMatter(result, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFrontMatter(markdown) {
|
||||||
|
const lines = markdown.split('\n')
|
||||||
|
|
||||||
|
if (delimiterRegExp.test(lines[0])) {
|
||||||
|
let line = 0
|
||||||
|
while (++line < lines.length && !delimiterRegExp.test(lines[line])) {}
|
||||||
|
|
||||||
|
return yaml.load(lines.slice(1, line).join('\n')) || {}
|
||||||
|
} else {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function replaceFrontMatter(markdown, metadata) {
|
||||||
|
const lines = markdown.split('\n')
|
||||||
|
|
||||||
|
if (delimiterRegExp.test(lines[0])) {
|
||||||
|
let line = 0
|
||||||
|
while (++line < lines.length && !delimiterRegExp.test(lines[line])) {}
|
||||||
|
|
||||||
|
return `---\n${yaml.dump(metadata)}---\n${lines.slice(line + 1).join('\n')}`
|
||||||
|
} else {
|
||||||
|
return `---\n${yaml.dump(metadata)}---\n\n${markdown}`
|
||||||
|
}
|
||||||
|
}
|
||||||
26
browser/main/lib/dataApi/formatPDF.js
Normal file
26
browser/main/lib/dataApi/formatPDF.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import formatHTML from './formatHTML'
|
||||||
|
import { remote } from 'electron'
|
||||||
|
|
||||||
|
export default function formatPDF(props) {
|
||||||
|
return function(note, targetPath, exportTasks) {
|
||||||
|
const printout = new remote.BrowserWindow({
|
||||||
|
show: false,
|
||||||
|
webPreferences: { webSecurity: false, javascript: false }
|
||||||
|
})
|
||||||
|
|
||||||
|
printout.loadURL(
|
||||||
|
'data:text/html;charset=UTF-8,' +
|
||||||
|
formatHTML(props)(note, targetPath, exportTasks)
|
||||||
|
)
|
||||||
|
|
||||||
|
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()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
58
browser/main/lib/dataApi/getContentFormatter.js
Normal file
58
browser/main/lib/dataApi/getContentFormatter.js
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import formatMarkdown from './formatMarkdown'
|
||||||
|
import formatHTML from './formatHTML'
|
||||||
|
import formatPDF from './formatPDF'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} storage
|
||||||
|
* @param {String} fileType
|
||||||
|
* @param {Object} config
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default function getContentFormatter(storage, fileType, config) {
|
||||||
|
if (fileType === 'md') {
|
||||||
|
return formatMarkdown({
|
||||||
|
storagePath: storage.path,
|
||||||
|
export: config.export
|
||||||
|
})
|
||||||
|
} else if (fileType === 'html') {
|
||||||
|
return formatHTML({
|
||||||
|
theme: config.ui.theme,
|
||||||
|
fontSize: config.preview.fontSize,
|
||||||
|
fontFamily: config.preview.fontFamily,
|
||||||
|
codeBlockTheme: config.preview.codeBlockTheme,
|
||||||
|
codeBlockFontFamily: config.editor.fontFamily,
|
||||||
|
lineNumber: config.preview.lineNumber,
|
||||||
|
indentSize: config.editor.indentSize,
|
||||||
|
scrollPastEnd: config.preview.scrollPastEnd,
|
||||||
|
smartQuotes: config.preview.smartQuotes,
|
||||||
|
breaks: config.preview.breaks,
|
||||||
|
sanitize: config.preview.sanitize,
|
||||||
|
customCSS: config.preview.customCSS,
|
||||||
|
allowCustomCSS: config.preview.allowCustomCSS,
|
||||||
|
storagePath: storage.path,
|
||||||
|
export: config.export,
|
||||||
|
RTL: config.editor.rtlEnabled /* && this.state.RTL */
|
||||||
|
})
|
||||||
|
} else if (fileType === 'pdf') {
|
||||||
|
return formatPDF({
|
||||||
|
theme: config.ui.theme,
|
||||||
|
fontSize: config.preview.fontSize,
|
||||||
|
fontFamily: config.preview.fontFamily,
|
||||||
|
codeBlockTheme: config.preview.codeBlockTheme,
|
||||||
|
codeBlockFontFamily: config.editor.fontFamily,
|
||||||
|
lineNumber: config.preview.lineNumber,
|
||||||
|
indentSize: config.editor.indentSize,
|
||||||
|
scrollPastEnd: config.preview.scrollPastEnd,
|
||||||
|
smartQuotes: config.preview.smartQuotes,
|
||||||
|
breaks: config.preview.breaks,
|
||||||
|
sanitize: config.preview.sanitize,
|
||||||
|
customCSS: config.preview.customCSS,
|
||||||
|
allowCustomCSS: config.preview.allowCustomCSS,
|
||||||
|
storagePath: storage.path,
|
||||||
|
export: config.export,
|
||||||
|
RTL: config.editor.rtlEnabled /* && this.state.RTL */
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
37
browser/main/lib/dataApi/getFilename.js
Normal file
37
browser/main/lib/dataApi/getFilename.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import filenamify from 'filenamify'
|
||||||
|
import i18n from 'browser/lib/i18n'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} note
|
||||||
|
* @param {String} fileType
|
||||||
|
* @param {String} directory
|
||||||
|
* @param {Object} deduplicator
|
||||||
|
*
|
||||||
|
* @return {String}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function getFilename(note, fileType, directory, deduplicator) {
|
||||||
|
const basename = note.title
|
||||||
|
? filenamify(note.title, { replacement: '_' })
|
||||||
|
: i18n.__('Untitled')
|
||||||
|
|
||||||
|
if (deduplicator) {
|
||||||
|
if (deduplicator[basename]) {
|
||||||
|
const filename = path.join(
|
||||||
|
directory,
|
||||||
|
`${basename} (${deduplicator[basename]}).${fileType}`
|
||||||
|
)
|
||||||
|
|
||||||
|
++deduplicator[basename]
|
||||||
|
|
||||||
|
return filename
|
||||||
|
} else {
|
||||||
|
deduplicator[basename] = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return path.join(directory, `${basename}.${fileType}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = getFilename
|
||||||
@@ -15,11 +15,14 @@ const dataApi = {
|
|||||||
updateNote: require('./updateNote'),
|
updateNote: require('./updateNote'),
|
||||||
deleteNote: require('./deleteNote'),
|
deleteNote: require('./deleteNote'),
|
||||||
moveNote: require('./moveNote'),
|
moveNote: require('./moveNote'),
|
||||||
|
exportNoteAs: require('./exportNoteAs'),
|
||||||
migrateFromV5Storage: require('./migrateFromV5Storage'),
|
migrateFromV5Storage: require('./migrateFromV5Storage'),
|
||||||
createSnippet: require('./createSnippet'),
|
createSnippet: require('./createSnippet'),
|
||||||
deleteSnippet: require('./deleteSnippet'),
|
deleteSnippet: require('./deleteSnippet'),
|
||||||
updateSnippet: require('./updateSnippet'),
|
updateSnippet: require('./updateSnippet'),
|
||||||
fetchSnippet: require('./fetchSnippet'),
|
fetchSnippet: require('./fetchSnippet'),
|
||||||
|
exportTag: require('./exportTag'),
|
||||||
|
getFilename: require('./getFilename'),
|
||||||
|
|
||||||
_migrateFromV6Storage: require('./migrateFromV6Storage'),
|
_migrateFromV6Storage: require('./migrateFromV6Storage'),
|
||||||
_resolveStorageData: require('./resolveStorageData'),
|
_resolveStorageData: require('./resolveStorageData'),
|
||||||
|
|||||||
184
browser/main/modals/PreferencesModal/ExportTab.js
Normal file
184
browser/main/modals/PreferencesModal/ExportTab.js
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import React from 'react'
|
||||||
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
|
import styles from './ConfigTab.styl'
|
||||||
|
import ConfigManager from 'browser/main/lib/ConfigManager'
|
||||||
|
import store from 'browser/main/store'
|
||||||
|
import _ from 'lodash'
|
||||||
|
import i18n from 'browser/lib/i18n'
|
||||||
|
|
||||||
|
const electron = require('electron')
|
||||||
|
const ipc = electron.ipcRenderer
|
||||||
|
|
||||||
|
class ExportTab extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
config: props.config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clearMessage() {
|
||||||
|
_.debounce(() => {
|
||||||
|
this.setState({
|
||||||
|
ExportAlert: null
|
||||||
|
})
|
||||||
|
}, 2000)()
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.handleSettingDone = () => {
|
||||||
|
this.setState({
|
||||||
|
ExportAlert: {
|
||||||
|
type: 'success',
|
||||||
|
message: i18n.__('Successfully applied!')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.handleSettingError = err => {
|
||||||
|
this.setState({
|
||||||
|
ExportAlert: {
|
||||||
|
type: 'error',
|
||||||
|
message:
|
||||||
|
err.message != null ? err.message : i18n.__('An error occurred!')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.oldExport = this.state.config.export
|
||||||
|
|
||||||
|
ipc.addListener('APP_SETTING_DONE', this.handleSettingDone)
|
||||||
|
ipc.addListener('APP_SETTING_ERROR', this.handleSettingError)
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
ipc.removeListener('APP_SETTING_DONE', this.handleSettingDone)
|
||||||
|
ipc.removeListener('APP_SETTING_ERROR', this.handleSettingError)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSaveButtonClick(e) {
|
||||||
|
const newConfig = {
|
||||||
|
export: this.state.config.export
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigManager.set(newConfig)
|
||||||
|
|
||||||
|
store.dispatch({
|
||||||
|
type: 'SET_UI',
|
||||||
|
config: newConfig
|
||||||
|
})
|
||||||
|
|
||||||
|
this.clearMessage()
|
||||||
|
this.props.haveToSave()
|
||||||
|
}
|
||||||
|
|
||||||
|
handleExportChange(e) {
|
||||||
|
const { config } = this.state
|
||||||
|
|
||||||
|
config.export = {
|
||||||
|
metadata: this.refs.metadata.value,
|
||||||
|
variable: !_.isNil(this.refs.variable)
|
||||||
|
? this.refs.variable.value
|
||||||
|
: config.export.variable,
|
||||||
|
prefixAttachmentFolder: this.refs.prefixAttachmentFolder.checked
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
config
|
||||||
|
})
|
||||||
|
|
||||||
|
if (_.isEqual(this.oldExport, config.export)) {
|
||||||
|
this.props.haveToSave()
|
||||||
|
} else {
|
||||||
|
this.props.haveToSave({
|
||||||
|
tab: 'Export',
|
||||||
|
type: 'warning',
|
||||||
|
message: i18n.__('Unsaved Changes!')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { config, ExportAlert } = this.state
|
||||||
|
|
||||||
|
const ExportAlertElement =
|
||||||
|
ExportAlert != null ? (
|
||||||
|
<p className={`alert ${ExportAlert.type}`}>{ExportAlert.message}</p>
|
||||||
|
) : null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div styleName='root'>
|
||||||
|
<div styleName='group'>
|
||||||
|
<div styleName='group-header'>{i18n.__('Export')}</div>
|
||||||
|
|
||||||
|
<div styleName='group-section'>
|
||||||
|
<div styleName='group-section-label'>{i18n.__('Metadata')}</div>
|
||||||
|
<div styleName='group-section-control'>
|
||||||
|
<select
|
||||||
|
value={config.export.metadata}
|
||||||
|
onChange={e => this.handleExportChange(e)}
|
||||||
|
ref='metadata'
|
||||||
|
>
|
||||||
|
<option value='DONT_EXPORT'>{i18n.__(`Don't export`)}</option>
|
||||||
|
<option value='MERGE_HEADER'>
|
||||||
|
{i18n.__('Merge with the header')}
|
||||||
|
</option>
|
||||||
|
<option value='MERGE_VARIABLE'>
|
||||||
|
{i18n.__('Merge with a variable')}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{config.export.metadata === 'MERGE_VARIABLE' && (
|
||||||
|
<div styleName='group-section'>
|
||||||
|
<div styleName='group-section-label'>
|
||||||
|
{i18n.__('Variable Name')}
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section-control'>
|
||||||
|
<input
|
||||||
|
styleName='group-section-control-input'
|
||||||
|
onChange={e => this.handleExportChange(e)}
|
||||||
|
ref='variable'
|
||||||
|
value={config.export.variable}
|
||||||
|
type='text'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div styleName='group-checkBoxSection'>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
onChange={e => this.handleExportChange(e)}
|
||||||
|
checked={config.export.prefixAttachmentFolder}
|
||||||
|
ref='prefixAttachmentFolder'
|
||||||
|
type='checkbox'
|
||||||
|
/>
|
||||||
|
|
||||||
|
{i18n.__('Prefix attachment folder')}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div styleName='group-control'>
|
||||||
|
<button
|
||||||
|
styleName='group-control-rightButton'
|
||||||
|
onClick={e => this.handleSaveButtonClick(e)}
|
||||||
|
>
|
||||||
|
{i18n.__('Save')}
|
||||||
|
</button>
|
||||||
|
{ExportAlertElement}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExportTab.propTypes = {
|
||||||
|
dispatch: PropTypes.func,
|
||||||
|
haveToSave: PropTypes.func
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CSSModules(ExportTab, styles)
|
||||||
@@ -16,25 +16,78 @@ class InfoTab extends React.Component {
|
|||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
config: this.props.config
|
config: this.props.config,
|
||||||
|
subscriptionFormStatus: 'idle',
|
||||||
|
subscriptionFormErrorMessage: null,
|
||||||
|
subscriptionFormEmail: ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const { autoUpdateEnabled, amaEnabled } = ConfigManager.get()
|
||||||
|
|
||||||
|
this.setState({ config: { autoUpdateEnabled, amaEnabled } })
|
||||||
|
}
|
||||||
|
|
||||||
handleLinkClick(e) {
|
handleLinkClick(e) {
|
||||||
shell.openExternal(e.currentTarget.href)
|
shell.openExternal(e.currentTarget.href)
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
handleConfigChange(e) {
|
handleConfigChange(e) {
|
||||||
const newConfig = { amaEnabled: this.refs.amaEnabled.checked }
|
const newConfig = {
|
||||||
|
amaEnabled: this.refs.amaEnabled.checked,
|
||||||
|
autoUpdateEnabled: this.refs.autoUpdateEnabled.checked
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({ config: newConfig })
|
this.setState({ config: newConfig })
|
||||||
|
return newConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSubscriptionFormSubmit(e) {
|
||||||
|
e.preventDefault()
|
||||||
|
this.setState({
|
||||||
|
subscriptionFormStatus: 'sending',
|
||||||
|
subscriptionFormErrorMessage: null
|
||||||
|
})
|
||||||
|
|
||||||
|
fetch(
|
||||||
|
'https://boostmails.boostio.co/api/public/lists/5f434dccd05f3160b41c0d49/subscriptions',
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({ email: this.state.subscriptionFormEmail })
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(response => {
|
||||||
|
if (response.status >= 400) {
|
||||||
|
return response.text().then(text => {
|
||||||
|
throw new Error(text)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
subscriptionFormStatus: 'done'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.setState({
|
||||||
|
subscriptionFormStatus: 'idle',
|
||||||
|
subscriptionFormErrorMessage: error.message
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSubscriptionFormEmailChange(e) {
|
||||||
|
this.setState({
|
||||||
|
subscriptionFormEmail: e.target.value
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSaveButtonClick(e) {
|
handleSaveButtonClick(e) {
|
||||||
const newConfig = {
|
const newConfig = this.state.config
|
||||||
amaEnabled: this.state.config.amaEnabled
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!newConfig.amaEnabled) {
|
if (!newConfig.amaEnabled) {
|
||||||
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('DISABLE_AMA')
|
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('DISABLE_AMA')
|
||||||
@@ -61,20 +114,17 @@ class InfoTab extends React.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleAutoUpdate() {
|
|
||||||
const newConfig = {
|
|
||||||
autoUpdateEnabled: !this.state.config.autoUpdateEnabled
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({ config: newConfig })
|
|
||||||
ConfigManager.set(newConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
infoMessage() {
|
infoMessage() {
|
||||||
const { amaMessage } = this.state
|
const { amaMessage } = this.state
|
||||||
return amaMessage ? <p styleName='policy-confirm'>{amaMessage}</p> : null
|
return amaMessage ? <p styleName='policy-confirm'>{amaMessage}</p> : null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleAutoUpdateChange() {
|
||||||
|
const { autoUpdateEnabled } = this.handleConfigChange()
|
||||||
|
|
||||||
|
ConfigManager.set({ autoUpdateEnabled })
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div styleName='root'>
|
<div styleName='root'>
|
||||||
@@ -134,6 +184,40 @@ class InfoTab extends React.Component {
|
|||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
<div styleName='group-header--sub'>Subscribe Update Notes</div>
|
||||||
|
{this.state.subscriptionFormStatus === 'done' ? (
|
||||||
|
<div>
|
||||||
|
<blockquote color={{ color: 'green' }}>
|
||||||
|
Thanks for the subscription!
|
||||||
|
</blockquote>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div>
|
||||||
|
{this.state.subscriptionFormErrorMessage != null && (
|
||||||
|
<blockquote style={{ color: 'red' }}>
|
||||||
|
{this.state.subscriptionFormErrorMessage}
|
||||||
|
</blockquote>
|
||||||
|
)}
|
||||||
|
<form onSubmit={e => this.handleSubscriptionFormSubmit(e)}>
|
||||||
|
<input
|
||||||
|
styleName='subscription-email-input'
|
||||||
|
placeholder='E-mail'
|
||||||
|
type='email'
|
||||||
|
onChange={e => this.handleSubscriptionFormEmailChange(e)}
|
||||||
|
disabled={this.state.subscriptionFormStatus === 'sending'}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
styleName='subscription-submit-button'
|
||||||
|
type='submit'
|
||||||
|
disabled={this.state.subscriptionFormStatus === 'sending'}
|
||||||
|
>
|
||||||
|
Subscribe
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<hr />
|
||||||
|
|
||||||
<div styleName='group-header--sub'>{i18n.__('About')}</div>
|
<div styleName='group-header--sub'>{i18n.__('About')}</div>
|
||||||
|
|
||||||
<div styleName='top'>
|
<div styleName='top'>
|
||||||
@@ -181,7 +265,8 @@ class InfoTab extends React.Component {
|
|||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type='checkbox'
|
type='checkbox'
|
||||||
onChange={this.toggleAutoUpdate.bind(this)}
|
ref='autoUpdateEnabled'
|
||||||
|
onChange={() => this.handleAutoUpdateChange()}
|
||||||
checked={this.state.config.autoUpdateEnabled}
|
checked={this.state.config.autoUpdateEnabled}
|
||||||
/>
|
/>
|
||||||
{i18n.__('Enable Auto Update')}
|
{i18n.__('Enable Auto Update')}
|
||||||
|
|||||||
@@ -33,6 +33,35 @@
|
|||||||
.separate-line
|
.separate-line
|
||||||
margin 40px 0
|
margin 40px 0
|
||||||
|
|
||||||
|
.subscription-email-input
|
||||||
|
height 35px
|
||||||
|
vertical-align middle
|
||||||
|
width 200px
|
||||||
|
font-size $tab--button-font-size
|
||||||
|
border solid 1px $border-color
|
||||||
|
border-radius 2px
|
||||||
|
padding 0 5px
|
||||||
|
margin-right 5px
|
||||||
|
outline none
|
||||||
|
&:disabled
|
||||||
|
background-color $ui-input--disabled-backgroundColor
|
||||||
|
|
||||||
|
.subscription-submit-button
|
||||||
|
margin-top 10px
|
||||||
|
height 35px
|
||||||
|
border-radius 2px
|
||||||
|
border none
|
||||||
|
background-color alpha(#1EC38B, 90%)
|
||||||
|
padding-left 20px
|
||||||
|
padding-right 20px
|
||||||
|
text-decoration none
|
||||||
|
color white
|
||||||
|
font-weight 600
|
||||||
|
font-size 16px
|
||||||
|
&:hover
|
||||||
|
background-color #1EC38B
|
||||||
|
transition 0.2s
|
||||||
|
|
||||||
.policy-submit
|
.policy-submit
|
||||||
margin-top 10px
|
margin-top 10px
|
||||||
height 35px
|
height 35px
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import UiTab from './UiTab'
|
|||||||
import InfoTab from './InfoTab'
|
import InfoTab from './InfoTab'
|
||||||
import Crowdfunding from './Crowdfunding'
|
import Crowdfunding from './Crowdfunding'
|
||||||
import StoragesTab from './StoragesTab'
|
import StoragesTab from './StoragesTab'
|
||||||
|
import ExportTab from './ExportTab'
|
||||||
import SnippetTab from './SnippetTab'
|
import SnippetTab from './SnippetTab'
|
||||||
import PluginsTab from './PluginsTab'
|
import PluginsTab from './PluginsTab'
|
||||||
import Blog from './Blog'
|
import Blog from './Blog'
|
||||||
@@ -24,7 +25,8 @@ class Preferences extends React.Component {
|
|||||||
currentTab: 'STORAGES',
|
currentTab: 'STORAGES',
|
||||||
UIAlert: '',
|
UIAlert: '',
|
||||||
HotkeyAlert: '',
|
HotkeyAlert: '',
|
||||||
BlogAlert: ''
|
BlogAlert: '',
|
||||||
|
ExportAlert: ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,6 +83,15 @@ class Preferences extends React.Component {
|
|||||||
haveToSave={alert => this.setState({ BlogAlert: alert })}
|
haveToSave={alert => this.setState({ BlogAlert: alert })}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
case 'EXPORT':
|
||||||
|
return (
|
||||||
|
<ExportTab
|
||||||
|
dispatch={dispatch}
|
||||||
|
config={config}
|
||||||
|
data={data}
|
||||||
|
haveToSave={alert => this.setState({ ExportAlert: alert })}
|
||||||
|
/>
|
||||||
|
)
|
||||||
case 'SNIPPET':
|
case 'SNIPPET':
|
||||||
return <SnippetTab dispatch={dispatch} config={config} data={data} />
|
return <SnippetTab dispatch={dispatch} config={config} data={data} />
|
||||||
case 'PLUGINS':
|
case 'PLUGINS':
|
||||||
@@ -131,6 +142,11 @@ class Preferences extends React.Component {
|
|||||||
{ target: 'INFO', label: i18n.__('About') },
|
{ target: 'INFO', label: i18n.__('About') },
|
||||||
{ target: 'CROWDFUNDING', label: i18n.__('Crowdfunding') },
|
{ target: 'CROWDFUNDING', label: i18n.__('Crowdfunding') },
|
||||||
{ target: 'BLOG', label: i18n.__('Blog'), Blog: this.state.BlogAlert },
|
{ target: 'BLOG', label: i18n.__('Blog'), Blog: this.state.BlogAlert },
|
||||||
|
{
|
||||||
|
target: 'EXPORT',
|
||||||
|
label: i18n.__('Export'),
|
||||||
|
Export: this.state.ExportAlert
|
||||||
|
},
|
||||||
{ target: 'SNIPPET', label: i18n.__('Snippets') },
|
{ target: 'SNIPPET', label: i18n.__('Snippets') },
|
||||||
{ target: 'PLUGINS', label: i18n.__('Plugins') }
|
{ target: 'PLUGINS', label: i18n.__('Plugins') }
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ module.exports = function(grunt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ChildProcess.exec(
|
ChildProcess.exec(
|
||||||
`codesign --verbose --deep --force --sign \"${OSX_COMMON_NAME}\" dist/Boostnote-darwin-x64/Boostnote.app`,
|
`codesign --verbose --deep --force --timestamp=none --sign \"${OSX_COMMON_NAME}\" dist/Boostnote-darwin-x64/Boostnote.app`,
|
||||||
function(err, stdout, stderr) {
|
function(err, stdout, stderr) {
|
||||||
grunt.log.writeln(stdout)
|
grunt.log.writeln(stdout)
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ if (!singleInstance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var isUpdateReady = false
|
var isUpdateReady = false
|
||||||
|
let updateFound = false
|
||||||
|
|
||||||
var ghReleasesOpts = {
|
var ghReleasesOpts = {
|
||||||
repo: 'BoostIO/boost-releases',
|
repo: 'BoostIO/boost-releases',
|
||||||
@@ -36,25 +37,33 @@ const updater = new GhReleases(ghReleasesOpts)
|
|||||||
|
|
||||||
// Check for updates
|
// Check for updates
|
||||||
// `status` returns true if there is a new update available
|
// `status` returns true if there is a new update available
|
||||||
function checkUpdate() {
|
function checkUpdate(manualTriggered = false) {
|
||||||
if (!isPackaged) {
|
if (!isPackaged) {
|
||||||
// Prevents app from attempting to update when in dev mode.
|
// Prevents app from attempting to update when in dev mode.
|
||||||
console.log('Updates are disabled in Development mode, see main-app.js')
|
console.log('Updates are disabled in Development mode, see main-app.js')
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if (!electronConfig.get('autoUpdateEnabled', true)) return
|
|
||||||
if (process.platform === 'linux' || isUpdateReady) {
|
// End if auto updates disabled and it is an automatic check
|
||||||
|
if (!electronConfig.get('autoUpdateEnabled', true) && !manualTriggered) return
|
||||||
|
|
||||||
|
if (process.platform === 'linux' || isUpdateReady || updateFound) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
updater.check((err, status) => {
|
updater.check((err, status) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
var isLatest = err.message === 'There is no newer version.'
|
var isLatest = err.message === 'There is no newer version.'
|
||||||
if (!isLatest) console.error('Updater error! %s', err.message)
|
if (!isLatest) console.error('Updater error! %s', err.message)
|
||||||
|
mainWindow.webContents.send(
|
||||||
|
'update-not-found',
|
||||||
|
isLatest ? 'There is no newer version.' : 'Updater error'
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (status) {
|
if (status) {
|
||||||
mainWindow.webContents.send('update-found', 'Update available!')
|
mainWindow.webContents.send('update-found', 'Update available!')
|
||||||
updater.download()
|
updateFound = true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -63,6 +72,7 @@ updater.on('update-downloaded', info => {
|
|||||||
if (mainWindow != null) {
|
if (mainWindow != null) {
|
||||||
mainWindow.webContents.send('update-ready', 'Update available!')
|
mainWindow.webContents.send('update-ready', 'Update available!')
|
||||||
isUpdateReady = true
|
isUpdateReady = true
|
||||||
|
updateFound = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -77,6 +87,14 @@ ipc.on('update-app-confirm', function(event, msg) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ipc.on('update-cancel', () => {
|
||||||
|
updateFound = false
|
||||||
|
})
|
||||||
|
|
||||||
|
ipc.on('update-download-confirm', () => {
|
||||||
|
updater.download()
|
||||||
|
})
|
||||||
|
|
||||||
app.on('window-all-closed', function() {
|
app.on('window-all-closed', function() {
|
||||||
app.quit()
|
app.quit()
|
||||||
})
|
})
|
||||||
@@ -113,7 +131,7 @@ app.on('ready', function() {
|
|||||||
if (isUpdateReady) {
|
if (isUpdateReady) {
|
||||||
mainWindow.webContents.send('update-ready', 'Update available!')
|
mainWindow.webContents.send('update-ready', 'Update available!')
|
||||||
} else {
|
} else {
|
||||||
checkUpdate()
|
checkUpdate(msg === 'manual')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, 10 * 1000)
|
}, 10 * 1000)
|
||||||
|
|||||||
@@ -178,6 +178,18 @@ const file = {
|
|||||||
mainWindow.webContents.send('list:isMarkdownNote', 'print')
|
mainWindow.webContents.send('list:isMarkdownNote', 'print')
|
||||||
mainWindow.webContents.send('print')
|
mainWindow.webContents.send('print')
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'separator'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Update',
|
||||||
|
click() {
|
||||||
|
mainWindow.webContents.send('update')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'separator'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -472,9 +484,21 @@ const help = {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const team = {
|
||||||
|
label: 'For Team',
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
label: 'BoostHub',
|
||||||
|
click: async () => {
|
||||||
|
shell.openExternal('https://boosthub.io/')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
module.exports =
|
module.exports =
|
||||||
process.platform === 'darwin'
|
process.platform === 'darwin'
|
||||||
? [boost, file, edit, view, window, help]
|
? [boost, file, edit, view, window, team, help]
|
||||||
: process.platform === 'win32'
|
: process.platform === 'win32'
|
||||||
? [boost, file, view, help]
|
? [boost, file, view, team, help]
|
||||||
: [file, view, help]
|
: [file, view, team, help]
|
||||||
|
|||||||
@@ -202,7 +202,6 @@
|
|||||||
"Create new folder": "Ordner erstellen",
|
"Create new folder": "Ordner erstellen",
|
||||||
"Folder name": "Ordnername",
|
"Folder name": "Ordnername",
|
||||||
"Create": "Erstellen",
|
"Create": "Erstellen",
|
||||||
"Untitled": "Neuer Ordner",
|
|
||||||
"Unlink Storage": "Speicherverknüpfung aufheben",
|
"Unlink Storage": "Speicherverknüpfung aufheben",
|
||||||
"Unlinking removes this linked storage from Boostnote. No data is removed, please manually delete the folder from your hard drive if needed.": "Die Verknüpfung des Speichers mit Boostnote wird entfernt. Es werden keine Daten gelöscht. Um die Daten dauerhaft zu löschen musst du den Ordner auf der Festplatte manuell entfernen.",
|
"Unlinking removes this linked storage from Boostnote. No data is removed, please manually delete the folder from your hard drive if needed.": "Die Verknüpfung des Speichers mit Boostnote wird entfernt. Es werden keine Daten gelöscht. Um die Daten dauerhaft zu löschen musst du den Ordner auf der Festplatte manuell entfernen.",
|
||||||
"Empty note": "Leere Notiz",
|
"Empty note": "Leere Notiz",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "boost",
|
"name": "boost",
|
||||||
"productName": "Boostnote",
|
"productName": "Boostnote",
|
||||||
"version": "0.16.0",
|
"version": "0.16.1",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"description": "Boostnote",
|
"description": "Boostnote",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
@@ -149,7 +149,7 @@
|
|||||||
"css-loader": "^0.19.0",
|
"css-loader": "^0.19.0",
|
||||||
"devtron": "^1.1.0",
|
"devtron": "^1.1.0",
|
||||||
"dom-storage": "^2.0.2",
|
"dom-storage": "^2.0.2",
|
||||||
"electron": "4",
|
"electron": "18",
|
||||||
"electron-debug": "^2.2.0",
|
"electron-debug": "^2.2.0",
|
||||||
"electron-devtools-installer": "^2.2.4",
|
"electron-devtools-installer": "^2.2.4",
|
||||||
"electron-packager": "^12.2.0",
|
"electron-packager": "^12.2.0",
|
||||||
|
|||||||
62
readme.md
62
readme.md
@@ -1,12 +1,26 @@
|
|||||||
> [We've launched desktop and mobile app of the new Boost Note now.](https://github.com/BoostIO/BoostNote.next)
|
> # New Boost Note app is available!
|
||||||
|
|
||||||
> ### [Boost Note for Teams](https://boosthub.io/)
|
|
||||||
>
|
>
|
||||||
> We've developed a collaborative workspace app called "Boost Hub" for developer teams.
|
> We've launched a new Boost Note app which supports real-time collaborative writing.
|
||||||
>
|
>
|
||||||
> It's customizable and easy to optimize for your team like rego blocks and even lets you edit documents together in real-time!
|
> And it is open sourced too! Please check it out! https://github.com/BoostIO/BoostNote-App
|
||||||
|
>
|
||||||
|
> ## 📦 Download App
|
||||||
|
>
|
||||||
|
> ### 🖥 Desktop
|
||||||
|
>
|
||||||
|
> - [🌎 Web App (boostnote.io)](https://boostnote.io)
|
||||||
|
> - [🍎 macOS (.dmg)](https://github.com/BoostIO/BoostNote-App/releases/latest/download/boost-note-mac.dmg)
|
||||||
|
> - [:framed_picture: Windows (.exe NSIS)](https://github.com/BoostIO/BoostNote-App/releases/latest/download/boost-note-win.exe)
|
||||||
|
> - [🐧 Linux (.deb)](https://github.com/BoostIO/BoostNote-App/releases/latest/download/boost-note-linux.deb)
|
||||||
|
> - [🐧 Linux (.rpm)](https://github.com/BoostIO/BoostNote-App/releases/latest/download/boost-note-linux.rpm)
|
||||||
|
>
|
||||||
|
> ### 📱 Mobile
|
||||||
|
>
|
||||||
|
> - [🌎 Mobile Web App (m.boostnote.io)](https://m.boostnote.io)
|
||||||
|
> - [🍏 iOS (Apple App Store)](https://apps.apple.com/gb/app/boost-note-mobile/id1576176505)
|
||||||
|
> - [🤖 Android (Google Play Store)](https://play.google.com/store/apps/details?id=com.boostio.boostnote2021)
|
||||||
|
|
||||||

|
<h1 align="center">BoostNote-Legacy</h1>
|
||||||
|
|
||||||
<h4 align="center">Note-taking app for programmers. </h4>
|
<h4 align="center">Note-taking app for programmers. </h4>
|
||||||
<h5 align="center">Apps available for Mac, Windows and Linux.</h5>
|
<h5 align="center">Apps available for Mac, Windows and Linux.</h5>
|
||||||
@@ -21,42 +35,6 @@
|
|||||||
|
|
||||||
[Find the latest release of Boostnote here!](https://github.com/BoostIO/boost-releases/releases/)
|
[Find the latest release of Boostnote here!](https://github.com/BoostIO/boost-releases/releases/)
|
||||||
|
|
||||||
## Roadmap
|
|
||||||
|
|
||||||
[Boost Note Roadmap 2020](https://medium.com/boostnote/boost-note-roadmap-2020-9f06a642f5f1)
|
|
||||||
|
|
||||||
## Authors & Maintainers
|
|
||||||
|
|
||||||
- [Rokt33r](https://github.com/rokt33r)
|
|
||||||
- [KZ](https://github.com/kazup01)
|
|
||||||
- [ZeroX-DG](https://github.com/ZeroX-DG)
|
|
||||||
|
|
||||||
## Contributors
|
|
||||||
|
|
||||||
Thank you to all the people who have contributed to Boostnote!
|
|
||||||
|
|
||||||
<a href="https://github.com/BoostIO/Boostnote/graphs/contributors"><img src="https://opencollective.com/boostnoteio/contributors.svg?width=890" /></a>
|
|
||||||
|
|
||||||
## Supporting Boostnote
|
|
||||||
|
|
||||||
Boostnote is an open source project. It's an independent project with its ongoing development made possible thanks to the support by our amazing backers.
|
|
||||||
|
|
||||||
Issues on Boostnote can be funded by anyone and the money will be distributed to contributors and maintainers. If you use Boostnote please consider becoming a backer:
|
|
||||||
|
|
||||||
[](https://issuehunt.io/repos/53266139)
|
|
||||||
|
|
||||||
## Community
|
|
||||||
|
|
||||||
- [Facebook Group](https://www.facebook.com/groups/boostnote/)
|
|
||||||
- [Twitter](https://twitter.com/boostnoteapp)
|
|
||||||
- [Slack Group](https://join.slack.com/t/boostnote-group/shared_invite/zt-cun7pas3-WwkaezxHBB1lCbUHrwQLXw)
|
|
||||||
- [Blog](https://medium.com/boostnote)
|
|
||||||
- [Reddit](https://www.reddit.com/r/Boostnote/)
|
|
||||||
|
|
||||||
### Boostnote mobile
|
|
||||||
A community project developing a mobile cross-platform version of boostnote for iOS and Android can be found here: [NoteApp](https://github.com/T0M0F/NoteApp)
|
|
||||||
|
|
||||||
|
|
||||||
#### More Information
|
#### More Information
|
||||||
|
|
||||||
- Website: https://boostnote.io
|
- Website: https://boostnote.io
|
||||||
|
|||||||
@@ -702,14 +702,15 @@ it('should remove the all ":storage" and noteKey references', function() {
|
|||||||
' </p>\n' +
|
' </p>\n' +
|
||||||
' </body>\n' +
|
' </body>\n' +
|
||||||
'</html>'
|
'</html>'
|
||||||
const actual = systemUnderTest.removeStorageAndNoteReferences(
|
const actual = systemUnderTest.replaceStorageReferences(
|
||||||
testInput,
|
testInput,
|
||||||
noteKey
|
noteKey,
|
||||||
|
systemUnderTest.DESTINATION_FOLDER
|
||||||
)
|
)
|
||||||
expect(actual).toEqual(expectedOutput)
|
expect(actual).toEqual(expectedOutput)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should make sure that "removeStorageAndNoteReferences" works with markdown content as well', function() {
|
it('should make sure that "replaceStorageReferences" works with markdown content as well', function() {
|
||||||
const noteKey = 'noteKey'
|
const noteKey = 'noteKey'
|
||||||
const testInput =
|
const testInput =
|
||||||
'Test input' +
|
'Test input' +
|
||||||
@@ -736,9 +737,113 @@ it('should make sure that "removeStorageAndNoteReferences" works with markdown c
|
|||||||
systemUnderTest.DESTINATION_FOLDER +
|
systemUnderTest.DESTINATION_FOLDER +
|
||||||
path.posix.sep +
|
path.posix.sep +
|
||||||
'pdf.pdf)'
|
'pdf.pdf)'
|
||||||
const actual = systemUnderTest.removeStorageAndNoteReferences(
|
const actual = systemUnderTest.replaceStorageReferences(
|
||||||
testInput,
|
testInput,
|
||||||
noteKey
|
noteKey,
|
||||||
|
systemUnderTest.DESTINATION_FOLDER
|
||||||
|
)
|
||||||
|
expect(actual).toEqual(expectedOutput)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should replace the all ":storage" references', function() {
|
||||||
|
const storageFolder = systemUnderTest.DESTINATION_FOLDER
|
||||||
|
const noteKey = 'noteKey'
|
||||||
|
const testInput =
|
||||||
|
'<html>\n' +
|
||||||
|
' <head>\n' +
|
||||||
|
' //header\n' +
|
||||||
|
' </head>\n' +
|
||||||
|
' <body data-theme="default">\n' +
|
||||||
|
' <h2 data-line="0" id="Headline">Headline</h2>\n' +
|
||||||
|
' <p data-line="2">\n' +
|
||||||
|
' <img src=":storage' +
|
||||||
|
mdurl.encode(path.sep) +
|
||||||
|
noteKey +
|
||||||
|
mdurl.encode(path.sep) +
|
||||||
|
'0.6r4zdgc22xp.png" alt="dummyImage.png" >\n' +
|
||||||
|
' </p>\n' +
|
||||||
|
' <p data-line="4">\n' +
|
||||||
|
' <a href=":storage' +
|
||||||
|
mdurl.encode(path.sep) +
|
||||||
|
noteKey +
|
||||||
|
mdurl.encode(path.sep) +
|
||||||
|
'0.q2i4iw0fyx.pdf">dummyPDF.pdf</a>\n' +
|
||||||
|
' </p>\n' +
|
||||||
|
' <p data-line="6">\n' +
|
||||||
|
' <img src=":storage' +
|
||||||
|
mdurl.encode(path.sep) +
|
||||||
|
noteKey +
|
||||||
|
mdurl.encode(path.sep) +
|
||||||
|
'd6c5ee92.jpg" alt="dummyImage2.jpg">\n' +
|
||||||
|
' </p>\n' +
|
||||||
|
' </body>\n' +
|
||||||
|
'</html>'
|
||||||
|
const expectedOutput =
|
||||||
|
'<html>\n' +
|
||||||
|
' <head>\n' +
|
||||||
|
' //header\n' +
|
||||||
|
' </head>\n' +
|
||||||
|
' <body data-theme="default">\n' +
|
||||||
|
' <h2 data-line="0" id="Headline">Headline</h2>\n' +
|
||||||
|
' <p data-line="2">\n' +
|
||||||
|
' <img src="' +
|
||||||
|
storageFolder +
|
||||||
|
path.sep +
|
||||||
|
'0.6r4zdgc22xp.png" alt="dummyImage.png" >\n' +
|
||||||
|
' </p>\n' +
|
||||||
|
' <p data-line="4">\n' +
|
||||||
|
' <a href="' +
|
||||||
|
storageFolder +
|
||||||
|
path.sep +
|
||||||
|
'0.q2i4iw0fyx.pdf">dummyPDF.pdf</a>\n' +
|
||||||
|
' </p>\n' +
|
||||||
|
' <p data-line="6">\n' +
|
||||||
|
' <img src="' +
|
||||||
|
storageFolder +
|
||||||
|
path.sep +
|
||||||
|
'd6c5ee92.jpg" alt="dummyImage2.jpg">\n' +
|
||||||
|
' </p>\n' +
|
||||||
|
' </body>\n' +
|
||||||
|
'</html>'
|
||||||
|
const actual = systemUnderTest.replaceStorageReferences(
|
||||||
|
testInput,
|
||||||
|
noteKey,
|
||||||
|
systemUnderTest.DESTINATION_FOLDER
|
||||||
|
)
|
||||||
|
expect(actual).toEqual(expectedOutput)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should make sure that "replaceStorageReferences" works with markdown content as well', function() {
|
||||||
|
const noteKey = 'noteKey'
|
||||||
|
const testInput =
|
||||||
|
'Test input' +
|
||||||
|
' \n' +
|
||||||
|
'[pdf](' +
|
||||||
|
systemUnderTest.STORAGE_FOLDER_PLACEHOLDER +
|
||||||
|
path.posix.sep +
|
||||||
|
noteKey +
|
||||||
|
path.posix.sep +
|
||||||
|
'pdf.pdf)'
|
||||||
|
|
||||||
|
const expectedOutput =
|
||||||
|
'Test input' +
|
||||||
|
' \n' +
|
||||||
|
'[pdf](' +
|
||||||
|
systemUnderTest.DESTINATION_FOLDER +
|
||||||
|
path.posix.sep +
|
||||||
|
'pdf.pdf)'
|
||||||
|
const actual = systemUnderTest.replaceStorageReferences(
|
||||||
|
testInput,
|
||||||
|
noteKey,
|
||||||
|
systemUnderTest.DESTINATION_FOLDER
|
||||||
)
|
)
|
||||||
expect(actual).toEqual(expectedOutput)
|
expect(actual).toEqual(expectedOutput)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -52,12 +52,20 @@ test.serial('Export a folder', t => {
|
|||||||
}
|
}
|
||||||
input2.title = 'input2'
|
input2.title = 'input2'
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
export: {
|
||||||
|
metadata: 'DONT_EXPORT',
|
||||||
|
variable: 'boostnote',
|
||||||
|
prefixAttachmentFolder: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return createNote(storageKey, input1)
|
return createNote(storageKey, input1)
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return createNote(storageKey, input2)
|
return createNote(storageKey, input2)
|
||||||
})
|
})
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return exportFolder(storageKey, folderKey, 'md', storagePath)
|
return exportFolder(storageKey, folderKey, 'md', storagePath, config)
|
||||||
})
|
})
|
||||||
.then(function assert() {
|
.then(function assert() {
|
||||||
let filePath = path.join(storagePath, 'input1.md')
|
let filePath = path.join(storagePath, 'input1.md')
|
||||||
|
|||||||
@@ -35,7 +35,16 @@ test.serial('Export a storage', t => {
|
|||||||
acc[folder.key] = folder.name
|
acc[folder.key] = folder.name
|
||||||
return acc
|
return acc
|
||||||
}, {})
|
}, {})
|
||||||
return exportStorage(storageKey, 'md', exportDir).then(() => {
|
|
||||||
|
const config = {
|
||||||
|
export: {
|
||||||
|
metadata: 'DONT_EXPORT',
|
||||||
|
variable: 'boostnote',
|
||||||
|
prefixAttachmentFolder: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return exportStorage(storageKey, 'md', exportDir, config).then(() => {
|
||||||
notes.forEach(note => {
|
notes.forEach(note => {
|
||||||
const noteDir = path.join(
|
const noteDir = path.join(
|
||||||
exportDir,
|
exportDir,
|
||||||
|
|||||||
415
yarn.lock
415
yarn.lock
@@ -75,6 +75,22 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
arrify "^1.0.1"
|
arrify "^1.0.1"
|
||||||
|
|
||||||
|
"@electron/get@^1.13.0":
|
||||||
|
version "1.14.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.14.1.tgz#16ba75f02dffb74c23965e72d617adc721d27f40"
|
||||||
|
integrity sha512-BrZYyL/6m0ZXz/lDxy/nlVhQz+WF+iPS6qXolEU8atw7h6v1aYkjwJZ63m+bJMBTxDE66X+r2tPS4a/8C82sZw==
|
||||||
|
dependencies:
|
||||||
|
debug "^4.1.1"
|
||||||
|
env-paths "^2.2.0"
|
||||||
|
fs-extra "^8.1.0"
|
||||||
|
got "^9.6.0"
|
||||||
|
progress "^2.0.3"
|
||||||
|
semver "^6.2.0"
|
||||||
|
sumchecker "^3.0.1"
|
||||||
|
optionalDependencies:
|
||||||
|
global-agent "^3.0.0"
|
||||||
|
global-tunnel-ng "^2.7.1"
|
||||||
|
|
||||||
"@enyaxu/markdown-it-anchor@^5.0.2":
|
"@enyaxu/markdown-it-anchor@^5.0.2":
|
||||||
version "5.0.2"
|
version "5.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/@enyaxu/markdown-it-anchor/-/markdown-it-anchor-5.0.2.tgz#d173f7b60b492aabc17dfba864c4d071f5595f72"
|
resolved "https://registry.yarnpkg.com/@enyaxu/markdown-it-anchor/-/markdown-it-anchor-5.0.2.tgz#d173f7b60b492aabc17dfba864c4d071f5595f72"
|
||||||
@@ -116,16 +132,28 @@
|
|||||||
fs-plus "2.x"
|
fs-plus "2.x"
|
||||||
optimist "~0.4.0"
|
optimist "~0.4.0"
|
||||||
|
|
||||||
|
"@sindresorhus/is@^0.14.0":
|
||||||
|
version "0.14.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
|
||||||
|
integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==
|
||||||
|
|
||||||
"@susisu/mte-kernel@^2.0.0":
|
"@susisu/mte-kernel@^2.0.0":
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@susisu/mte-kernel/-/mte-kernel-2.0.0.tgz#da3354d6a07ea27f36ec91d9fccf6bfa9010d00e"
|
resolved "https://registry.yarnpkg.com/@susisu/mte-kernel/-/mte-kernel-2.0.0.tgz#da3354d6a07ea27f36ec91d9fccf6bfa9010d00e"
|
||||||
dependencies:
|
dependencies:
|
||||||
meaw "^2.0.0"
|
meaw "^2.0.0"
|
||||||
|
|
||||||
"@types/node@^10.12.18":
|
"@szmarczak/http-timer@^1.1.2":
|
||||||
version "10.17.0"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.0.tgz#537c61a1df699a8331c79dab2ccc2c8799873c66"
|
resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421"
|
||||||
integrity sha512-wuJwN2KV4tIRz1bu9vq5kSPasJ8IsEjZaP1ZR7KlmdUZvGF/rXy8DmXOVwUD0kAtvtJ7aqMKPqUXC0NUTDbrDg==
|
integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==
|
||||||
|
dependencies:
|
||||||
|
defer-to-connect "^1.0.1"
|
||||||
|
|
||||||
|
"@types/node@^16.11.26":
|
||||||
|
version "16.18.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.3.tgz#d7f7ba828ad9e540270f01ce00d391c54e6e0abc"
|
||||||
|
integrity sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==
|
||||||
|
|
||||||
"JSV@>= 4.0.x":
|
"JSV@>= 4.0.x":
|
||||||
version "4.0.2"
|
version "4.0.2"
|
||||||
@@ -1368,6 +1396,11 @@ body-parser@1.18.2:
|
|||||||
raw-body "2.3.2"
|
raw-body "2.3.2"
|
||||||
type-is "~1.6.15"
|
type-is "~1.6.15"
|
||||||
|
|
||||||
|
boolean@^3.0.1:
|
||||||
|
version "3.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b"
|
||||||
|
integrity sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==
|
||||||
|
|
||||||
boxen@^1.2.1:
|
boxen@^1.2.1:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"
|
resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"
|
||||||
@@ -1519,6 +1552,19 @@ cache-base@^1.0.1:
|
|||||||
union-value "^1.0.0"
|
union-value "^1.0.0"
|
||||||
unset-value "^1.0.0"
|
unset-value "^1.0.0"
|
||||||
|
|
||||||
|
cacheable-request@^6.0.0:
|
||||||
|
version "6.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912"
|
||||||
|
integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==
|
||||||
|
dependencies:
|
||||||
|
clone-response "^1.0.2"
|
||||||
|
get-stream "^5.1.0"
|
||||||
|
http-cache-semantics "^4.0.0"
|
||||||
|
keyv "^3.0.0"
|
||||||
|
lowercase-keys "^2.0.0"
|
||||||
|
normalize-url "^4.1.0"
|
||||||
|
responselike "^1.0.2"
|
||||||
|
|
||||||
caching-transform@^1.0.0:
|
caching-transform@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-1.0.1.tgz#6dbdb2f20f8d8fbce79f3e94e9d1742dcdf5c0a1"
|
resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-1.0.1.tgz#6dbdb2f20f8d8fbce79f3e94e9d1742dcdf5c0a1"
|
||||||
@@ -1828,6 +1874,13 @@ cliui@^4.0.0:
|
|||||||
strip-ansi "^4.0.0"
|
strip-ansi "^4.0.0"
|
||||||
wrap-ansi "^2.0.0"
|
wrap-ansi "^2.0.0"
|
||||||
|
|
||||||
|
clone-response@^1.0.2:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3"
|
||||||
|
integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==
|
||||||
|
dependencies:
|
||||||
|
mimic-response "^1.0.0"
|
||||||
|
|
||||||
clone@^1.0.2:
|
clone@^1.0.2:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
|
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
|
||||||
@@ -2083,6 +2136,14 @@ conf@^1.0.0:
|
|||||||
pkg-up "^2.0.0"
|
pkg-up "^2.0.0"
|
||||||
write-file-atomic "^2.3.0"
|
write-file-atomic "^2.3.0"
|
||||||
|
|
||||||
|
config-chain@^1.1.11:
|
||||||
|
version "1.1.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4"
|
||||||
|
integrity sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==
|
||||||
|
dependencies:
|
||||||
|
ini "^1.3.4"
|
||||||
|
proto-list "~1.2.1"
|
||||||
|
|
||||||
configstore@^3.0.0:
|
configstore@^3.0.0:
|
||||||
version "3.1.2"
|
version "3.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f"
|
resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f"
|
||||||
@@ -2753,6 +2814,13 @@ debug@^4.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ms "^2.1.1"
|
ms "^2.1.1"
|
||||||
|
|
||||||
|
debug@^4.1.1:
|
||||||
|
version "4.3.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||||
|
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||||
|
dependencies:
|
||||||
|
ms "2.1.2"
|
||||||
|
|
||||||
decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2:
|
decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
||||||
@@ -2761,6 +2829,13 @@ decode-uri-component@^0.2.0:
|
|||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
|
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
|
||||||
|
|
||||||
|
decompress-response@^3.3.0:
|
||||||
|
version "3.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3"
|
||||||
|
integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==
|
||||||
|
dependencies:
|
||||||
|
mimic-response "^1.0.0"
|
||||||
|
|
||||||
decompress-zip@0.3.0:
|
decompress-zip@0.3.0:
|
||||||
version "0.3.0"
|
version "0.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/decompress-zip/-/decompress-zip-0.3.0.tgz#ae3bcb7e34c65879adfe77e19c30f86602b4bdb0"
|
resolved "https://registry.yarnpkg.com/decompress-zip/-/decompress-zip-0.3.0.tgz#ae3bcb7e34c65879adfe77e19c30f86602b4bdb0"
|
||||||
@@ -2791,6 +2866,11 @@ default-require-extensions@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
strip-bom "^2.0.0"
|
strip-bom "^2.0.0"
|
||||||
|
|
||||||
|
defer-to-connect@^1.0.1:
|
||||||
|
version "1.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
|
||||||
|
integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==
|
||||||
|
|
||||||
define-properties@^1.1.2:
|
define-properties@^1.1.2:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94"
|
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94"
|
||||||
@@ -2798,6 +2878,14 @@ define-properties@^1.1.2:
|
|||||||
foreach "^2.0.5"
|
foreach "^2.0.5"
|
||||||
object-keys "^1.0.8"
|
object-keys "^1.0.8"
|
||||||
|
|
||||||
|
define-properties@^1.1.3:
|
||||||
|
version "1.1.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1"
|
||||||
|
integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==
|
||||||
|
dependencies:
|
||||||
|
has-property-descriptors "^1.0.0"
|
||||||
|
object-keys "^1.1.1"
|
||||||
|
|
||||||
define-property@^0.2.5:
|
define-property@^0.2.5:
|
||||||
version "0.2.5"
|
version "0.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
|
resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
|
||||||
@@ -2882,6 +2970,11 @@ detect-newline@^2.1.0:
|
|||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
|
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
|
||||||
|
|
||||||
|
detect-node@^2.0.4:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1"
|
||||||
|
integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==
|
||||||
|
|
||||||
devtron@^1.1.0:
|
devtron@^1.1.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/devtron/-/devtron-1.4.0.tgz#b5e748bd6e95bbe70bfcc68aae6fe696119441e1"
|
resolved "https://registry.yarnpkg.com/devtron/-/devtron-1.4.0.tgz#b5e748bd6e95bbe70bfcc68aae6fe696119441e1"
|
||||||
@@ -3015,7 +3108,7 @@ electron-devtools-installer@^2.2.4:
|
|||||||
rimraf "^2.5.2"
|
rimraf "^2.5.2"
|
||||||
semver "^5.3.0"
|
semver "^5.3.0"
|
||||||
|
|
||||||
electron-download@^4.1.0, electron-download@^4.1.1:
|
electron-download@^4.1.1:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-4.1.1.tgz#02e69556705cc456e520f9e035556ed5a015ebe8"
|
resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-4.1.1.tgz#02e69556705cc456e520f9e035556ed5a015ebe8"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3134,13 +3227,13 @@ electron-winstaller@^2.2.0:
|
|||||||
lodash.template "^4.2.2"
|
lodash.template "^4.2.2"
|
||||||
temp "^0.8.3"
|
temp "^0.8.3"
|
||||||
|
|
||||||
electron@4:
|
electron@18:
|
||||||
version "4.2.12"
|
version "18.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/electron/-/electron-4.2.12.tgz#8e8926a6a6654cde5eb0612952fed98a56941875"
|
resolved "https://registry.yarnpkg.com/electron/-/electron-18.3.7.tgz#a22a23d63811d067c8e33abc5674122408319265"
|
||||||
integrity sha512-EES8eMztoW8gEP5E4GQLP8slrfS2jqTYtHbu36mlu3k1xYAaNPyQQr6mCILkYxqj4l3la4CT2Vcs89CUG62vcQ==
|
integrity sha512-SDvX0VYejR1xw9PrJyvnyiDcuIhdzFVaA1NaRN2LEWXr5R6mEFl8NVTM+i5dtxMm2SHP/FPnkvmsWZs6MHijqg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "^10.12.18"
|
"@electron/get" "^1.13.0"
|
||||||
electron-download "^4.1.0"
|
"@types/node" "^16.11.26"
|
||||||
extract-zip "^1.0.3"
|
extract-zip "^1.0.3"
|
||||||
|
|
||||||
emoji-regex@^6.4.1:
|
emoji-regex@^6.4.1:
|
||||||
@@ -3159,7 +3252,7 @@ empower-core@^0.6.1:
|
|||||||
call-signature "0.0.2"
|
call-signature "0.0.2"
|
||||||
core-js "^2.0.0"
|
core-js "^2.0.0"
|
||||||
|
|
||||||
encodeurl@~1.0.2:
|
encodeurl@^1.0.2, encodeurl@~1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||||
|
|
||||||
@@ -3169,6 +3262,13 @@ encoding@^0.1.11:
|
|||||||
dependencies:
|
dependencies:
|
||||||
iconv-lite "~0.4.13"
|
iconv-lite "~0.4.13"
|
||||||
|
|
||||||
|
end-of-stream@^1.1.0:
|
||||||
|
version "1.4.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
||||||
|
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
|
||||||
|
dependencies:
|
||||||
|
once "^1.4.0"
|
||||||
|
|
||||||
enhanced-resolve@~0.9.0:
|
enhanced-resolve@~0.9.0:
|
||||||
version "0.9.1"
|
version "0.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e"
|
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e"
|
||||||
@@ -3192,6 +3292,11 @@ env-paths@^1.0.0:
|
|||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0"
|
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0"
|
||||||
|
|
||||||
|
env-paths@^2.2.0:
|
||||||
|
version "2.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
|
||||||
|
integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==
|
||||||
|
|
||||||
equal-length@^1.0.0:
|
equal-length@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/equal-length/-/equal-length-1.0.1.tgz#21ca112d48ab24b4e1e7ffc0e5339d31fdfc274c"
|
resolved "https://registry.yarnpkg.com/equal-length/-/equal-length-1.0.1.tgz#21ca112d48ab24b4e1e7ffc0e5339d31fdfc274c"
|
||||||
@@ -3240,7 +3345,7 @@ es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14:
|
|||||||
es6-symbol "~3.1.1"
|
es6-symbol "~3.1.1"
|
||||||
next-tick "1"
|
next-tick "1"
|
||||||
|
|
||||||
es6-error@^4.0.1, es6-error@^4.0.2:
|
es6-error@^4.0.1, es6-error@^4.0.2, es6-error@^4.1.1:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d"
|
resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d"
|
||||||
|
|
||||||
@@ -3301,6 +3406,11 @@ escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2, escape-string-regexp@^
|
|||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||||
|
|
||||||
|
escape-string-regexp@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
|
||||||
|
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
||||||
|
|
||||||
escaper@^2.5.3:
|
escaper@^2.5.3:
|
||||||
version "2.5.3"
|
version "2.5.3"
|
||||||
resolved "https://registry.yarnpkg.com/escaper/-/escaper-2.5.3.tgz#8b8fe90ba364054151ab7eff18b4ce43b1e13ab5"
|
resolved "https://registry.yarnpkg.com/escaper/-/escaper-2.5.3.tgz#8b8fe90ba364054151ab7eff18b4ce43b1e13ab5"
|
||||||
@@ -4078,6 +4188,15 @@ fs-extra@^5.0.0:
|
|||||||
jsonfile "^4.0.0"
|
jsonfile "^4.0.0"
|
||||||
universalify "^0.1.0"
|
universalify "^0.1.0"
|
||||||
|
|
||||||
|
fs-extra@^8.1.0:
|
||||||
|
version "8.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
|
||||||
|
integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
|
||||||
|
dependencies:
|
||||||
|
graceful-fs "^4.2.0"
|
||||||
|
jsonfile "^4.0.0"
|
||||||
|
universalify "^0.1.0"
|
||||||
|
|
||||||
fs-minipass@^1.2.5:
|
fs-minipass@^1.2.5:
|
||||||
version "1.2.5"
|
version "1.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d"
|
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d"
|
||||||
@@ -4163,6 +4282,15 @@ get-folder-size@^1.0.0:
|
|||||||
async "^1.4.2"
|
async "^1.4.2"
|
||||||
gar "^1.0.2"
|
gar "^1.0.2"
|
||||||
|
|
||||||
|
get-intrinsic@^1.1.1:
|
||||||
|
version "1.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385"
|
||||||
|
integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==
|
||||||
|
dependencies:
|
||||||
|
function-bind "^1.1.1"
|
||||||
|
has "^1.0.3"
|
||||||
|
has-symbols "^1.0.3"
|
||||||
|
|
||||||
get-package-info@^1.0.0:
|
get-package-info@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/get-package-info/-/get-package-info-1.0.0.tgz#6432796563e28113cd9474dbbd00052985a4999c"
|
resolved "https://registry.yarnpkg.com/get-package-info/-/get-package-info-1.0.0.tgz#6432796563e28113cd9474dbbd00052985a4999c"
|
||||||
@@ -4192,6 +4320,20 @@ get-stream@^3.0.0:
|
|||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
|
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
|
||||||
|
|
||||||
|
get-stream@^4.1.0:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
|
||||||
|
integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
|
||||||
|
dependencies:
|
||||||
|
pump "^3.0.0"
|
||||||
|
|
||||||
|
get-stream@^5.1.0:
|
||||||
|
version "5.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
|
||||||
|
integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
|
||||||
|
dependencies:
|
||||||
|
pump "^3.0.0"
|
||||||
|
|
||||||
get-value@^2.0.3, get-value@^2.0.6:
|
get-value@^2.0.3, get-value@^2.0.6:
|
||||||
version "2.0.6"
|
version "2.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
|
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
|
||||||
@@ -4266,12 +4408,34 @@ glob@~3.1.21:
|
|||||||
inherits "1"
|
inherits "1"
|
||||||
minimatch "~0.2.11"
|
minimatch "~0.2.11"
|
||||||
|
|
||||||
|
global-agent@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-3.0.0.tgz#ae7cd31bd3583b93c5a16437a1afe27cc33a1ab6"
|
||||||
|
integrity sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==
|
||||||
|
dependencies:
|
||||||
|
boolean "^3.0.1"
|
||||||
|
es6-error "^4.1.1"
|
||||||
|
matcher "^3.0.0"
|
||||||
|
roarr "^2.15.3"
|
||||||
|
semver "^7.3.2"
|
||||||
|
serialize-error "^7.0.1"
|
||||||
|
|
||||||
global-dirs@^0.1.0:
|
global-dirs@^0.1.0:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445"
|
resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445"
|
||||||
dependencies:
|
dependencies:
|
||||||
ini "^1.3.4"
|
ini "^1.3.4"
|
||||||
|
|
||||||
|
global-tunnel-ng@^2.7.1:
|
||||||
|
version "2.7.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz#d03b5102dfde3a69914f5ee7d86761ca35d57d8f"
|
||||||
|
integrity sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==
|
||||||
|
dependencies:
|
||||||
|
encodeurl "^1.0.2"
|
||||||
|
lodash "^4.17.10"
|
||||||
|
npm-conf "^1.1.3"
|
||||||
|
tunnel "^0.0.6"
|
||||||
|
|
||||||
global@^4.3.0:
|
global@^4.3.0:
|
||||||
version "4.3.2"
|
version "4.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f"
|
resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f"
|
||||||
@@ -4288,6 +4452,13 @@ globals@^9.18.0, globals@^9.2.0:
|
|||||||
version "9.18.0"
|
version "9.18.0"
|
||||||
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
|
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
|
||||||
|
|
||||||
|
globalthis@^1.0.1:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf"
|
||||||
|
integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==
|
||||||
|
dependencies:
|
||||||
|
define-properties "^1.1.3"
|
||||||
|
|
||||||
globby@^5.0.0:
|
globby@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
|
resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
|
||||||
@@ -4345,10 +4516,32 @@ got@^6.7.1:
|
|||||||
unzip-response "^2.0.1"
|
unzip-response "^2.0.1"
|
||||||
url-parse-lax "^1.0.0"
|
url-parse-lax "^1.0.0"
|
||||||
|
|
||||||
|
got@^9.6.0:
|
||||||
|
version "9.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85"
|
||||||
|
integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==
|
||||||
|
dependencies:
|
||||||
|
"@sindresorhus/is" "^0.14.0"
|
||||||
|
"@szmarczak/http-timer" "^1.1.2"
|
||||||
|
cacheable-request "^6.0.0"
|
||||||
|
decompress-response "^3.3.0"
|
||||||
|
duplexer3 "^0.1.4"
|
||||||
|
get-stream "^4.1.0"
|
||||||
|
lowercase-keys "^1.0.1"
|
||||||
|
mimic-response "^1.0.1"
|
||||||
|
p-cancelable "^1.0.0"
|
||||||
|
to-readable-stream "^1.0.0"
|
||||||
|
url-parse-lax "^3.0.0"
|
||||||
|
|
||||||
graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9:
|
graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9:
|
||||||
version "4.1.11"
|
version "4.1.11"
|
||||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
|
||||||
|
|
||||||
|
graceful-fs@^4.2.0:
|
||||||
|
version "4.2.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
|
||||||
|
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
|
||||||
|
|
||||||
graceful-fs@~1.2.0:
|
graceful-fs@~1.2.0:
|
||||||
version "1.2.3"
|
version "1.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-1.2.3.tgz#15a4806a57547cb2d2dbf27f42e89a8c3451b364"
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-1.2.3.tgz#15a4806a57547cb2d2dbf27f42e89a8c3451b364"
|
||||||
@@ -4514,6 +4707,18 @@ has-flag@^3.0.0:
|
|||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||||
|
|
||||||
|
has-property-descriptors@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861"
|
||||||
|
integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==
|
||||||
|
dependencies:
|
||||||
|
get-intrinsic "^1.1.1"
|
||||||
|
|
||||||
|
has-symbols@^1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
|
||||||
|
integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
|
||||||
|
|
||||||
has-unicode@^2.0.0:
|
has-unicode@^2.0.0:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
|
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
|
||||||
@@ -4555,6 +4760,13 @@ has@^1.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
function-bind "^1.0.2"
|
function-bind "^1.0.2"
|
||||||
|
|
||||||
|
has@^1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
||||||
|
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
|
||||||
|
dependencies:
|
||||||
|
function-bind "^1.1.1"
|
||||||
|
|
||||||
he@^1.1.1, he@^1.2.0:
|
he@^1.1.1, he@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
||||||
@@ -4642,6 +4854,11 @@ htmlparser2@^3.9.0:
|
|||||||
inherits "^2.0.1"
|
inherits "^2.0.1"
|
||||||
readable-stream "^2.0.2"
|
readable-stream "^2.0.2"
|
||||||
|
|
||||||
|
http-cache-semantics@^4.0.0:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390"
|
||||||
|
integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==
|
||||||
|
|
||||||
http-errors@1.6.2:
|
http-errors@1.6.2:
|
||||||
version "1.6.2"
|
version "1.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
|
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
|
||||||
@@ -5806,6 +6023,11 @@ jsesc@~0.5.0:
|
|||||||
version "0.5.0"
|
version "0.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
|
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
|
||||||
|
|
||||||
|
json-buffer@3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898"
|
||||||
|
integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==
|
||||||
|
|
||||||
json-loader@^0.5.4:
|
json-loader@^0.5.4:
|
||||||
version "0.5.7"
|
version "0.5.7"
|
||||||
resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d"
|
resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d"
|
||||||
@@ -5833,7 +6055,7 @@ json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
jsonify "~0.0.0"
|
jsonify "~0.0.0"
|
||||||
|
|
||||||
json-stringify-safe@~5.0.1:
|
json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
|
||||||
version "5.0.1"
|
version "5.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
||||||
|
|
||||||
@@ -5909,6 +6131,13 @@ keyboardevents-areequal@^0.2.1:
|
|||||||
resolved "https://registry.yarnpkg.com/keyboardevents-areequal/-/keyboardevents-areequal-0.2.2.tgz#88191ec738ce9f7591c25e9056de928b40277194"
|
resolved "https://registry.yarnpkg.com/keyboardevents-areequal/-/keyboardevents-areequal-0.2.2.tgz#88191ec738ce9f7591c25e9056de928b40277194"
|
||||||
integrity sha512-Nv+Kr33T0mEjxR500q+I6IWisOQ0lK1GGOncV0kWE6n4KFmpcu7RUX5/2B0EUtX51Cb0HjZ9VJsSY3u4cBa0kw==
|
integrity sha512-Nv+Kr33T0mEjxR500q+I6IWisOQ0lK1GGOncV0kWE6n4KFmpcu7RUX5/2B0EUtX51Cb0HjZ9VJsSY3u4cBa0kw==
|
||||||
|
|
||||||
|
keyv@^3.0.0:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9"
|
||||||
|
integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==
|
||||||
|
dependencies:
|
||||||
|
json-buffer "3.0.0"
|
||||||
|
|
||||||
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
|
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
|
||||||
version "3.2.2"
|
version "3.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
|
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
|
||||||
@@ -6214,10 +6443,15 @@ lower-case@^1.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
|
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
|
||||||
integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=
|
integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=
|
||||||
|
|
||||||
lowercase-keys@^1.0.0:
|
lowercase-keys@^1.0.0, lowercase-keys@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
|
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
|
||||||
|
|
||||||
|
lowercase-keys@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
|
||||||
|
integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
|
||||||
|
|
||||||
lru-cache@2:
|
lru-cache@2:
|
||||||
version "2.7.3"
|
version "2.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952"
|
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952"
|
||||||
@@ -6229,6 +6463,13 @@ lru-cache@^4.0.1:
|
|||||||
pseudomap "^1.0.2"
|
pseudomap "^1.0.2"
|
||||||
yallist "^2.1.2"
|
yallist "^2.1.2"
|
||||||
|
|
||||||
|
lru-cache@^6.0.0:
|
||||||
|
version "6.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
|
||||||
|
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
|
||||||
|
dependencies:
|
||||||
|
yallist "^4.0.0"
|
||||||
|
|
||||||
make-dir@^1.0.0:
|
make-dir@^1.0.0:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
|
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
|
||||||
@@ -6366,6 +6607,13 @@ matcher@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
escape-string-regexp "^1.0.4"
|
escape-string-regexp "^1.0.4"
|
||||||
|
|
||||||
|
matcher@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca"
|
||||||
|
integrity sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==
|
||||||
|
dependencies:
|
||||||
|
escape-string-regexp "^4.0.0"
|
||||||
|
|
||||||
material-colors@^1.2.1:
|
material-colors@^1.2.1:
|
||||||
version "1.2.5"
|
version "1.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.5.tgz#5292593e6754cb1bcc2b98030e4e0d6a3afc9ea1"
|
resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.5.tgz#5292593e6754cb1bcc2b98030e4e0d6a3afc9ea1"
|
||||||
@@ -6539,6 +6787,11 @@ mimic-fn@^1.0.0:
|
|||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
|
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
|
||||||
|
|
||||||
|
mimic-response@^1.0.0, mimic-response@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
|
||||||
|
integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
|
||||||
|
|
||||||
min-document@^2.19.0:
|
min-document@^2.19.0:
|
||||||
version "2.19.0"
|
version "2.19.0"
|
||||||
resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
|
resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
|
||||||
@@ -6663,15 +6916,15 @@ ms@2.0.0:
|
|||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||||
|
|
||||||
ms@^2.0.0:
|
ms@2.1.2, ms@^2.1.1:
|
||||||
version "2.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
|
|
||||||
|
|
||||||
ms@^2.1.1:
|
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||||
|
|
||||||
|
ms@^2.0.0:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
|
||||||
|
|
||||||
multimatch@^2.1.0:
|
multimatch@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b"
|
resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b"
|
||||||
@@ -6892,10 +7145,23 @@ normalize-url@^1.4.0:
|
|||||||
query-string "^4.1.0"
|
query-string "^4.1.0"
|
||||||
sort-keys "^1.0.0"
|
sort-keys "^1.0.0"
|
||||||
|
|
||||||
|
normalize-url@^4.1.0:
|
||||||
|
version "4.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a"
|
||||||
|
integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==
|
||||||
|
|
||||||
npm-bundled@^1.0.1:
|
npm-bundled@^1.0.1:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308"
|
resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308"
|
||||||
|
|
||||||
|
npm-conf@^1.1.3:
|
||||||
|
version "1.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9"
|
||||||
|
integrity sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==
|
||||||
|
dependencies:
|
||||||
|
config-chain "^1.1.11"
|
||||||
|
pify "^3.0.0"
|
||||||
|
|
||||||
npm-packlist@^1.1.6:
|
npm-packlist@^1.1.6:
|
||||||
version "1.1.10"
|
version "1.1.10"
|
||||||
resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.10.tgz#1039db9e985727e464df066f4cf0ab6ef85c398a"
|
resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.10.tgz#1039db9e985727e464df066f4cf0ab6ef85c398a"
|
||||||
@@ -6974,6 +7240,11 @@ object-keys@^1.0.8:
|
|||||||
version "1.0.11"
|
version "1.0.11"
|
||||||
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d"
|
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d"
|
||||||
|
|
||||||
|
object-keys@^1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
|
||||||
|
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
|
||||||
|
|
||||||
object-keys@~0.4.0:
|
object-keys@~0.4.0:
|
||||||
version "0.4.0"
|
version "0.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336"
|
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336"
|
||||||
@@ -7026,7 +7297,7 @@ on-headers@~1.0.1:
|
|||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"
|
resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"
|
||||||
|
|
||||||
once@^1.3.0, once@^1.4.0:
|
once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -7114,6 +7385,11 @@ osenv@^0.1.4:
|
|||||||
os-homedir "^1.0.0"
|
os-homedir "^1.0.0"
|
||||||
os-tmpdir "^1.0.0"
|
os-tmpdir "^1.0.0"
|
||||||
|
|
||||||
|
p-cancelable@^1.0.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc"
|
||||||
|
integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==
|
||||||
|
|
||||||
p-finally@^1.0.0:
|
p-finally@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
|
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
|
||||||
@@ -7659,6 +7935,11 @@ prepend-http@^1.0.0, prepend-http@^1.0.1:
|
|||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
|
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
|
||||||
|
|
||||||
|
prepend-http@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
|
||||||
|
integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==
|
||||||
|
|
||||||
preserve@^0.2.0:
|
preserve@^0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
|
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
|
||||||
@@ -7728,7 +8009,7 @@ progress@^1.1.8:
|
|||||||
version "1.1.8"
|
version "1.1.8"
|
||||||
resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be"
|
resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be"
|
||||||
|
|
||||||
progress@^2.0.0:
|
progress@^2.0.0, progress@^2.0.3:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
|
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
|
||||||
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
|
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
|
||||||
@@ -7769,6 +8050,11 @@ prop-types@^15.6.2:
|
|||||||
loose-envify "^1.3.1"
|
loose-envify "^1.3.1"
|
||||||
object-assign "^4.1.1"
|
object-assign "^4.1.1"
|
||||||
|
|
||||||
|
proto-list@~1.2.1:
|
||||||
|
version "1.2.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
|
||||||
|
integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==
|
||||||
|
|
||||||
proxy-addr@~2.0.3:
|
proxy-addr@~2.0.3:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.3.tgz#355f262505a621646b3130a728eb647e22055341"
|
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.3.tgz#355f262505a621646b3130a728eb647e22055341"
|
||||||
@@ -7788,6 +8074,14 @@ psl@^1.1.24:
|
|||||||
version "1.1.29"
|
version "1.1.29"
|
||||||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67"
|
resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67"
|
||||||
|
|
||||||
|
pump@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
|
||||||
|
integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
|
||||||
|
dependencies:
|
||||||
|
end-of-stream "^1.1.0"
|
||||||
|
once "^1.3.1"
|
||||||
|
|
||||||
punycode@1.3.2:
|
punycode@1.3.2:
|
||||||
version "1.3.2"
|
version "1.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
|
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
|
||||||
@@ -8521,6 +8815,13 @@ resolve@^1.1.6:
|
|||||||
dependencies:
|
dependencies:
|
||||||
path-parse "^1.0.5"
|
path-parse "^1.0.5"
|
||||||
|
|
||||||
|
responselike@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7"
|
||||||
|
integrity sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==
|
||||||
|
dependencies:
|
||||||
|
lowercase-keys "^1.0.0"
|
||||||
|
|
||||||
restore-cursor@^1.0.1:
|
restore-cursor@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
|
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
|
||||||
@@ -8559,6 +8860,18 @@ ripemd160@0.2.0:
|
|||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-0.2.0.tgz#2bf198bde167cacfa51c0a928e84b68bbe171fce"
|
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-0.2.0.tgz#2bf198bde167cacfa51c0a928e84b68bbe171fce"
|
||||||
|
|
||||||
|
roarr@^2.15.3:
|
||||||
|
version "2.15.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.4.tgz#f5fe795b7b838ccfe35dc608e0282b9eba2e7afd"
|
||||||
|
integrity sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==
|
||||||
|
dependencies:
|
||||||
|
boolean "^3.0.1"
|
||||||
|
detect-node "^2.0.4"
|
||||||
|
globalthis "^1.0.1"
|
||||||
|
json-stringify-safe "^5.0.1"
|
||||||
|
semver-compare "^1.0.0"
|
||||||
|
sprintf-js "^1.1.2"
|
||||||
|
|
||||||
rsvp@^3.3.3:
|
rsvp@^3.3.3:
|
||||||
version "3.6.2"
|
version "3.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
|
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
|
||||||
@@ -8728,6 +9041,18 @@ semver@^5.5.0:
|
|||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
|
||||||
integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==
|
integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==
|
||||||
|
|
||||||
|
semver@^6.2.0:
|
||||||
|
version "6.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||||
|
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||||
|
|
||||||
|
semver@^7.3.2:
|
||||||
|
version "7.3.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
|
||||||
|
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
|
||||||
|
dependencies:
|
||||||
|
lru-cache "^6.0.0"
|
||||||
|
|
||||||
send@0.16.2:
|
send@0.16.2:
|
||||||
version "0.16.2"
|
version "0.16.2"
|
||||||
resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
|
resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
|
||||||
@@ -8750,6 +9075,13 @@ serialize-error@^2.1.0:
|
|||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a"
|
resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a"
|
||||||
|
|
||||||
|
serialize-error@^7.0.1:
|
||||||
|
version "7.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18"
|
||||||
|
integrity sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==
|
||||||
|
dependencies:
|
||||||
|
type-fest "^0.13.1"
|
||||||
|
|
||||||
serve-index@^1.7.2:
|
serve-index@^1.7.2:
|
||||||
version "1.9.1"
|
version "1.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239"
|
resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239"
|
||||||
@@ -9067,6 +9399,11 @@ split-string@^3.0.1, split-string@^3.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
extend-shallow "^3.0.0"
|
extend-shallow "^3.0.0"
|
||||||
|
|
||||||
|
sprintf-js@^1.1.2:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673"
|
||||||
|
integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==
|
||||||
|
|
||||||
sprintf-js@~1.0.2:
|
sprintf-js@~1.0.2:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||||
@@ -9336,6 +9673,13 @@ sumchecker@^2.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
debug "^2.2.0"
|
debug "^2.2.0"
|
||||||
|
|
||||||
|
sumchecker@^3.0.1:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.1.tgz#6377e996795abb0b6d348e9b3e1dfb24345a8e42"
|
||||||
|
integrity sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==
|
||||||
|
dependencies:
|
||||||
|
debug "^4.1.0"
|
||||||
|
|
||||||
supertap@^1.0.0:
|
supertap@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/supertap/-/supertap-1.0.0.tgz#bd9751c7fafd68c68cf8222a29892206a119fa9e"
|
resolved "https://registry.yarnpkg.com/supertap/-/supertap-1.0.0.tgz#bd9751c7fafd68c68cf8222a29892206a119fa9e"
|
||||||
@@ -9558,6 +9902,11 @@ to-object-path@^0.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
kind-of "^3.0.2"
|
kind-of "^3.0.2"
|
||||||
|
|
||||||
|
to-readable-stream@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771"
|
||||||
|
integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==
|
||||||
|
|
||||||
to-regex-range@^2.1.0:
|
to-regex-range@^2.1.0:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38"
|
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38"
|
||||||
@@ -9663,6 +10012,11 @@ tunnel-agent@^0.6.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "^5.0.1"
|
safe-buffer "^5.0.1"
|
||||||
|
|
||||||
|
tunnel@^0.0.6:
|
||||||
|
version "0.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c"
|
||||||
|
integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==
|
||||||
|
|
||||||
turndown-plugin-gfm@^1.0.2:
|
turndown-plugin-gfm@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/turndown-plugin-gfm/-/turndown-plugin-gfm-1.0.2.tgz#6f8678a361f35220b2bdf5619e6049add75bf1c7"
|
resolved "https://registry.yarnpkg.com/turndown-plugin-gfm/-/turndown-plugin-gfm-1.0.2.tgz#6f8678a361f35220b2bdf5619e6049add75bf1c7"
|
||||||
@@ -9683,6 +10037,11 @@ type-check@~0.3.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
prelude-ls "~1.1.2"
|
prelude-ls "~1.1.2"
|
||||||
|
|
||||||
|
type-fest@^0.13.1:
|
||||||
|
version "0.13.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934"
|
||||||
|
integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==
|
||||||
|
|
||||||
type-fest@^0.5.2:
|
type-fest@^0.5.2:
|
||||||
version "0.5.2"
|
version "0.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2"
|
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2"
|
||||||
@@ -9880,6 +10239,13 @@ url-parse-lax@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
prepend-http "^1.0.1"
|
prepend-http "^1.0.1"
|
||||||
|
|
||||||
|
url-parse-lax@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c"
|
||||||
|
integrity sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==
|
||||||
|
dependencies:
|
||||||
|
prepend-http "^2.0.0"
|
||||||
|
|
||||||
url-parse@^1.1.8, url-parse@~1.4.0:
|
url-parse@^1.1.8, url-parse@~1.4.0:
|
||||||
version "1.4.7"
|
version "1.4.7"
|
||||||
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
|
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
|
||||||
@@ -10307,6 +10673,11 @@ yallist@^3.0.0, yallist@^3.0.2:
|
|||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9"
|
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9"
|
||||||
|
|
||||||
|
yallist@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||||
|
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||||
|
|
||||||
yargs-parser@^10.0.0:
|
yargs-parser@^10.0.0:
|
||||||
version "10.1.0"
|
version "10.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"
|
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"
|
||||||
|
|||||||
Reference in New Issue
Block a user