mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-14 18:26:26 +00:00
Compare commits
245 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1195c77f7a | ||
|
|
c373c207c0 | ||
|
|
65e83e7017 | ||
|
|
3c12e0d119 | ||
|
|
60d6c68e48 | ||
|
|
d8605965a8 | ||
|
|
6d455fc286 | ||
|
|
2882667e94 | ||
|
|
7fa578880e | ||
|
|
3f465df1cd | ||
|
|
c423784cc5 | ||
|
|
ce853a7e3a | ||
|
|
099ebad06b | ||
|
|
75a1347ae1 | ||
|
|
b83d3e5c33 | ||
|
|
1a7c719a4e | ||
|
|
d78f6b7aba | ||
|
|
7d4d176bf4 | ||
|
|
52ea44ceaa | ||
|
|
132d04326b | ||
|
|
9996b5d686 | ||
|
|
e9d9f49ff3 | ||
|
|
95300546dc | ||
|
|
489fc6578b | ||
|
|
edebba6680 | ||
|
|
72c2a20a74 | ||
|
|
abef6c5fee | ||
|
|
662ae73637 | ||
|
|
3ef485548a | ||
|
|
a90c10ef3e | ||
|
|
d43fe8db75 | ||
|
|
1d84cac922 | ||
|
|
5280b6ed63 | ||
|
|
77833ff980 | ||
|
|
d010c5532d | ||
|
|
f2dc8b8020 | ||
|
|
1798353eac | ||
|
|
772a8b2383 | ||
|
|
5690c8361a | ||
|
|
6d09cf227c | ||
|
|
8736666e91 | ||
|
|
d1fd5cfb45 | ||
|
|
3eabf95fb3 | ||
|
|
8ea920ef91 | ||
|
|
3c0f20f364 | ||
|
|
59f8425c97 | ||
|
|
f181a7e459 | ||
|
|
6b1c595f87 | ||
|
|
0003de8f08 | ||
|
|
5357d8dc04 | ||
|
|
d069722bf9 | ||
|
|
3f4dd49a8f | ||
|
|
be06b3f7e8 | ||
|
|
5044bdda00 | ||
|
|
fbeffb0b5d | ||
|
|
ef0af39aa7 | ||
|
|
0697bc0a74 | ||
|
|
43d8ebb3c4 | ||
|
|
68175cd71b | ||
|
|
f4d87f64ae | ||
|
|
68b3077651 | ||
|
|
1332b337f3 | ||
|
|
e9975d1ea5 | ||
|
|
2c103aca3d | ||
|
|
c0a5eb0d2b | ||
|
|
ff7c4495f0 | ||
|
|
35fe639cd2 | ||
|
|
59add8982e | ||
|
|
8d9c514097 | ||
|
|
6f880d0f02 | ||
|
|
ec47ee8110 | ||
|
|
28b8141c6b | ||
|
|
5b0b309c49 | ||
|
|
0b84a372f6 | ||
|
|
8355e1e006 | ||
|
|
c7d33fbd83 | ||
|
|
cf324d93fe | ||
|
|
9a704a2bcb | ||
|
|
1e00651541 | ||
|
|
857e75594d | ||
|
|
2f1dadfc3e | ||
|
|
7d0404657e | ||
|
|
b9dd651fc1 | ||
|
|
25ef456af2 | ||
|
|
084decaa85 | ||
|
|
330a444fc5 | ||
|
|
a47dac2854 | ||
|
|
08070f3e2d | ||
|
|
2352c78cb6 | ||
|
|
6ef9c3865f | ||
|
|
ff9789b5a7 | ||
|
|
f09297f406 | ||
|
|
2d3c69d178 | ||
|
|
b837653cf1 | ||
|
|
eeca031c86 | ||
|
|
918a8627e9 | ||
|
|
86370edd1e | ||
|
|
1173631255 | ||
|
|
911fd9a004 | ||
|
|
0ad3da5bbc | ||
|
|
89ae2a9516 | ||
|
|
70892cae05 | ||
|
|
de0af153bc | ||
|
|
33161e46e6 | ||
|
|
7e3c662374 | ||
|
|
a39e9c2da6 | ||
|
|
72b8d56245 | ||
|
|
0d36f59036 | ||
|
|
a3f7d2287a | ||
|
|
8edfbd28ed | ||
|
|
606be4304d | ||
|
|
329066719e | ||
|
|
93b8ef35f7 | ||
|
|
484b003b34 | ||
|
|
ed427130a9 | ||
|
|
807feae540 | ||
|
|
4b62e93257 | ||
|
|
e425417d68 | ||
|
|
bc1e837466 | ||
|
|
95321e33a0 | ||
|
|
5720b313a3 | ||
|
|
f3e2205e69 | ||
|
|
410b611b14 | ||
|
|
1c8af47bac | ||
|
|
c8a2baca3c | ||
|
|
ac5a323115 | ||
|
|
fa65e7feef | ||
|
|
71d27d0e55 | ||
|
|
972d053c83 | ||
|
|
7797661489 | ||
|
|
9f9e036c68 | ||
|
|
e940253caf | ||
|
|
2b4d20b94e | ||
|
|
f88fc23e58 | ||
|
|
caf1f92fef | ||
|
|
f2a02a25a7 | ||
|
|
e85767b4a0 | ||
|
|
c83e5cc7d8 | ||
|
|
71f565f66b | ||
|
|
769407b3df | ||
|
|
e7615ed6d7 | ||
|
|
fe508307b2 | ||
|
|
c2a26a8547 | ||
|
|
addf9b920f | ||
|
|
4e30d4b8fb | ||
|
|
850561613b | ||
|
|
782d71ddb0 | ||
|
|
a0799d19f8 | ||
|
|
ba6eb4f26f | ||
|
|
38fcee35c2 | ||
|
|
4af7106e01 | ||
|
|
bd52226ae2 | ||
|
|
cb7ac77c61 | ||
|
|
55a7ee1f91 | ||
|
|
d37210a0d0 | ||
|
|
0c7a1e8f17 | ||
|
|
3d7ab40674 | ||
|
|
b8de51be57 | ||
|
|
1ce72b91ca | ||
|
|
3f96587a70 | ||
|
|
c012bbd54a | ||
|
|
a50852306e | ||
|
|
db396ec107 | ||
|
|
6b868658aa | ||
|
|
9fe9e1a1c4 | ||
|
|
aeb77e5a40 | ||
|
|
1d59d89588 | ||
|
|
bde357f952 | ||
|
|
558c091205 | ||
|
|
f67175e628 | ||
|
|
390f6d545f | ||
|
|
44efb0178c | ||
|
|
37eee26bdf | ||
|
|
b4251a793b | ||
|
|
6736a08240 | ||
|
|
ed4a670f0a | ||
|
|
fbb9afe34f | ||
|
|
020bc11bd7 | ||
|
|
ae0837e29b | ||
|
|
f0380ef733 | ||
|
|
25bdaf9f00 | ||
|
|
ef1809305c | ||
|
|
090b5c32f0 | ||
|
|
49c75e3599 | ||
|
|
05765642d9 | ||
|
|
f62eba9d7b | ||
|
|
bc27fd0acc | ||
|
|
244a28c7d2 | ||
|
|
edac4d3fed | ||
|
|
e402929cca | ||
|
|
639bfbe549 | ||
|
|
60e841e5a2 | ||
|
|
25d055e560 | ||
|
|
052fb3df5b | ||
|
|
929f475354 | ||
|
|
1afa02bbb3 | ||
|
|
3c39dc3cec | ||
|
|
7e8f46c4f3 | ||
|
|
333b0584a4 | ||
|
|
f7a648903e | ||
|
|
6ec687ef15 | ||
|
|
b6212f4bfe | ||
|
|
9794149fae | ||
|
|
edc9d8bd4d | ||
|
|
76335f78ac | ||
|
|
56192f0758 | ||
|
|
63eb8584e7 | ||
|
|
aa4d06fb1e | ||
|
|
c70cca2776 | ||
|
|
1a38771f1a | ||
|
|
25728e51d2 | ||
|
|
02576c48b6 | ||
|
|
4263309d89 | ||
|
|
b68b367b3c | ||
|
|
2cffb50884 | ||
|
|
3b473a5f7a | ||
|
|
8b82c448af | ||
|
|
270a015514 | ||
|
|
f02125e411 | ||
|
|
b0f2694745 | ||
|
|
2497bdb124 | ||
|
|
c82dbddc74 | ||
|
|
0d6c952721 | ||
|
|
c42eb41fb3 | ||
|
|
2da4f1df32 | ||
|
|
69a62d1b73 | ||
|
|
61e054024b | ||
|
|
0a5c4c092a | ||
|
|
f1597f8e84 | ||
|
|
f3ca893aea | ||
|
|
ecfeedeff3 | ||
|
|
a162bab591 | ||
|
|
79a29c3461 | ||
|
|
33d1700548 | ||
|
|
8b3beb45c6 | ||
|
|
4ba4e68833 | ||
|
|
11bed72bed | ||
|
|
7fb22f3f07 | ||
|
|
788900e31a | ||
|
|
a58b6f1b49 | ||
|
|
b6b29e02f3 | ||
|
|
2fc37d54f2 | ||
|
|
18aae8cf7b | ||
|
|
4a9bc69ac2 | ||
|
|
d97e62f864 |
2
.babelrc
2
.babelrc
@@ -7,7 +7,7 @@
|
|||||||
"test": {
|
"test": {
|
||||||
"presets": ["env" ,"react", "es2015"],
|
"presets": ["env" ,"react", "es2015"],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
[ "babel-plugin-webpack-alias", { "config": "${PWD}/webpack.config.js" } ]
|
[ "babel-plugin-webpack-alias", { "config": "<rootDir>/webpack.config.js" } ]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,9 @@
|
|||||||
"globals": {
|
"globals": {
|
||||||
"FileReader": true,
|
"FileReader": true,
|
||||||
"localStorage": true,
|
"localStorage": true,
|
||||||
"fetch": true
|
"fetch": true,
|
||||||
|
"Image": true,
|
||||||
|
"MutationObserver": true
|
||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
"jest": true
|
"jest": true
|
||||||
|
|||||||
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
issuehunt: BoostIo/Boostnote
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -9,4 +9,5 @@ node_modules/*
|
|||||||
/secret
|
/secret
|
||||||
*.log
|
*.log
|
||||||
.idea
|
.idea
|
||||||
.vscode
|
.vscode
|
||||||
|
package-lock.json
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ node_js:
|
|||||||
- 8
|
- 8
|
||||||
script:
|
script:
|
||||||
- npm run lint && npm run test
|
- npm run lint && npm run test
|
||||||
- yarn jest
|
|
||||||
- 'if [[ ${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH} = "master" ]]; then npm install -g grunt npm@6.4 && grunt pre-build; fi'
|
- 'if [[ ${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH} = "master" ]]; then npm install -g grunt npm@6.4 && grunt pre-build; fi'
|
||||||
after_success:
|
after_success:
|
||||||
- openssl aes-256-cbc -K $encrypted_440d7f9a3c38_key -iv $encrypted_440d7f9a3c38_iv
|
- openssl aes-256-cbc -K $encrypted_440d7f9a3c38_key -iv $encrypted_440d7f9a3c38_iv
|
||||||
|
|||||||
@@ -20,12 +20,15 @@ import styles from '../components/CodeEditor.styl'
|
|||||||
const { ipcRenderer, remote, clipboard } = require('electron')
|
const { ipcRenderer, remote, clipboard } = require('electron')
|
||||||
import normalizeEditorFontFamily from 'browser/lib/normalizeEditorFontFamily'
|
import normalizeEditorFontFamily from 'browser/lib/normalizeEditorFontFamily'
|
||||||
const spellcheck = require('browser/lib/spellcheck')
|
const spellcheck = require('browser/lib/spellcheck')
|
||||||
const buildEditorContextMenu = require('browser/lib/contextMenuBuilder')
|
const buildEditorContextMenu = require('browser/lib/contextMenuBuilder').buildEditorContextMenu
|
||||||
import TurndownService from 'turndown'
|
import { createTurndownService } from '../lib/turndown'
|
||||||
import {languageMaps} from '../lib/CMLanguageList'
|
import {languageMaps} from '../lib/CMLanguageList'
|
||||||
import snippetManager from '../lib/SnippetManager'
|
import snippetManager from '../lib/SnippetManager'
|
||||||
import {generateInEditor, tocExistsInEditor} from 'browser/lib/markdown-toc-generator'
|
import {generateInEditor, tocExistsInEditor} from 'browser/lib/markdown-toc-generator'
|
||||||
import markdownlint from 'markdownlint'
|
import markdownlint from 'markdownlint'
|
||||||
|
import Jsonlint from 'jsonlint-mod'
|
||||||
|
import { DEFAULT_CONFIG } from '../main/lib/ConfigManager'
|
||||||
|
import prettier from 'prettier'
|
||||||
|
|
||||||
CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js'
|
CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js'
|
||||||
|
|
||||||
@@ -38,38 +41,6 @@ function translateHotkey (hotkey) {
|
|||||||
return hotkey.replace(/\s*\+\s*/g, '-').replace(/Command/g, 'Cmd').replace(/Control/g, 'Ctrl')
|
return hotkey.replace(/\s*\+\s*/g, '-').replace(/Command/g, 'Cmd').replace(/Control/g, 'Ctrl')
|
||||||
}
|
}
|
||||||
|
|
||||||
const validatorOfMarkdown = (text, updateLinting) => {
|
|
||||||
const lintOptions = {
|
|
||||||
'strings': {
|
|
||||||
'content': text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return markdownlint(lintOptions, (err, result) => {
|
|
||||||
if (!err) {
|
|
||||||
const foundIssues = []
|
|
||||||
result.content.map(item => {
|
|
||||||
let ruleNames = ''
|
|
||||||
item.ruleNames.map((ruleName, index) => {
|
|
||||||
ruleNames += ruleName
|
|
||||||
if (index === item.ruleNames.length - 1) {
|
|
||||||
ruleNames += ': '
|
|
||||||
} else {
|
|
||||||
ruleNames += '/'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
foundIssues.push({
|
|
||||||
from: CodeMirror.Pos(item.lineNumber, 0),
|
|
||||||
to: CodeMirror.Pos(item.lineNumber, 1),
|
|
||||||
message: ruleNames + item.ruleDescription,
|
|
||||||
severity: 'warning'
|
|
||||||
})
|
|
||||||
})
|
|
||||||
updateLinting(foundIssues)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class CodeEditor extends React.Component {
|
export default class CodeEditor extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props)
|
super(props)
|
||||||
@@ -83,6 +54,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(attachmentManagement.deleteAttachmentsNotPresentInNote, 30000)
|
||||||
this.blurHandler = (editor, e) => {
|
this.blurHandler = (editor, e) => {
|
||||||
ipcRenderer.send('editor:focused', false)
|
ipcRenderer.send('editor:focused', false)
|
||||||
if (e == null) return null
|
if (e == null) return null
|
||||||
@@ -94,16 +66,13 @@ export default class CodeEditor extends React.Component {
|
|||||||
el = el.parentNode
|
el = el.parentNode
|
||||||
}
|
}
|
||||||
this.props.onBlur != null && this.props.onBlur(e)
|
this.props.onBlur != null && this.props.onBlur(e)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
storageKey,
|
storageKey,
|
||||||
noteKey
|
noteKey
|
||||||
} = this.props
|
} = this.props
|
||||||
attachmentManagement.deleteAttachmentsNotPresentInNote(
|
if (this.props.deleteUnusedAttachments === true) {
|
||||||
this.editor.getValue(),
|
debouncedDeletionOfAttachments(this.editor.getValue(), storageKey, noteKey)
|
||||||
storageKey,
|
}
|
||||||
noteKey
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
this.pasteHandler = (editor, e) => {
|
this.pasteHandler = (editor, e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
@@ -116,6 +85,8 @@ export default class CodeEditor extends React.Component {
|
|||||||
this.searchHandler = (e, msg) => this.handleSearch(msg)
|
this.searchHandler = (e, msg) => this.handleSearch(msg)
|
||||||
this.searchState = null
|
this.searchState = null
|
||||||
this.scrollToLineHandeler = this.scrollToLine.bind(this)
|
this.scrollToLineHandeler = this.scrollToLine.bind(this)
|
||||||
|
this.getCodeEditorLintConfig = this.getCodeEditorLintConfig.bind(this)
|
||||||
|
this.validatorOfMarkdown = this.validatorOfMarkdown.bind(this)
|
||||||
|
|
||||||
this.formatTable = () => this.handleFormatTable()
|
this.formatTable = () => this.handleFormatTable()
|
||||||
|
|
||||||
@@ -130,7 +101,7 @@ export default class CodeEditor extends React.Component {
|
|||||||
|
|
||||||
this.editorActivityHandler = () => this.handleEditorActivity()
|
this.editorActivityHandler = () => this.handleEditorActivity()
|
||||||
|
|
||||||
this.turndownService = new TurndownService()
|
this.turndownService = createTurndownService()
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSearch (msg) {
|
handleSearch (msg) {
|
||||||
@@ -138,7 +109,7 @@ export default class CodeEditor extends React.Component {
|
|||||||
const component = this
|
const component = this
|
||||||
|
|
||||||
if (component.searchState) cm.removeOverlay(component.searchState)
|
if (component.searchState) cm.removeOverlay(component.searchState)
|
||||||
if (msg.length < 3) return
|
if (msg.length < 1) return
|
||||||
|
|
||||||
cm.operation(function () {
|
cm.operation(function () {
|
||||||
component.searchState = makeOverlay(msg, 'searching')
|
component.searchState = makeOverlay(msg, 'searching')
|
||||||
@@ -233,23 +204,11 @@ export default class CodeEditor extends React.Component {
|
|||||||
'Cmd-T': function (cm) {
|
'Cmd-T': function (cm) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
},
|
},
|
||||||
'Ctrl-/': function (cm) {
|
[translateHotkey(hotkey.insertDate)]: function (cm) {
|
||||||
if (global.process.platform === 'darwin') { return }
|
|
||||||
const dateNow = new Date()
|
const dateNow = new Date()
|
||||||
cm.replaceSelection(dateNow.toLocaleDateString())
|
cm.replaceSelection(dateNow.toLocaleDateString())
|
||||||
},
|
},
|
||||||
'Cmd-/': function (cm) {
|
[translateHotkey(hotkey.insertDateTime)]: function (cm) {
|
||||||
if (global.process.platform !== 'darwin') { return }
|
|
||||||
const dateNow = new Date()
|
|
||||||
cm.replaceSelection(dateNow.toLocaleDateString())
|
|
||||||
},
|
|
||||||
'Shift-Ctrl-/': function (cm) {
|
|
||||||
if (global.process.platform === 'darwin') { return }
|
|
||||||
const dateNow = new Date()
|
|
||||||
cm.replaceSelection(dateNow.toLocaleString())
|
|
||||||
},
|
|
||||||
'Shift-Cmd-/': function (cm) {
|
|
||||||
if (global.process.platform !== 'darwin') { return }
|
|
||||||
const dateNow = new Date()
|
const dateNow = new Date()
|
||||||
cm.replaceSelection(dateNow.toLocaleString())
|
cm.replaceSelection(dateNow.toLocaleString())
|
||||||
},
|
},
|
||||||
@@ -260,6 +219,37 @@ export default class CodeEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
return CodeMirror.Pass
|
return CodeMirror.Pass
|
||||||
},
|
},
|
||||||
|
[translateHotkey(hotkey.prettifyMarkdown)]: cm => {
|
||||||
|
// Default / User configured prettier options
|
||||||
|
const currentConfig = JSON.parse(self.props.prettierConfig)
|
||||||
|
|
||||||
|
// Parser type will always need to be markdown so we override the option before use
|
||||||
|
currentConfig.parser = 'markdown'
|
||||||
|
|
||||||
|
// Get current cursor position
|
||||||
|
const cursorPos = cm.getCursor()
|
||||||
|
currentConfig.cursorOffset = cm.doc.indexFromPos(cursorPos)
|
||||||
|
|
||||||
|
// Prettify contents of editor
|
||||||
|
const formattedTextDetails = prettier.formatWithCursor(cm.doc.getValue(), currentConfig)
|
||||||
|
|
||||||
|
const formattedText = formattedTextDetails.formatted
|
||||||
|
const formattedCursorPos = formattedTextDetails.cursorOffset
|
||||||
|
cm.doc.setValue(formattedText)
|
||||||
|
|
||||||
|
// Reset Cursor position to be at the same markdown as was before prettifying
|
||||||
|
const newCursorPos = cm.doc.posFromIndex(formattedCursorPos)
|
||||||
|
cm.doc.setCursor(newCursorPos)
|
||||||
|
},
|
||||||
|
[translateHotkey(hotkey.sortLines)]: cm => {
|
||||||
|
const selection = cm.doc.getSelection()
|
||||||
|
const appendLineBreak = /\n$/.test(selection)
|
||||||
|
|
||||||
|
const sorted = _.split(selection.trim(), '\n').sort()
|
||||||
|
const sortedString = _.join(sorted, '\n') + (appendLineBreak ? '\n' : '')
|
||||||
|
|
||||||
|
cm.doc.replaceSelection(sortedString)
|
||||||
|
},
|
||||||
[translateHotkey(hotkey.pasteSmartly)]: cm => {
|
[translateHotkey(hotkey.pasteSmartly)]: cm => {
|
||||||
this.handlePaste(cm, true)
|
this.handlePaste(cm, true)
|
||||||
}
|
}
|
||||||
@@ -283,20 +273,19 @@ export default class CodeEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
const { rulers, enableRulers } = this.props
|
const { rulers, enableRulers, enableMarkdownLint } = this.props
|
||||||
eventEmitter.on('line:jump', this.scrollToLineHandeler)
|
eventEmitter.on('line:jump', this.scrollToLineHandeler)
|
||||||
|
|
||||||
snippetManager.init()
|
snippetManager.init()
|
||||||
this.updateDefaultKeyMap()
|
this.updateDefaultKeyMap()
|
||||||
|
|
||||||
const checkMarkdownNoteIsOpening = this.props.mode === 'Boost Flavored Markdown'
|
|
||||||
this.value = this.props.value
|
this.value = this.props.value
|
||||||
this.editor = CodeMirror(this.refs.root, {
|
this.editor = CodeMirror(this.refs.root, {
|
||||||
rulers: buildCMRulers(rulers, enableRulers),
|
rulers: buildCMRulers(rulers, enableRulers),
|
||||||
value: this.props.value,
|
value: this.props.value,
|
||||||
linesHighlighted: this.props.linesHighlighted,
|
linesHighlighted: this.props.linesHighlighted,
|
||||||
lineNumbers: this.props.displayLineNumbers,
|
lineNumbers: this.props.displayLineNumbers,
|
||||||
lineWrapping: true,
|
lineWrapping: this.props.lineWrapping,
|
||||||
theme: this.props.theme,
|
theme: this.props.theme,
|
||||||
indentUnit: this.props.indentSize,
|
indentUnit: this.props.indentSize,
|
||||||
tabSize: this.props.indentSize,
|
tabSize: this.props.indentSize,
|
||||||
@@ -306,10 +295,7 @@ export default class CodeEditor extends React.Component {
|
|||||||
inputStyle: 'textarea',
|
inputStyle: 'textarea',
|
||||||
dragDrop: false,
|
dragDrop: false,
|
||||||
foldGutter: true,
|
foldGutter: true,
|
||||||
lint: checkMarkdownNoteIsOpening ? {
|
lint: enableMarkdownLint ? this.getCodeEditorLintConfig() : false,
|
||||||
'getAnnotations': validatorOfMarkdown,
|
|
||||||
'async': true
|
|
||||||
} : false,
|
|
||||||
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers'],
|
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers'],
|
||||||
autoCloseBrackets: {
|
autoCloseBrackets: {
|
||||||
pairs: this.props.matchingPairs,
|
pairs: this.props.matchingPairs,
|
||||||
@@ -317,9 +303,12 @@ export default class CodeEditor extends React.Component {
|
|||||||
explode: this.props.explodingPairs,
|
explode: this.props.explodingPairs,
|
||||||
override: true
|
override: true
|
||||||
},
|
},
|
||||||
extraKeys: this.defaultKeyMap
|
extraKeys: this.defaultKeyMap,
|
||||||
|
prettierConfig: this.props.prettierConfig
|
||||||
})
|
})
|
||||||
|
|
||||||
|
document.querySelector('.CodeMirror-lint-markers').style.display = enableMarkdownLint ? 'inline-block' : 'none'
|
||||||
|
|
||||||
if (!this.props.mode && this.props.value && this.props.autoDetect) {
|
if (!this.props.mode && this.props.value && this.props.autoDetect) {
|
||||||
this.autoDetectLanguage(this.props.value)
|
this.autoDetectLanguage(this.props.value)
|
||||||
} else {
|
} else {
|
||||||
@@ -546,7 +535,9 @@ export default class CodeEditor extends React.Component {
|
|||||||
let needRefresh = false
|
let needRefresh = false
|
||||||
const {
|
const {
|
||||||
rulers,
|
rulers,
|
||||||
enableRulers
|
enableRulers,
|
||||||
|
enableMarkdownLint,
|
||||||
|
customMarkdownLintConfig
|
||||||
} = this.props
|
} = this.props
|
||||||
if (prevProps.mode !== this.props.mode) {
|
if (prevProps.mode !== this.props.mode) {
|
||||||
this.setMode(this.props.mode)
|
this.setMode(this.props.mode)
|
||||||
@@ -564,6 +555,16 @@ export default class CodeEditor extends React.Component {
|
|||||||
if (prevProps.keyMap !== this.props.keyMap) {
|
if (prevProps.keyMap !== this.props.keyMap) {
|
||||||
needRefresh = true
|
needRefresh = true
|
||||||
}
|
}
|
||||||
|
if (prevProps.enableMarkdownLint !== enableMarkdownLint || prevProps.customMarkdownLintConfig !== customMarkdownLintConfig) {
|
||||||
|
if (!enableMarkdownLint) {
|
||||||
|
this.editor.setOption('lint', {default: false})
|
||||||
|
document.querySelector('.CodeMirror-lint-markers').style.display = 'none'
|
||||||
|
} else {
|
||||||
|
this.editor.setOption('lint', this.getCodeEditorLintConfig())
|
||||||
|
document.querySelector('.CodeMirror-lint-markers').style.display = 'inline-block'
|
||||||
|
}
|
||||||
|
needRefresh = true
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
prevProps.enableRulers !== enableRulers ||
|
prevProps.enableRulers !== enableRulers ||
|
||||||
@@ -584,6 +585,10 @@ export default class CodeEditor extends React.Component {
|
|||||||
this.editor.setOption('lineNumbers', this.props.displayLineNumbers)
|
this.editor.setOption('lineNumbers', this.props.displayLineNumbers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prevProps.lineWrapping !== this.props.lineWrapping) {
|
||||||
|
this.editor.setOption('lineWrapping', this.props.lineWrapping)
|
||||||
|
}
|
||||||
|
|
||||||
if (prevProps.scrollPastEnd !== this.props.scrollPastEnd) {
|
if (prevProps.scrollPastEnd !== this.props.scrollPastEnd) {
|
||||||
this.editor.setOption('scrollPastEnd', this.props.scrollPastEnd)
|
this.editor.setOption('scrollPastEnd', this.props.scrollPastEnd)
|
||||||
}
|
}
|
||||||
@@ -638,12 +643,65 @@ export default class CodeEditor extends React.Component {
|
|||||||
this.editor.addPanel(this.createSpellCheckPanel(), {position: 'bottom'})
|
this.editor.addPanel(this.createSpellCheckPanel(), {position: 'bottom'})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (prevProps.deleteUnusedAttachments !== this.props.deleteUnusedAttachments) {
|
||||||
|
this.editor.setOption('deleteUnusedAttachments', this.props.deleteUnusedAttachments)
|
||||||
|
}
|
||||||
|
|
||||||
if (needRefresh) {
|
if (needRefresh) {
|
||||||
this.editor.refresh()
|
this.editor.refresh()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCodeEditorLintConfig () {
|
||||||
|
const { mode } = this.props
|
||||||
|
const checkMarkdownNoteIsOpen = mode === 'Boost Flavored Markdown'
|
||||||
|
|
||||||
|
return checkMarkdownNoteIsOpen ? {
|
||||||
|
getAnnotations: this.validatorOfMarkdown,
|
||||||
|
async: true
|
||||||
|
} : false
|
||||||
|
}
|
||||||
|
|
||||||
|
validatorOfMarkdown (text, updateLinting) {
|
||||||
|
const { customMarkdownLintConfig } = this.props
|
||||||
|
let lintConfigJson
|
||||||
|
try {
|
||||||
|
Jsonlint.parse(customMarkdownLintConfig)
|
||||||
|
lintConfigJson = JSON.parse(customMarkdownLintConfig)
|
||||||
|
} catch (err) {
|
||||||
|
eventEmitter.emit('APP_SETTING_ERROR')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const lintOptions = {
|
||||||
|
strings: {
|
||||||
|
content: text
|
||||||
|
},
|
||||||
|
config: lintConfigJson
|
||||||
|
}
|
||||||
|
|
||||||
|
return markdownlint(lintOptions, (err, result) => {
|
||||||
|
if (!err) {
|
||||||
|
const foundIssues = []
|
||||||
|
const splitText = text.split('\n')
|
||||||
|
result.content.map(item => {
|
||||||
|
let ruleNames = ''
|
||||||
|
item.ruleNames.map((ruleName, index) => {
|
||||||
|
ruleNames += ruleName
|
||||||
|
ruleNames += (index === item.ruleNames.length - 1) ? ': ' : '/'
|
||||||
|
})
|
||||||
|
const lineNumber = item.lineNumber - 1
|
||||||
|
foundIssues.push({
|
||||||
|
from: CodeMirror.Pos(lineNumber, 0),
|
||||||
|
to: CodeMirror.Pos(lineNumber, splitText[lineNumber].length),
|
||||||
|
message: ruleNames + item.ruleDescription,
|
||||||
|
severity: 'warning'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
updateLinting(foundIssues)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
setMode (mode) {
|
setMode (mode) {
|
||||||
let syntax = CodeMirror.findModeByName(convertModeName(mode || 'text'))
|
let syntax = CodeMirror.findModeByName(convertModeName(mode || 'text'))
|
||||||
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')
|
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')
|
||||||
@@ -816,6 +874,17 @@ export default class CodeEditor extends React.Component {
|
|||||||
this.editor.setCursor(cursor)
|
this.editor.setCursor(cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update content of one line
|
||||||
|
* @param {Number} lineNumber
|
||||||
|
* @param {String} content
|
||||||
|
*/
|
||||||
|
setLineContent (lineNumber, content) {
|
||||||
|
const prevContent = this.editor.getLine(lineNumber)
|
||||||
|
const prevContentLength = prevContent ? prevContent.length : 0
|
||||||
|
this.editor.replaceRange(content, { line: lineNumber, ch: 0 }, { line: lineNumber, ch: prevContentLength })
|
||||||
|
}
|
||||||
|
|
||||||
handleDropImage (dropEvent) {
|
handleDropImage (dropEvent) {
|
||||||
dropEvent.preventDefault()
|
dropEvent.preventDefault()
|
||||||
const {
|
const {
|
||||||
@@ -1105,13 +1174,11 @@ export default class CodeEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
ref='root'
|
ref='root'
|
||||||
tabIndex='-1'
|
tabIndex='-1'
|
||||||
style={
|
style={{
|
||||||
{
|
|
||||||
fontFamily,
|
fontFamily,
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
width: width
|
width: width
|
||||||
}
|
}}
|
||||||
}
|
|
||||||
onDrop={
|
onDrop={
|
||||||
e => this.handleDropImage(e)
|
e => this.handleDropImage(e)
|
||||||
}
|
}
|
||||||
@@ -1149,7 +1216,10 @@ CodeEditor.propTypes = {
|
|||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
readOnly: PropTypes.bool,
|
readOnly: PropTypes.bool,
|
||||||
autoDetect: PropTypes.bool,
|
autoDetect: PropTypes.bool,
|
||||||
spellCheck: PropTypes.bool
|
spellCheck: PropTypes.bool,
|
||||||
|
enableMarkdownLint: PropTypes.bool,
|
||||||
|
customMarkdownLintConfig: PropTypes.string,
|
||||||
|
deleteUnusedAttachments: PropTypes.bool
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeEditor.defaultProps = {
|
CodeEditor.defaultProps = {
|
||||||
@@ -1161,5 +1231,9 @@ CodeEditor.defaultProps = {
|
|||||||
indentSize: 4,
|
indentSize: 4,
|
||||||
indentType: 'space',
|
indentType: 'space',
|
||||||
autoDetect: false,
|
autoDetect: false,
|
||||||
spellCheck: false
|
spellCheck: false,
|
||||||
|
enableMarkdownLint: DEFAULT_CONFIG.editor.enableMarkdownLint,
|
||||||
|
customMarkdownLintConfig: DEFAULT_CONFIG.editor.customMarkdownLintConfig,
|
||||||
|
prettierConfig: DEFAULT_CONFIG.editor.prettierConfig,
|
||||||
|
deleteUnusedAttachments: DEFAULT_CONFIG.editor.deleteUnusedAttachments
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ class MarkdownEditor extends React.Component {
|
|||||||
status: 'PREVIEW'
|
status: 'PREVIEW'
|
||||||
}, () => {
|
}, () => {
|
||||||
this.refs.preview.focus()
|
this.refs.preview.focus()
|
||||||
this.refs.preview.scrollTo(cursorPosition.line)
|
this.refs.preview.scrollToRow(cursorPosition.line)
|
||||||
})
|
})
|
||||||
eventEmitter.emit('topbar:togglelockbutton', this.state.status)
|
eventEmitter.emit('topbar:togglelockbutton', this.state.status)
|
||||||
}
|
}
|
||||||
@@ -159,24 +159,25 @@ class MarkdownEditor extends React.Component {
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
const idMatch = /checkbox-([0-9]+)/
|
const idMatch = /checkbox-([0-9]+)/
|
||||||
const checkedMatch = /^\s*[\+\-\*] \[x\]/i
|
const checkedMatch = /^(\s*>?)*\s*[+\-*] \[x]/i
|
||||||
const uncheckedMatch = /^\s*[\+\-\*] \[ \]/
|
const uncheckedMatch = /^(\s*>?)*\s*[+\-*] \[ ]/
|
||||||
const checkReplace = /\[x\]/i
|
const checkReplace = /\[x]/i
|
||||||
const uncheckReplace = /\[ \]/
|
const uncheckReplace = /\[ ]/
|
||||||
if (idMatch.test(e.target.getAttribute('id'))) {
|
if (idMatch.test(e.target.getAttribute('id'))) {
|
||||||
const lineIndex = parseInt(e.target.getAttribute('id').match(idMatch)[1], 10) - 1
|
const lineIndex = parseInt(e.target.getAttribute('id').match(idMatch)[1], 10) - 1
|
||||||
const lines = this.refs.code.value
|
const lines = this.refs.code.value
|
||||||
.split('\n')
|
.split('\n')
|
||||||
|
|
||||||
const targetLine = lines[lineIndex]
|
const targetLine = lines[lineIndex]
|
||||||
|
let newLine = targetLine
|
||||||
|
|
||||||
if (targetLine.match(checkedMatch)) {
|
if (targetLine.match(checkedMatch)) {
|
||||||
lines[lineIndex] = targetLine.replace(checkReplace, '[ ]')
|
newLine = targetLine.replace(checkReplace, '[ ]')
|
||||||
}
|
}
|
||||||
if (targetLine.match(uncheckedMatch)) {
|
if (targetLine.match(uncheckedMatch)) {
|
||||||
lines[lineIndex] = targetLine.replace(uncheckReplace, '[x]')
|
newLine = targetLine.replace(uncheckReplace, '[x]')
|
||||||
}
|
}
|
||||||
this.refs.code.setValue(lines.join('\n'))
|
this.refs.code.setLineContent(lineIndex, newLine)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,6 +305,7 @@ class MarkdownEditor extends React.Component {
|
|||||||
enableRulers={config.editor.enableRulers}
|
enableRulers={config.editor.enableRulers}
|
||||||
rulers={config.editor.rulers}
|
rulers={config.editor.rulers}
|
||||||
displayLineNumbers={config.editor.displayLineNumbers}
|
displayLineNumbers={config.editor.displayLineNumbers}
|
||||||
|
lineWrapping
|
||||||
matchingPairs={config.editor.matchingPairs}
|
matchingPairs={config.editor.matchingPairs}
|
||||||
matchingTriples={config.editor.matchingTriples}
|
matchingTriples={config.editor.matchingTriples}
|
||||||
explodingPairs={config.editor.explodingPairs}
|
explodingPairs={config.editor.explodingPairs}
|
||||||
@@ -319,6 +321,10 @@ class MarkdownEditor extends React.Component {
|
|||||||
enableSmartPaste={config.editor.enableSmartPaste}
|
enableSmartPaste={config.editor.enableSmartPaste}
|
||||||
hotkey={config.hotkey}
|
hotkey={config.hotkey}
|
||||||
switchPreview={config.editor.switchPreview}
|
switchPreview={config.editor.switchPreview}
|
||||||
|
enableMarkdownLint={config.editor.enableMarkdownLint}
|
||||||
|
customMarkdownLintConfig={config.editor.customMarkdownLintConfig}
|
||||||
|
prettierConfig={config.editor.prettierConfig}
|
||||||
|
deleteUnusedAttachments={config.editor.deleteUnusedAttachments}
|
||||||
/>
|
/>
|
||||||
<MarkdownPreview styleName={this.state.status === 'PREVIEW'
|
<MarkdownPreview styleName={this.state.status === 'PREVIEW'
|
||||||
? 'preview'
|
? 'preview'
|
||||||
@@ -338,6 +344,7 @@ class MarkdownEditor extends React.Component {
|
|||||||
smartArrows={config.preview.smartArrows}
|
smartArrows={config.preview.smartArrows}
|
||||||
breaks={config.preview.breaks}
|
breaks={config.preview.breaks}
|
||||||
sanitize={config.preview.sanitize}
|
sanitize={config.preview.sanitize}
|
||||||
|
mermaidHTMLLabel={config.preview.mermaidHTMLLabel}
|
||||||
ref='preview'
|
ref='preview'
|
||||||
onContextMenu={(e) => this.handleContextMenu(e)}
|
onContextMenu={(e) => this.handleContextMenu(e)}
|
||||||
onDoubleClick={(e) => this.handleDoubleClick(e)}
|
onDoubleClick={(e) => this.handleDoubleClick(e)}
|
||||||
|
|||||||
@@ -18,15 +18,14 @@ 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 { escapeHtmlCharacters } from 'browser/lib/utils'
|
||||||
import yaml from 'js-yaml'
|
import yaml from 'js-yaml'
|
||||||
import context from 'browser/lib/context'
|
|
||||||
import i18n from 'browser/lib/i18n'
|
|
||||||
import fs from 'fs'
|
|
||||||
import { render } from 'react-dom'
|
import { render } from 'react-dom'
|
||||||
import Carousel from 'react-image-carousel'
|
import Carousel from 'react-image-carousel'
|
||||||
import ConfigManager from '../main/lib/ConfigManager'
|
import ConfigManager from '../main/lib/ConfigManager'
|
||||||
|
import i18n from 'browser/lib/i18n'
|
||||||
|
|
||||||
const { remote, shell } = require('electron')
|
const { remote, shell } = require('electron')
|
||||||
const attachmentManagement = require('../main/lib/dataApi/attachmentManagement')
|
const attachmentManagement = require('../main/lib/dataApi/attachmentManagement')
|
||||||
|
const buildMarkdownPreviewContextMenu = require('browser/lib/contextMenuBuilder').buildMarkdownPreviewContextMenu
|
||||||
|
|
||||||
const { app } = remote
|
const { app } = remote
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
@@ -34,8 +33,6 @@ const fileUrl = require('file-url')
|
|||||||
|
|
||||||
const dialog = remote.dialog
|
const dialog = remote.dialog
|
||||||
|
|
||||||
const uri2path = require('file-uri-to-path')
|
|
||||||
|
|
||||||
const markdownStyle = require('!!css!stylus?sourceMap!./markdown.styl')[0][1]
|
const markdownStyle = require('!!css!stylus?sourceMap!./markdown.styl')[0][1]
|
||||||
const appPath = fileUrl(
|
const appPath = fileUrl(
|
||||||
process.env.NODE_ENV === 'production' ? app.getAppPath() : path.resolve()
|
process.env.NODE_ENV === 'production' ? app.getAppPath() : path.resolve()
|
||||||
@@ -46,16 +43,29 @@ const CSS_FILES = [
|
|||||||
`${appPath}/node_modules/react-image-carousel/lib/css/main.min.css`
|
`${appPath}/node_modules/react-image-carousel/lib/css/main.min.css`
|
||||||
]
|
]
|
||||||
|
|
||||||
function buildStyle (
|
/**
|
||||||
fontFamily,
|
* @param {Object} opts
|
||||||
fontSize,
|
* @param {String} opts.fontFamily
|
||||||
codeBlockFontFamily,
|
* @param {Numberl} opts.fontSize
|
||||||
lineNumber,
|
* @param {String} opts.codeBlockFontFamily
|
||||||
scrollPastEnd,
|
* @param {String} opts.theme
|
||||||
theme,
|
* @param {Boolean} [opts.lineNumber] Should show line number
|
||||||
allowCustomCSS,
|
* @param {Boolean} [opts.scrollPastEnd]
|
||||||
customCSS
|
* @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
|
||||||
|
} = opts
|
||||||
return `
|
return `
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Lato';
|
font-family: 'Lato';
|
||||||
@@ -85,12 +95,17 @@ function buildStyle (
|
|||||||
url('${appPath}/resources/fonts/MaterialIcons-Regular.woff') format('woff'),
|
url('${appPath}/resources/fonts/MaterialIcons-Regular.woff') format('woff'),
|
||||||
url('${appPath}/resources/fonts/MaterialIcons-Regular.ttf') format('truetype');
|
url('${appPath}/resources/fonts/MaterialIcons-Regular.ttf') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
${markdownStyle}
|
${markdownStyle}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: '${fontFamily.join("','")}';
|
font-family: '${fontFamily.join("','")}';
|
||||||
font-size: ${fontSize}px;
|
font-size: ${fontSize}px;
|
||||||
${scrollPastEnd && 'padding-bottom: 90vh;'}
|
${scrollPastEnd ? `
|
||||||
|
padding-bottom: 90vh;
|
||||||
|
box-sizing: border-box;
|
||||||
|
`
|
||||||
|
: ''}
|
||||||
}
|
}
|
||||||
@media print {
|
@media print {
|
||||||
body {
|
body {
|
||||||
@@ -166,6 +181,10 @@ const scrollBarStyle = `
|
|||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
background-color: rgba(0, 0, 0, 0.15);
|
background-color: rgba(0, 0, 0, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track-piece {
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
`
|
`
|
||||||
const scrollBarDarkStyle = `
|
const scrollBarDarkStyle = `
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
@@ -175,6 +194,10 @@ const scrollBarDarkStyle = `
|
|||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
background-color: rgba(0, 0, 0, 0.3);
|
background-color: rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track-piece {
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const OSX = global.process.platform === 'darwin'
|
const OSX = global.process.platform === 'darwin'
|
||||||
@@ -223,6 +246,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
this.saveAsHtmlHandler = () => this.handleSaveAsHtml()
|
this.saveAsHtmlHandler = () => this.handleSaveAsHtml()
|
||||||
this.saveAsPdfHandler = () => this.handleSaveAsPdf()
|
this.saveAsPdfHandler = () => this.handleSaveAsPdf()
|
||||||
this.printHandler = () => this.handlePrint()
|
this.printHandler = () => this.handlePrint()
|
||||||
|
this.resizeHandler = _.throttle(this.handleResize.bind(this), 100)
|
||||||
|
|
||||||
this.linkClickHandler = this.handleLinkClick.bind(this)
|
this.linkClickHandler = this.handleLinkClick.bind(this)
|
||||||
this.initMarkdown = this.initMarkdown.bind(this)
|
this.initMarkdown = this.initMarkdown.bind(this)
|
||||||
@@ -249,30 +273,12 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleContextMenu (event) {
|
handleContextMenu (event) {
|
||||||
// If a contextMenu handler was passed to us, use it instead of the self-defined one -> return
|
const menu = buildMarkdownPreviewContextMenu(this, event)
|
||||||
if (_.isFunction(this.props.onContextMenu)) {
|
const switchPreview = ConfigManager.get().editor.switchPreview
|
||||||
|
if (menu != null && switchPreview !== 'RIGHTCLICK') {
|
||||||
|
menu.popup(remote.getCurrentWindow())
|
||||||
|
} else if (_.isFunction(this.props.onContextMenu)) {
|
||||||
this.props.onContextMenu(event)
|
this.props.onContextMenu(event)
|
||||||
return
|
|
||||||
}
|
|
||||||
// No contextMenu was passed to us -> execute our own link-opener
|
|
||||||
if (event.target.tagName.toLowerCase() === 'a' && event.target.getAttribute('href')) {
|
|
||||||
const href = event.target.href
|
|
||||||
const isLocalFile = href.startsWith('file:')
|
|
||||||
if (isLocalFile) {
|
|
||||||
const absPath = uri2path(href)
|
|
||||||
try {
|
|
||||||
if (fs.lstatSync(absPath).isFile()) {
|
|
||||||
context.popup([
|
|
||||||
{
|
|
||||||
label: i18n.__('Show in explorer'),
|
|
||||||
click: (e) => shell.showItemInFolder(absPath)
|
|
||||||
}
|
|
||||||
])
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log('Error while evaluating if the file is locally available', e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,7 +340,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
customCSS
|
customCSS
|
||||||
} = this.getStyleParams()
|
} = this.getStyleParams()
|
||||||
|
|
||||||
const inlineStyles = buildStyle(
|
const inlineStyles = buildStyle({
|
||||||
fontFamily,
|
fontFamily,
|
||||||
fontSize,
|
fontSize,
|
||||||
codeBlockFontFamily,
|
codeBlockFontFamily,
|
||||||
@@ -343,9 +349,13 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
theme,
|
theme,
|
||||||
allowCustomCSS,
|
allowCustomCSS,
|
||||||
customCSS
|
customCSS
|
||||||
|
})
|
||||||
|
let body = this.refs.root.contentWindow.document.body.innerHTML
|
||||||
|
body = attachmentManagement.fixLocalURLS(
|
||||||
|
body,
|
||||||
|
this.props.storagePath
|
||||||
)
|
)
|
||||||
let body = this.markdown.render(noteContent)
|
const files = [this.getCodeThemeLink(codeBlockTheme), ...CSS_FILES]
|
||||||
const files = [this.GetCodeThemeLink(codeBlockTheme), ...CSS_FILES]
|
|
||||||
files.forEach(file => {
|
files.forEach(file => {
|
||||||
if (global.process.platform === 'win32') {
|
if (global.process.platform === 'win32') {
|
||||||
file = file.replace('file:///', '')
|
file = file.replace('file:///', '')
|
||||||
@@ -360,7 +370,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
|
|
||||||
let styles = ''
|
let styles = ''
|
||||||
files.forEach(file => {
|
files.forEach(file => {
|
||||||
styles += `<link rel="stylesheet" href="css/${path.basename(file)}">`
|
styles += `<link rel="stylesheet" href="../css/${path.basename(file)}">`
|
||||||
})
|
})
|
||||||
|
|
||||||
return `<html>
|
return `<html>
|
||||||
@@ -381,7 +391,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
|
|
||||||
handleSaveAsPdf () {
|
handleSaveAsPdf () {
|
||||||
this.exportAsDocument('pdf', (noteContent, exportTasks, targetDir) => {
|
this.exportAsDocument('pdf', (noteContent, exportTasks, targetDir) => {
|
||||||
const printout = new remote.BrowserWindow({show: false, webPreferences: {webSecurity: false}})
|
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))
|
printout.loadURL('data:text/html;charset=UTF-8,' + this.htmlContentFormatter(noteContent, exportTasks, targetDir))
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
printout.webContents.on('did-finish-load', () => {
|
printout.webContents.on('did-finish-load', () => {
|
||||||
@@ -415,7 +425,8 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
.then(res => {
|
.then(res => {
|
||||||
dialog.showMessageBox(remote.getCurrentWindow(), {
|
dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||||
type: 'info',
|
type: 'info',
|
||||||
message: `Exported to ${filename}`
|
message: `Exported to ${filename}`,
|
||||||
|
buttons: [i18n.__('Ok')]
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
@@ -530,6 +541,10 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
'scroll',
|
'scroll',
|
||||||
this.scrollHandler
|
this.scrollHandler
|
||||||
)
|
)
|
||||||
|
this.refs.root.contentWindow.addEventListener(
|
||||||
|
'resize',
|
||||||
|
this.resizeHandler
|
||||||
|
)
|
||||||
eventEmitter.on('export:save-text', this.saveAsTextHandler)
|
eventEmitter.on('export:save-text', this.saveAsTextHandler)
|
||||||
eventEmitter.on('export:save-md', this.saveAsMdHandler)
|
eventEmitter.on('export:save-md', this.saveAsMdHandler)
|
||||||
eventEmitter.on('export:save-html', this.saveAsHtmlHandler)
|
eventEmitter.on('export:save-html', this.saveAsHtmlHandler)
|
||||||
@@ -568,6 +583,10 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
'scroll',
|
'scroll',
|
||||||
this.scrollHandler
|
this.scrollHandler
|
||||||
)
|
)
|
||||||
|
this.refs.root.contentWindow.removeEventListener(
|
||||||
|
'resize',
|
||||||
|
this.resizeHandler
|
||||||
|
)
|
||||||
eventEmitter.off('export:save-text', this.saveAsTextHandler)
|
eventEmitter.off('export:save-text', this.saveAsTextHandler)
|
||||||
eventEmitter.off('export:save-md', this.saveAsMdHandler)
|
eventEmitter.off('export:save-md', this.saveAsMdHandler)
|
||||||
eventEmitter.off('export:save-html', this.saveAsHtmlHandler)
|
eventEmitter.off('export:save-html', this.saveAsHtmlHandler)
|
||||||
@@ -576,16 +595,19 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate (prevProps) {
|
componentDidUpdate (prevProps) {
|
||||||
if (prevProps.value !== this.props.value) this.rewriteIframe()
|
// actual rewriteIframe function should be called only once
|
||||||
|
let needsRewriteIframe = false
|
||||||
|
if (prevProps.value !== this.props.value) needsRewriteIframe = true
|
||||||
if (
|
if (
|
||||||
prevProps.smartQuotes !== this.props.smartQuotes ||
|
prevProps.smartQuotes !== this.props.smartQuotes ||
|
||||||
prevProps.sanitize !== this.props.sanitize ||
|
prevProps.sanitize !== this.props.sanitize ||
|
||||||
|
prevProps.mermaidHTMLLabel !== this.props.mermaidHTMLLabel ||
|
||||||
prevProps.smartArrows !== this.props.smartArrows ||
|
prevProps.smartArrows !== this.props.smartArrows ||
|
||||||
prevProps.breaks !== this.props.breaks ||
|
prevProps.breaks !== this.props.breaks ||
|
||||||
prevProps.lineThroughCheckbox !== this.props.lineThroughCheckbox
|
prevProps.lineThroughCheckbox !== this.props.lineThroughCheckbox
|
||||||
) {
|
) {
|
||||||
this.initMarkdown()
|
this.initMarkdown()
|
||||||
this.rewriteIframe()
|
needsRewriteIframe = true
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
prevProps.fontFamily !== this.props.fontFamily ||
|
prevProps.fontFamily !== this.props.fontFamily ||
|
||||||
@@ -600,8 +622,17 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
prevProps.customCSS !== this.props.customCSS
|
prevProps.customCSS !== this.props.customCSS
|
||||||
) {
|
) {
|
||||||
this.applyStyle()
|
this.applyStyle()
|
||||||
|
needsRewriteIframe = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsRewriteIframe) {
|
||||||
this.rewriteIframe()
|
this.rewriteIframe()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Should scroll to top after selecting another note
|
||||||
|
if (prevProps.noteKey !== this.props.noteKey) {
|
||||||
|
this.scrollTo(0, 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getStyleParams () {
|
getStyleParams () {
|
||||||
@@ -657,8 +688,8 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
|
|
||||||
this.getWindow().document.getElementById(
|
this.getWindow().document.getElementById(
|
||||||
'codeTheme'
|
'codeTheme'
|
||||||
).href = this.GetCodeThemeLink(codeBlockTheme)
|
).href = this.getCodeThemeLink(codeBlockTheme)
|
||||||
this.getWindow().document.getElementById('style').innerHTML = buildStyle(
|
this.getWindow().document.getElementById('style').innerHTML = buildStyle({
|
||||||
fontFamily,
|
fontFamily,
|
||||||
fontSize,
|
fontSize,
|
||||||
codeBlockFontFamily,
|
codeBlockFontFamily,
|
||||||
@@ -667,17 +698,15 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
theme,
|
theme,
|
||||||
allowCustomCSS,
|
allowCustomCSS,
|
||||||
customCSS
|
customCSS
|
||||||
)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
GetCodeThemeLink (name) {
|
getCodeThemeLink (name) {
|
||||||
const theme = consts.THEMES.find(theme => theme.name === name)
|
const theme = consts.THEMES.find(theme => theme.name === name)
|
||||||
|
|
||||||
if (theme) {
|
return theme != null
|
||||||
return `${appPath}/${theme.path}`
|
? theme.path
|
||||||
} else {
|
: `${appPath}/node_modules/codemirror/theme/elegant.css`
|
||||||
return `${appPath}/node_modules/codemirror/theme/elegant.css`
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rewriteIframe () {
|
rewriteIframe () {
|
||||||
@@ -703,7 +732,8 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
showCopyNotification,
|
showCopyNotification,
|
||||||
storagePath,
|
storagePath,
|
||||||
noteKey,
|
noteKey,
|
||||||
sanitize
|
sanitize,
|
||||||
|
mermaidHTMLLabel
|
||||||
} = this.props
|
} = this.props
|
||||||
let { value, codeBlockTheme } = this.props
|
let { value, codeBlockTheme } = this.props
|
||||||
|
|
||||||
@@ -835,6 +865,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
canvas.height = height.value + 'vh'
|
canvas.height = height.value + 'vh'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
const chart = new Chart(canvas, chartConfig)
|
const chart = new Chart(canvas, chartConfig)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
el.className = 'chart-error'
|
el.className = 'chart-error'
|
||||||
@@ -845,7 +876,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
_.forEach(
|
_.forEach(
|
||||||
this.refs.root.contentWindow.document.querySelectorAll('.mermaid'),
|
this.refs.root.contentWindow.document.querySelectorAll('.mermaid'),
|
||||||
el => {
|
el => {
|
||||||
mermaidRender(el, htmlTextHelper.decodeEntities(el.innerHTML), theme)
|
mermaidRender(el, htmlTextHelper.decodeEntities(el.innerHTML), theme, mermaidHTMLLabel)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -895,6 +926,12 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
this.setImgOnClickEventHelper(img, rect)
|
this.setImgOnClickEventHelper(img, rect)
|
||||||
imgObserver.observe(parentEl, config)
|
imgObserver.observe(parentEl, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const aList = markdownPreviewIframe.contentWindow.document.body.querySelectorAll('a')
|
||||||
|
for (const a of aList) {
|
||||||
|
a.removeEventListener('click', this.linkClickHandler)
|
||||||
|
a.addEventListener('click', this.linkClickHandler)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setImgOnClickEventHelper (img, rect) {
|
setImgOnClickEventHelper (img, rect) {
|
||||||
@@ -967,8 +1004,15 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
overlay.appendChild(zoomImg)
|
overlay.appendChild(zoomImg)
|
||||||
document.body.appendChild(overlay)
|
document.body.appendChild(overlay)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.getWindow().scrollTo(0, 0)
|
handleResize () {
|
||||||
|
_.forEach(
|
||||||
|
this.refs.root.contentWindow.document.querySelectorAll('svg[ratio]'),
|
||||||
|
el => {
|
||||||
|
el.setAttribute('height', el.clientWidth / el.getAttribute('ratio'))
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
focus () {
|
focus () {
|
||||||
@@ -979,7 +1023,11 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
return this.refs.root.contentWindow
|
return this.refs.root.contentWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollTo (targetRow) {
|
/**
|
||||||
|
* @public
|
||||||
|
* @param {Number} targetRow
|
||||||
|
*/
|
||||||
|
scrollToRow (targetRow) {
|
||||||
const blocks = this.getWindow().document.querySelectorAll(
|
const blocks = this.getWindow().document.querySelectorAll(
|
||||||
'body>[data-line]'
|
'body>[data-line]'
|
||||||
)
|
)
|
||||||
@@ -989,12 +1037,21 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
const row = parseInt(block.getAttribute('data-line'))
|
const row = parseInt(block.getAttribute('data-line'))
|
||||||
if (row > targetRow || index === blocks.length - 1) {
|
if (row > targetRow || index === blocks.length - 1) {
|
||||||
block = blocks[index - 1]
|
block = blocks[index - 1]
|
||||||
block != null && this.getWindow().scrollTo(0, block.offsetTop)
|
block != null && this.scrollTo(0, block.offsetTop)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `document.body.scrollTo`
|
||||||
|
* @param {Number} x
|
||||||
|
* @param {Number} y
|
||||||
|
*/
|
||||||
|
scrollTo (x, y) {
|
||||||
|
this.getWindow().document.body.scrollTo(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
preventImageDroppedHandler (e) {
|
preventImageDroppedHandler (e) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
@@ -1015,22 +1072,32 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
|
|
||||||
const href = e.target.getAttribute('href')
|
const rawHref = e.target.getAttribute('href')
|
||||||
const linkHash = href.split('/').pop()
|
if (!rawHref) return // not checked href because parser will create file://... string for [empty link]()
|
||||||
|
|
||||||
if (!href) return
|
const parser = document.createElement('a')
|
||||||
|
parser.href = rawHref
|
||||||
|
const isStartWithHash = rawHref[0] === '#'
|
||||||
|
const { href, hash } = parser
|
||||||
|
|
||||||
const regexNoteInternalLink = /main.html#(.+)/
|
const linkHash = hash === '' ? rawHref : hash // needed because we're having special link formats that are removed by parser e.g. :line:10
|
||||||
if (regexNoteInternalLink.test(linkHash)) {
|
|
||||||
const targetId = mdurl.encode(linkHash.match(regexNoteInternalLink)[1])
|
|
||||||
const targetElement = this.refs.root.contentWindow.document.getElementById(
|
|
||||||
targetId
|
|
||||||
)
|
|
||||||
|
|
||||||
if (targetElement != null) {
|
const extractIdRegex = /file:\/\/.*main.?\w*.html#/ // file://path/to/main(.development.)html
|
||||||
this.getWindow().scrollTo(0, targetElement.offsetTop)
|
const regexNoteInternalLink = new RegExp(`${extractIdRegex.source}(.+)`)
|
||||||
|
if (isStartWithHash || regexNoteInternalLink.test(rawHref)) {
|
||||||
|
const posOfHash = linkHash.indexOf('#')
|
||||||
|
if (posOfHash > -1) {
|
||||||
|
const extractedId = linkHash.slice(posOfHash + 1)
|
||||||
|
const targetId = mdurl.encode(extractedId)
|
||||||
|
const targetElement = this.getWindow().document.getElementById(
|
||||||
|
targetId
|
||||||
|
)
|
||||||
|
|
||||||
|
if (targetElement != null) {
|
||||||
|
this.scrollTo(0, targetElement.offsetTop)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// this will match the new uuid v4 hash and the old hash
|
// this will match the new uuid v4 hash and the old hash
|
||||||
|
|||||||
@@ -78,24 +78,25 @@ class MarkdownSplitEditor extends React.Component {
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
const idMatch = /checkbox-([0-9]+)/
|
const idMatch = /checkbox-([0-9]+)/
|
||||||
const checkedMatch = /^\s*[\+\-\*] \[x\]/i
|
const checkedMatch = /^(\s*>?)*\s*[+\-*] \[x]/i
|
||||||
const uncheckedMatch = /^\s*[\+\-\*] \[ \]/
|
const uncheckedMatch = /^(\s*>?)*\s*[+\-*] \[ ]/
|
||||||
const checkReplace = /\[x\]/i
|
const checkReplace = /\[x]/i
|
||||||
const uncheckReplace = /\[ \]/
|
const uncheckReplace = /\[ ]/
|
||||||
if (idMatch.test(e.target.getAttribute('id'))) {
|
if (idMatch.test(e.target.getAttribute('id'))) {
|
||||||
const lineIndex = parseInt(e.target.getAttribute('id').match(idMatch)[1], 10) - 1
|
const lineIndex = parseInt(e.target.getAttribute('id').match(idMatch)[1], 10) - 1
|
||||||
const lines = this.refs.code.value
|
const lines = this.refs.code.value
|
||||||
.split('\n')
|
.split('\n')
|
||||||
|
|
||||||
const targetLine = lines[lineIndex]
|
const targetLine = lines[lineIndex]
|
||||||
|
let newLine = targetLine
|
||||||
|
|
||||||
if (targetLine.match(checkedMatch)) {
|
if (targetLine.match(checkedMatch)) {
|
||||||
lines[lineIndex] = targetLine.replace(checkReplace, '[ ]')
|
newLine = targetLine.replace(checkReplace, '[ ]')
|
||||||
}
|
}
|
||||||
if (targetLine.match(uncheckedMatch)) {
|
if (targetLine.match(uncheckedMatch)) {
|
||||||
lines[lineIndex] = targetLine.replace(uncheckReplace, '[x]')
|
newLine = targetLine.replace(uncheckReplace, '[x]')
|
||||||
}
|
}
|
||||||
this.refs.code.setValue(lines.join('\n'))
|
this.refs.code.setLineContent(lineIndex, newLine)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +151,6 @@ class MarkdownSplitEditor extends React.Component {
|
|||||||
onMouseMove={e => this.handleMouseMove(e)}
|
onMouseMove={e => this.handleMouseMove(e)}
|
||||||
onMouseUp={e => this.handleMouseUp(e)}>
|
onMouseUp={e => this.handleMouseUp(e)}>
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
styleName='codeEditor'
|
|
||||||
ref='code'
|
ref='code'
|
||||||
width={this.state.codeEditorWidthInPercent + '%'}
|
width={this.state.codeEditorWidthInPercent + '%'}
|
||||||
mode='Boost Flavored Markdown'
|
mode='Boost Flavored Markdown'
|
||||||
@@ -160,6 +160,7 @@ class MarkdownSplitEditor extends React.Component {
|
|||||||
fontFamily={config.editor.fontFamily}
|
fontFamily={config.editor.fontFamily}
|
||||||
fontSize={editorFontSize}
|
fontSize={editorFontSize}
|
||||||
displayLineNumbers={config.editor.displayLineNumbers}
|
displayLineNumbers={config.editor.displayLineNumbers}
|
||||||
|
lineWrapping
|
||||||
matchingPairs={config.editor.matchingPairs}
|
matchingPairs={config.editor.matchingPairs}
|
||||||
matchingTriples={config.editor.matchingTriples}
|
matchingTriples={config.editor.matchingTriples}
|
||||||
explodingPairs={config.editor.explodingPairs}
|
explodingPairs={config.editor.explodingPairs}
|
||||||
@@ -179,13 +180,15 @@ class MarkdownSplitEditor extends React.Component {
|
|||||||
enableSmartPaste={config.editor.enableSmartPaste}
|
enableSmartPaste={config.editor.enableSmartPaste}
|
||||||
hotkey={config.hotkey}
|
hotkey={config.hotkey}
|
||||||
switchPreview={config.editor.switchPreview}
|
switchPreview={config.editor.switchPreview}
|
||||||
|
enableMarkdownLint={config.editor.enableMarkdownLint}
|
||||||
|
customMarkdownLintConfig={config.editor.customMarkdownLintConfig}
|
||||||
|
deleteUnusedAttachments={config.editor.deleteUnusedAttachments}
|
||||||
/>
|
/>
|
||||||
<div styleName='slider' style={{left: this.state.codeEditorWidthInPercent + '%'}} onMouseDown={e => this.handleMouseDown(e)} >
|
<div styleName='slider' style={{left: this.state.codeEditorWidthInPercent + '%'}} onMouseDown={e => this.handleMouseDown(e)} >
|
||||||
<div styleName='slider-hitbox' />
|
<div styleName='slider-hitbox' />
|
||||||
</div>
|
</div>
|
||||||
<MarkdownPreview
|
<MarkdownPreview
|
||||||
style={previewStyle}
|
style={previewStyle}
|
||||||
styleName='preview'
|
|
||||||
theme={config.ui.theme}
|
theme={config.ui.theme}
|
||||||
keyMap={config.editor.keyMap}
|
keyMap={config.editor.keyMap}
|
||||||
fontSize={config.preview.fontSize}
|
fontSize={config.preview.fontSize}
|
||||||
@@ -198,6 +201,7 @@ class MarkdownSplitEditor extends React.Component {
|
|||||||
smartArrows={config.preview.smartArrows}
|
smartArrows={config.preview.smartArrows}
|
||||||
breaks={config.preview.breaks}
|
breaks={config.preview.breaks}
|
||||||
sanitize={config.preview.sanitize}
|
sanitize={config.preview.sanitize}
|
||||||
|
mermaidHTMLLabel={config.preview.mermaidHTMLLabel}
|
||||||
ref='preview'
|
ref='preview'
|
||||||
tabInde='0'
|
tabInde='0'
|
||||||
value={value}
|
value={value}
|
||||||
|
|||||||
@@ -8,9 +8,30 @@
|
|||||||
top -2px
|
top -2px
|
||||||
width 0
|
width 0
|
||||||
z-index 0
|
z-index 0
|
||||||
|
border-left 1px solid $ui-borderColor
|
||||||
.slider-hitbox
|
.slider-hitbox
|
||||||
absolute top bottom left right
|
absolute top bottom left right
|
||||||
width 7px
|
width 7px
|
||||||
left -3px
|
left -3px
|
||||||
z-index 10
|
z-index 10
|
||||||
cursor col-resize
|
cursor col-resize
|
||||||
|
|
||||||
|
body[data-theme="dark"]
|
||||||
|
.root
|
||||||
|
.slider
|
||||||
|
border-left 1px solid $ui-dark-borderColor
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root
|
||||||
|
.slider
|
||||||
|
border-left 1px solid $ui-solarized-dark-borderColor
|
||||||
|
|
||||||
|
body[data-theme="monokai"]
|
||||||
|
.root
|
||||||
|
.slider
|
||||||
|
border-left 1px solid $ui-monokai-borderColor
|
||||||
|
|
||||||
|
body[data-theme="dracula"]
|
||||||
|
.root
|
||||||
|
.slider
|
||||||
|
border-left 1px solid $ui-dracula-borderColor
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const ModalEscButton = ({
|
|||||||
}) => (
|
}) => (
|
||||||
<button styleName='escButton' onClick={handleEscButtonClick}>
|
<button styleName='escButton' onClick={handleEscButtonClick}>
|
||||||
<div styleName='esc-mark'>×</div>
|
<div styleName='esc-mark'>×</div>
|
||||||
<div styleName='esc-text'>esc</div>
|
<div>esc</div>
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
*/
|
*/
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { isArray } from 'lodash'
|
import { isArray, sortBy } from 'lodash'
|
||||||
import invertColor from 'invert-color'
|
import invertColor from 'invert-color'
|
||||||
|
import Emoji from 'react-emoji-render'
|
||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
import { getTodoStatus } from 'browser/lib/getTodoStatus'
|
import { getTodoStatus } from 'browser/lib/getTodoStatus'
|
||||||
import styles from './NoteItem.styl'
|
import styles from './NoteItem.styl'
|
||||||
@@ -43,7 +44,7 @@ const TagElementList = (tags, showTagsAlphabetically, coloredTags) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (showTagsAlphabetically) {
|
if (showTagsAlphabetically) {
|
||||||
return _.sortBy(tags).map(tag => TagElement({ tagName: tag, color: coloredTags[tag] }))
|
return sortBy(tags).map(tag => TagElement({ tagName: tag, color: coloredTags[tag] }))
|
||||||
} else {
|
} else {
|
||||||
return tags.map(tag => TagElement({ tagName: tag, color: coloredTags[tag] }))
|
return tags.map(tag => TagElement({ tagName: tag, color: coloredTags[tag] }))
|
||||||
}
|
}
|
||||||
@@ -87,7 +88,7 @@ const NoteItem = ({
|
|||||||
: <i styleName='item-title-icon' className='fa fa-fw fa-file-text-o' />}
|
: <i styleName='item-title-icon' className='fa fa-fw fa-file-text-o' />}
|
||||||
<div styleName='item-title'>
|
<div styleName='item-title'>
|
||||||
{note.title.trim().length > 0
|
{note.title.trim().length > 0
|
||||||
? note.title
|
? <Emoji text={note.title} />
|
||||||
: <span styleName='item-title-empty'>{i18n.__('Empty note')}</span>}
|
: <span styleName='item-title-empty'>{i18n.__('Empty note')}</span>}
|
||||||
</div>
|
</div>
|
||||||
<div styleName='item-middle'>
|
<div styleName='item-middle'>
|
||||||
@@ -148,15 +149,14 @@ NoteItem.propTypes = {
|
|||||||
tags: PropTypes.array,
|
tags: PropTypes.array,
|
||||||
isStarred: PropTypes.bool.isRequired,
|
isStarred: PropTypes.bool.isRequired,
|
||||||
isTrashed: PropTypes.bool.isRequired,
|
isTrashed: PropTypes.bool.isRequired,
|
||||||
blog: {
|
blog: PropTypes.shape({
|
||||||
blogLink: PropTypes.string,
|
blogLink: PropTypes.string,
|
||||||
blogId: PropTypes.number
|
blogId: PropTypes.number
|
||||||
}
|
})
|
||||||
}),
|
}),
|
||||||
handleNoteClick: PropTypes.func.isRequired,
|
handleNoteClick: PropTypes.func.isRequired,
|
||||||
handleNoteContextMenu: PropTypes.func.isRequired,
|
handleNoteContextMenu: PropTypes.func.isRequired,
|
||||||
handleDragStart: PropTypes.func.isRequired,
|
handleDragStart: PropTypes.func.isRequired
|
||||||
handleDragEnd: PropTypes.func.isRequired
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CSSModules(NoteItem, styles)
|
export default CSSModules(NoteItem, styles)
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ SideNavFilter.propTypes = {
|
|||||||
isStarredActive: PropTypes.bool.isRequired,
|
isStarredActive: PropTypes.bool.isRequired,
|
||||||
isTrashedActive: PropTypes.bool.isRequired,
|
isTrashedActive: PropTypes.bool.isRequired,
|
||||||
handleStarredButtonClick: PropTypes.func.isRequired,
|
handleStarredButtonClick: PropTypes.func.isRequired,
|
||||||
handleTrashdButtonClick: PropTypes.func.isRequired
|
handleTrashedButtonClick: PropTypes.func.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CSSModules(SideNavFilter, styles)
|
export default CSSModules(SideNavFilter, styles)
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ class SnippetTab extends React.Component {
|
|||||||
>
|
>
|
||||||
{snippet.name.trim().length > 0
|
{snippet.name.trim().length > 0
|
||||||
? snippet.name
|
? snippet.name
|
||||||
: <span styleName='button-unnamed'>
|
: <span>
|
||||||
{i18n.__('Unnamed')}
|
{i18n.__('Unnamed')}
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ const TodoProcess = ({
|
|||||||
)
|
)
|
||||||
|
|
||||||
TodoProcess.propTypes = {
|
TodoProcess.propTypes = {
|
||||||
todoStatus: {
|
todoStatus: PropTypes.exact({
|
||||||
total: PropTypes.number.isRequired,
|
total: PropTypes.number.isRequired,
|
||||||
completed: PropTypes.number.isRequired
|
completed: PropTypes.number.isRequired
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CSSModules(TodoProcess, styles)
|
export default CSSModules(TodoProcess, styles)
|
||||||
|
|||||||
@@ -363,7 +363,10 @@ admonition_types = {
|
|||||||
danger: {color: #c2185b, icon: "block"},
|
danger: {color: #c2185b, icon: "block"},
|
||||||
caution: {color: #ffa726, icon: "warning"},
|
caution: {color: #ffa726, icon: "warning"},
|
||||||
error: {color: #d32f2f, icon: "error_outline"},
|
error: {color: #d32f2f, icon: "error_outline"},
|
||||||
attention: {color: #455a64, icon: "priority_high"}
|
question: {color: #64dd17, icon: "help_outline"},
|
||||||
|
quote: {color: #9e9e9e, icon: "format_quote"},
|
||||||
|
abstract: {color: #00b0ff, icon: "subject"},
|
||||||
|
attention: {color: #455a64, icon: "priority_high"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, val in admonition_types
|
for name, val in admonition_types
|
||||||
@@ -424,6 +427,9 @@ pre.fence
|
|||||||
canvas, svg
|
canvas, svg
|
||||||
max-width 100% !important
|
max-width 100% !important
|
||||||
|
|
||||||
|
svg[ratio]
|
||||||
|
width 100%
|
||||||
|
|
||||||
.gallery
|
.gallery
|
||||||
width 100%
|
width 100%
|
||||||
height 50vh
|
height 50vh
|
||||||
@@ -444,6 +450,44 @@ pre.fence
|
|||||||
color $ui-text-color
|
color $ui-text-color
|
||||||
background-color $ui-tag-backgroundColor
|
background-color $ui-tag-backgroundColor
|
||||||
|
|
||||||
|
.markdownIt-TOC-wrapper
|
||||||
|
list-style none
|
||||||
|
position fixed
|
||||||
|
right 0
|
||||||
|
top 0
|
||||||
|
margin-left 15px
|
||||||
|
z-index 1000
|
||||||
|
transition transform .2s ease-in-out
|
||||||
|
transform translateX(100%)
|
||||||
|
|
||||||
|
.markdownIt-TOC
|
||||||
|
display block
|
||||||
|
max-height 90vh
|
||||||
|
overflow-y auto
|
||||||
|
padding 25px
|
||||||
|
padding-left 38px
|
||||||
|
|
||||||
|
&,
|
||||||
|
&:before
|
||||||
|
background-color $ui-dark-backgroundColor
|
||||||
|
color: $ui-dark-text-color
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
transform translateX(-15px)
|
||||||
|
|
||||||
|
&:before
|
||||||
|
content 'TOC'
|
||||||
|
position absolute
|
||||||
|
width 60px
|
||||||
|
height 30px
|
||||||
|
top 60px
|
||||||
|
left -29px
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
justify-content center
|
||||||
|
transform-origin top left
|
||||||
|
transform rotate(-90deg)
|
||||||
|
|
||||||
themeDarkBackground = darken(#21252B, 10%)
|
themeDarkBackground = darken(#21252B, 10%)
|
||||||
themeDarkText = #f9f9f9
|
themeDarkText = #f9f9f9
|
||||||
themeDarkBorder = lighten(themeDarkBackground, 20%)
|
themeDarkBorder = lighten(themeDarkBackground, 20%)
|
||||||
@@ -511,6 +555,14 @@ body[data-theme="dark"]
|
|||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
background-color $ui-dark-tag-backgroundColor
|
background-color $ui-dark-tag-backgroundColor
|
||||||
|
|
||||||
|
.markdownIt-TOC-wrapper
|
||||||
|
&,
|
||||||
|
&:before
|
||||||
|
background-color darken(themeDarkBackground, 5%)
|
||||||
|
color themeDarkText
|
||||||
|
|
||||||
|
|
||||||
|
themeSolarizedDarkBackground = $ui-solarized-dark-noteDetail-backgroundColor
|
||||||
themeSolarizedDarkTableOdd = $ui-solarized-dark-noteDetail-backgroundColor
|
themeSolarizedDarkTableOdd = $ui-solarized-dark-noteDetail-backgroundColor
|
||||||
themeSolarizedDarkTableEven = darken($ui-solarized-dark-noteDetail-backgroundColor, 10%)
|
themeSolarizedDarkTableEven = darken($ui-solarized-dark-noteDetail-backgroundColor, 10%)
|
||||||
themeSolarizedDarkTableHead = themeSolarizedDarkTableEven
|
themeSolarizedDarkTableHead = themeSolarizedDarkTableEven
|
||||||
@@ -519,7 +571,7 @@ themeSolarizedDarkTableBorder = themeDarkBorder
|
|||||||
body[data-theme="solarized-dark"]
|
body[data-theme="solarized-dark"]
|
||||||
color $ui-solarized-dark-text-color
|
color $ui-solarized-dark-text-color
|
||||||
border-color themeDarkBorder
|
border-color themeDarkBorder
|
||||||
background-color $ui-solarized-dark-noteDetail-backgroundColor
|
background-color themeSolarizedDarkBackground
|
||||||
table
|
table
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
@@ -554,6 +606,13 @@ body[data-theme="solarized-dark"]
|
|||||||
color $ui-solarized-dark-button--active-color
|
color $ui-solarized-dark-button--active-color
|
||||||
background-color $ui-solarized-dark-button-backgroundColor
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
|
||||||
|
.markdownIt-TOC-wrapper
|
||||||
|
&,
|
||||||
|
&:before
|
||||||
|
background-color darken(themeSolarizedDarkBackground, 15%)
|
||||||
|
color themeDarkText
|
||||||
|
|
||||||
|
themeMonokaiBackground = $ui-monokai-noteDetail-backgroundColor
|
||||||
themeMonokaiTableOdd = $ui-monokai-noteDetail-backgroundColor
|
themeMonokaiTableOdd = $ui-monokai-noteDetail-backgroundColor
|
||||||
themeMonokaiTableEven = darken($ui-monokai-noteDetail-backgroundColor, 10%)
|
themeMonokaiTableEven = darken($ui-monokai-noteDetail-backgroundColor, 10%)
|
||||||
themeMonokaiTableHead = themeMonokaiTableEven
|
themeMonokaiTableHead = themeMonokaiTableEven
|
||||||
@@ -562,7 +621,7 @@ themeMonokaiTableBorder = themeDarkBorder
|
|||||||
body[data-theme="monokai"]
|
body[data-theme="monokai"]
|
||||||
color $ui-monokai-text-color
|
color $ui-monokai-text-color
|
||||||
border-color themeDarkBorder
|
border-color themeDarkBorder
|
||||||
background-color $ui-monokai-noteDetail-backgroundColor
|
background-color themeMonokaiBackground
|
||||||
table
|
table
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
@@ -600,6 +659,13 @@ body[data-theme="monokai"]
|
|||||||
color $ui-monokai-button--active-color
|
color $ui-monokai-button--active-color
|
||||||
background-color $ui-monokai-button-backgroundColor
|
background-color $ui-monokai-button-backgroundColor
|
||||||
|
|
||||||
|
.markdownIt-TOC-wrapper
|
||||||
|
&,
|
||||||
|
&:before
|
||||||
|
background-color darken(themeMonokaiBackground, 15%)
|
||||||
|
color themeDarkText
|
||||||
|
|
||||||
|
themeDraculaBackground = $ui-dracula-noteDetail-backgroundColor
|
||||||
themeDraculaTableOdd = $ui-dracula-noteDetail-backgroundColor
|
themeDraculaTableOdd = $ui-dracula-noteDetail-backgroundColor
|
||||||
themeDraculaTableEven = darken($ui-dracula-noteDetail-backgroundColor, 10%)
|
themeDraculaTableEven = darken($ui-dracula-noteDetail-backgroundColor, 10%)
|
||||||
themeDraculaTableHead = themeDraculaTableEven
|
themeDraculaTableHead = themeDraculaTableEven
|
||||||
@@ -608,7 +674,7 @@ themeDraculaTableBorder = themeDarkBorder
|
|||||||
body[data-theme="dracula"]
|
body[data-theme="dracula"]
|
||||||
color $ui-dracula-text-color
|
color $ui-dracula-text-color
|
||||||
border-color themeDarkBorder
|
border-color themeDarkBorder
|
||||||
background-color $ui-dracula-noteDetail-backgroundColor
|
background-color themeDraculaBackground
|
||||||
table
|
table
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
@@ -645,3 +711,9 @@ body[data-theme="dracula"]
|
|||||||
.prev, .next
|
.prev, .next
|
||||||
color $ui-dracula-button--active-color
|
color $ui-dracula-button--active-color
|
||||||
background-color $ui-dracula-button-backgroundColor
|
background-color $ui-dracula-button-backgroundColor
|
||||||
|
|
||||||
|
.markdownIt-TOC-wrapper
|
||||||
|
&,
|
||||||
|
&:before
|
||||||
|
background-color darken(themeDraculaBackground, 15%)
|
||||||
|
color themeDarkText
|
||||||
|
|||||||
@@ -19,20 +19,43 @@ function getId () {
|
|||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
function render (element, content, theme) {
|
function render (element, content, theme, enableHTMLLabel) {
|
||||||
try {
|
try {
|
||||||
const height = element.attributes.getNamedItem('data-height')
|
const height = element.attributes.getNamedItem('data-height')
|
||||||
if (height && height.value !== 'undefined') {
|
const isPredefined = height && height.value !== 'undefined'
|
||||||
|
if (isPredefined) {
|
||||||
element.style.height = height.value + 'vh'
|
element.style.height = height.value + 'vh'
|
||||||
}
|
}
|
||||||
const isDarkTheme = theme === 'dark' || theme === 'solarized-dark' || theme === 'monokai' || theme === 'dracula'
|
const isDarkTheme = theme === 'dark' || theme === 'solarized-dark' || theme === 'monokai' || theme === 'dracula'
|
||||||
mermaidAPI.initialize({
|
mermaidAPI.initialize({
|
||||||
theme: isDarkTheme ? 'dark' : 'default',
|
theme: isDarkTheme ? 'dark' : 'default',
|
||||||
themeCSS: isDarkTheme ? darkThemeStyling : '',
|
themeCSS: isDarkTheme ? darkThemeStyling : '',
|
||||||
useMaxWidth: false
|
flowchart: {
|
||||||
|
htmlLabels: enableHTMLLabel
|
||||||
|
},
|
||||||
|
gantt: {
|
||||||
|
useWidth: element.clientWidth
|
||||||
|
}
|
||||||
})
|
})
|
||||||
mermaidAPI.render(getId(), content, (svgGraph) => {
|
mermaidAPI.render(getId(), content, (svgGraph) => {
|
||||||
element.innerHTML = svgGraph
|
element.innerHTML = svgGraph
|
||||||
|
|
||||||
|
if (!isPredefined) {
|
||||||
|
const el = element.firstChild
|
||||||
|
const viewBox = el.getAttribute('viewBox').split(' ')
|
||||||
|
|
||||||
|
let ratio = viewBox[2] / viewBox[3]
|
||||||
|
|
||||||
|
if (el.style.maxWidth) {
|
||||||
|
const maxWidth = parseFloat(el.style.maxWidth)
|
||||||
|
|
||||||
|
ratio *= el.parentNode.clientWidth / maxWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
el.setAttribute('ratio', ratio)
|
||||||
|
el.setAttribute('height', el.parentNode.clientWidth / ratio)
|
||||||
|
console.log(el)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
element.className = 'mermaid-error'
|
element.className = 'mermaid-error'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import CSSModules from 'react-css-modules'
|
import CSSModules from 'react-css-modules'
|
||||||
|
|
||||||
export default function (component, styles) {
|
export default function (component, styles) {
|
||||||
return CSSModules(component, styles, {errorWhenNotFound: false})
|
return CSSModules(component, styles, {handleNotFoundStyleName: 'log'})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ const languages = [
|
|||||||
name: 'Chinese (zh-TW)',
|
name: 'Chinese (zh-TW)',
|
||||||
locale: 'zh-TW'
|
locale: 'zh-TW'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Czech',
|
||||||
|
locale: 'cs'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Danish',
|
name: 'Danish',
|
||||||
locale: 'da'
|
locale: 'da'
|
||||||
@@ -62,10 +66,12 @@ const languages = [
|
|||||||
{
|
{
|
||||||
name: 'Spanish',
|
name: 'Spanish',
|
||||||
locale: 'es-ES'
|
locale: 'es-ES'
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'Turkish',
|
name: 'Turkish',
|
||||||
locale: 'tr'
|
locale: 'tr'
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'Thai',
|
name: 'Thai',
|
||||||
locale: 'th'
|
locale: 'th'
|
||||||
}
|
}
|
||||||
@@ -82,4 +88,3 @@ module.exports = {
|
|||||||
return languages
|
return languages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const { dialog } = remote
|
|||||||
export function confirmDeleteNote (confirmDeletion, permanent) {
|
export function confirmDeleteNote (confirmDeletion, permanent) {
|
||||||
if (confirmDeletion || permanent) {
|
if (confirmDeletion || permanent) {
|
||||||
const alertConfig = {
|
const alertConfig = {
|
||||||
ype: 'warning',
|
type: 'warning',
|
||||||
message: i18n.__('Confirm note deletion'),
|
message: i18n.__('Confirm note deletion'),
|
||||||
detail: i18n.__('This will permanently remove this note.'),
|
detail: i18n.__('This will permanently remove this note.'),
|
||||||
buttons: [i18n.__('Confirm'), i18n.__('Cancel')]
|
buttons: [i18n.__('Confirm'), i18n.__('Cancel')]
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ const CODEMIRROR_THEME_PATH = 'node_modules/codemirror/theme'
|
|||||||
const CODEMIRROR_EXTRA_THEME_PATH = 'extra_scripts/codemirror/theme'
|
const CODEMIRROR_EXTRA_THEME_PATH = 'extra_scripts/codemirror/theme'
|
||||||
|
|
||||||
const isProduction = process.env.NODE_ENV === 'production'
|
const isProduction = process.env.NODE_ENV === 'production'
|
||||||
|
|
||||||
const paths = [
|
const paths = [
|
||||||
isProduction ? path.join(app.getAppPath(), CODEMIRROR_THEME_PATH) : path.resolve(CODEMIRROR_THEME_PATH),
|
isProduction ? path.join(app.getAppPath(), CODEMIRROR_THEME_PATH) : path.resolve(CODEMIRROR_THEME_PATH),
|
||||||
isProduction ? path.join(app.getAppPath(), CODEMIRROR_EXTRA_THEME_PATH) : path.resolve(CODEMIRROR_EXTRA_THEME_PATH)
|
isProduction ? path.join(app.getAppPath(), CODEMIRROR_EXTRA_THEME_PATH) : path.resolve(CODEMIRROR_EXTRA_THEME_PATH)
|
||||||
@@ -18,7 +19,7 @@ const themes = paths
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
path: path.join(directory.split(/\//g).slice(-3).join('/'), file),
|
path: path.join(directory, file),
|
||||||
className: `cm-s-${name}`
|
className: `cm-s-${name}`
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
@@ -27,17 +28,16 @@ const themes = paths
|
|||||||
|
|
||||||
themes.splice(themes.findIndex(({ name }) => name === 'solarized'), 1, {
|
themes.splice(themes.findIndex(({ name }) => name === 'solarized'), 1, {
|
||||||
name: 'solarized dark',
|
name: 'solarized dark',
|
||||||
path: `${CODEMIRROR_THEME_PATH}/solarized.css`,
|
path: path.join(paths[0], 'solarized.css'),
|
||||||
className: `cm-s-solarized cm-s-dark`
|
className: `cm-s-solarized cm-s-dark`
|
||||||
}, {
|
}, {
|
||||||
name: 'solarized light',
|
name: 'solarized light',
|
||||||
path: `${CODEMIRROR_THEME_PATH}/solarized.css`,
|
path: path.join(paths[0], 'solarized.css'),
|
||||||
className: `cm-s-solarized cm-s-light`
|
className: `cm-s-solarized cm-s-light`
|
||||||
})
|
})
|
||||||
|
|
||||||
themes.splice(0, 0, {
|
themes.splice(0, 0, {
|
||||||
name: 'default',
|
name: 'default',
|
||||||
path: `${CODEMIRROR_THEME_PATH}/elegant.css`,
|
path: path.join(paths[0], 'elegant.css'),
|
||||||
className: `cm-s-default`
|
className: `cm-s-default`
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
|
import i18n from 'browser/lib/i18n'
|
||||||
|
import fs from 'fs'
|
||||||
|
|
||||||
const {remote} = require('electron')
|
const {remote} = require('electron')
|
||||||
const {Menu} = remote.require('electron')
|
const {Menu} = remote.require('electron')
|
||||||
|
const {clipboard} = remote.require('electron')
|
||||||
|
const {shell} = remote.require('electron')
|
||||||
const spellcheck = require('./spellcheck')
|
const spellcheck = require('./spellcheck')
|
||||||
|
const uri2path = require('file-uri-to-path')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the context menu that is shown when there is a right click in the editor of a (not-snippet) note.
|
* Creates the context menu that is shown when there is a right click in the editor of a (not-snippet) note.
|
||||||
@@ -62,4 +68,57 @@ const buildEditorContextMenu = function (editor, event) {
|
|||||||
return Menu.buildFromTemplate(template)
|
return Menu.buildFromTemplate(template)
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = buildEditorContextMenu
|
/**
|
||||||
|
* Creates the context menu that is shown when there is a right click Markdown preview of a (not-snippet) note.
|
||||||
|
* @param {MarkdownPreview} markdownPreview
|
||||||
|
* @param {MouseEvent} event that has triggered the creation of the context menu
|
||||||
|
* @returns {Electron.Menu} The created electron context menu
|
||||||
|
*/
|
||||||
|
const buildMarkdownPreviewContextMenu = function (markdownPreview, event) {
|
||||||
|
if (markdownPreview == null || event == null || event.pageX == null || event.pageY == null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default context menu inclusions
|
||||||
|
const template = [{
|
||||||
|
role: 'copy'
|
||||||
|
}, {
|
||||||
|
role: 'selectall'
|
||||||
|
}]
|
||||||
|
|
||||||
|
if (event.target.tagName.toLowerCase() === 'a' && event.target.getAttribute('href')) {
|
||||||
|
// Link opener for files on the local system pointed to by href
|
||||||
|
const href = event.target.href
|
||||||
|
const isLocalFile = href.startsWith('file:')
|
||||||
|
if (isLocalFile) {
|
||||||
|
const absPath = uri2path(href)
|
||||||
|
try {
|
||||||
|
if (fs.lstatSync(absPath).isFile()) {
|
||||||
|
template.push(
|
||||||
|
{
|
||||||
|
label: i18n.__('Show in explorer'),
|
||||||
|
click: (e) => shell.showItemInFolder(absPath)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Error while evaluating if the file is locally available', e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add option to context menu to copy url
|
||||||
|
template.push(
|
||||||
|
{
|
||||||
|
label: i18n.__('Copy Url'),
|
||||||
|
click: (e) => clipboard.writeText(href)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return Menu.buildFromTemplate(template)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports =
|
||||||
|
{
|
||||||
|
buildEditorContextMenu: buildEditorContextMenu,
|
||||||
|
buildMarkdownPreviewContextMenu: buildMarkdownPreviewContextMenu
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
import CodeMirror from 'codemirror'
|
import CodeMirror from 'codemirror'
|
||||||
import 'codemirror-mode-elixir'
|
import 'codemirror-mode-elixir'
|
||||||
|
|
||||||
CodeMirror.modeInfo.push({name: 'Stylus', mime: 'text/x-styl', mode: 'stylus', ext: ['styl'], alias: ['styl']})
|
const stylusCodeInfo = CodeMirror.modeInfo.find(info => info.name === 'Stylus')
|
||||||
|
if (stylusCodeInfo == null) {
|
||||||
|
CodeMirror.modeInfo.push({name: 'Stylus', mime: 'text/x-styl', mode: 'stylus', ext: ['styl'], alias: ['styl']})
|
||||||
|
} else {
|
||||||
|
stylusCodeInfo.alias = ['styl']
|
||||||
|
}
|
||||||
CodeMirror.modeInfo.push({name: 'Elixir', mime: 'text/x-elixir', mode: 'elixir', ext: ['ex']})
|
CodeMirror.modeInfo.push({name: 'Elixir', mime: 'text/x-elixir', mode: 'elixir', ext: ['ex']})
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ export function getTodoStatus (content) {
|
|||||||
let numberOfCompletedTodo = 0
|
let numberOfCompletedTodo = 0
|
||||||
|
|
||||||
splitted.forEach((line) => {
|
splitted.forEach((line) => {
|
||||||
const trimmedLine = line.trim()
|
const trimmedLine = line.trim().replace(/^(>\s*)*/, '')
|
||||||
if (trimmedLine.match(/^[\+\-\*] \[(\s|x)\] ./i)) {
|
if (trimmedLine.match(/^[+\-*] \[(\s|x)] ./i)) {
|
||||||
numberOfTodo++
|
numberOfTodo++
|
||||||
}
|
}
|
||||||
if (trimmedLine.match(/^[\+\-\*] \[x\] ./i)) {
|
if (trimmedLine.match(/^[+\-*] \[x] ./i)) {
|
||||||
numberOfCompletedTodo++
|
numberOfCompletedTodo++
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
const crypto = require('crypto')
|
const crypto = require('crypto')
|
||||||
const _ = require('lodash')
|
|
||||||
const uuidv4 = require('uuid/v4')
|
const uuidv4 = require('uuid/v4')
|
||||||
|
|
||||||
module.exports = function (uuid) {
|
module.exports = function (uuid) {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ module.exports = function sanitizePlugin (md, options) {
|
|||||||
options
|
options
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (state.tokens[tokenIdx].type === '_fence') {
|
if (state.tokens[tokenIdx].type.match(/.*_fence$/)) {
|
||||||
// escapeHtmlCharacters has better performance
|
// escapeHtmlCharacters has better performance
|
||||||
state.tokens[tokenIdx].content = escapeHtmlCharacters(
|
state.tokens[tokenIdx].content = escapeHtmlCharacters(
|
||||||
state.tokens[tokenIdx].content,
|
state.tokens[tokenIdx].content,
|
||||||
@@ -96,6 +96,10 @@ function sanitizeInline (html, options) {
|
|||||||
|
|
||||||
function naughtyHRef (href, options) {
|
function naughtyHRef (href, options) {
|
||||||
// href = href.replace(/[\x00-\x20]+/g, '')
|
// href = href.replace(/[\x00-\x20]+/g, '')
|
||||||
|
if (!href) {
|
||||||
|
// No href
|
||||||
|
return false
|
||||||
|
}
|
||||||
href = href.replace(/<\!\-\-.*?\-\-\>/g, '')
|
href = href.replace(/<\!\-\-.*?\-\-\>/g, '')
|
||||||
|
|
||||||
const matches = href.match(/^([a-zA-Z]+)\:/)
|
const matches = href.match(/^([a-zA-Z]+)\:/)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ function uniqueSlug (slug, slugs, opts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function linkify (token) {
|
function linkify (token) {
|
||||||
token.content = mdlink(token.content, '#' + token.slug)
|
token.content = mdlink(token.content, `#${decodeURI(token.slug)}`)
|
||||||
return token
|
return token
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ import markdownit from 'markdown-it'
|
|||||||
import sanitize from './markdown-it-sanitize-html'
|
import sanitize from './markdown-it-sanitize-html'
|
||||||
import emoji from 'markdown-it-emoji'
|
import emoji from 'markdown-it-emoji'
|
||||||
import math from '@rokt33r/markdown-it-math'
|
import math from '@rokt33r/markdown-it-math'
|
||||||
|
import mdurl from 'mdurl'
|
||||||
import smartArrows from 'markdown-it-smartarrows'
|
import smartArrows from 'markdown-it-smartarrows'
|
||||||
|
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'
|
||||||
@@ -32,6 +34,7 @@ class Markdown {
|
|||||||
|
|
||||||
const updatedOptions = Object.assign(defaultOptions, options)
|
const updatedOptions = Object.assign(defaultOptions, options)
|
||||||
this.md = markdownit(updatedOptions)
|
this.md = markdownit(updatedOptions)
|
||||||
|
this.md.linkify.set({ fuzzyLink: false })
|
||||||
|
|
||||||
if (updatedOptions.sanitize !== 'NONE') {
|
if (updatedOptions.sanitize !== 'NONE') {
|
||||||
const allowedTags = ['iframe', 'input', 'b',
|
const allowedTags = ['iframe', 'input', 'b',
|
||||||
@@ -121,10 +124,23 @@ class Markdown {
|
|||||||
slugify: require('./slugify')
|
slugify: require('./slugify')
|
||||||
})
|
})
|
||||||
this.md.use(require('markdown-it-kbd'))
|
this.md.use(require('markdown-it-kbd'))
|
||||||
this.md.use(require('markdown-it-admonition'), {types: ['note', 'hint', 'attention', 'caution', 'danger', 'error']})
|
this.md.use(require('markdown-it-admonition'), {types: ['note', 'hint', 'attention', 'caution', 'danger', 'error', 'quote', 'abstract', 'question']})
|
||||||
this.md.use(require('markdown-it-abbr'))
|
this.md.use(require('markdown-it-abbr'))
|
||||||
this.md.use(require('markdown-it-sub'))
|
this.md.use(require('markdown-it-sub'))
|
||||||
this.md.use(require('markdown-it-sup'))
|
this.md.use(require('markdown-it-sup'))
|
||||||
|
|
||||||
|
this.md.use(md => {
|
||||||
|
markdownItTocAndAnchor(md, {
|
||||||
|
toc: true,
|
||||||
|
tocPattern: /\[TOC\]/i,
|
||||||
|
anchorLink: false,
|
||||||
|
appendIdToHeading: false
|
||||||
|
})
|
||||||
|
|
||||||
|
md.renderer.rules.toc_open = () => '<div class="markdownIt-TOC-wrapper">'
|
||||||
|
md.renderer.rules.toc_close = () => '</div>'
|
||||||
|
})
|
||||||
|
|
||||||
this.md.use(require('./markdown-it-deflist'))
|
this.md.use(require('./markdown-it-deflist'))
|
||||||
this.md.use(require('./markdown-it-frontmatter'))
|
this.md.use(require('./markdown-it-frontmatter'))
|
||||||
|
|
||||||
@@ -149,9 +165,9 @@ class Markdown {
|
|||||||
const content = token.content.split('\n').slice(0, -1).map(line => {
|
const content = token.content.split('\n').slice(0, -1).map(line => {
|
||||||
const match = /!\[[^\]]*]\(([^\)]*)\)/.exec(line)
|
const match = /!\[[^\]]*]\(([^\)]*)\)/.exec(line)
|
||||||
if (match) {
|
if (match) {
|
||||||
return match[1]
|
return mdurl.encode(match[1])
|
||||||
} else {
|
} else {
|
||||||
return line
|
return mdurl.encode(line)
|
||||||
}
|
}
|
||||||
}).join('\n')
|
}).join('\n')
|
||||||
|
|
||||||
@@ -181,32 +197,47 @@ class Markdown {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const deflate = require('markdown-it-plantuml/lib/deflate')
|
const deflate = require('markdown-it-plantuml/lib/deflate')
|
||||||
this.md.use(require('markdown-it-plantuml'), {
|
const plantuml = require('markdown-it-plantuml')
|
||||||
generateSource: function (umlCode) {
|
const plantUmlStripTrailingSlash = (url) => url.endsWith('/') ? url.slice(0, -1) : url
|
||||||
const stripTrailingSlash = (url) => url.endsWith('/') ? url.slice(0, -1) : url
|
const plantUmlServerAddress = plantUmlStripTrailingSlash(config.preview.plantUMLServerAddress)
|
||||||
const serverAddress = stripTrailingSlash(config.preview.plantUMLServerAddress) + '/svg'
|
const parsePlantUml = function (umlCode, openMarker, closeMarker, type) {
|
||||||
const s = unescape(encodeURIComponent(umlCode))
|
const s = unescape(encodeURIComponent(umlCode))
|
||||||
const zippedCode = deflate.encode64(
|
const zippedCode = deflate.encode64(
|
||||||
deflate.zip_deflate(`@startuml\n${s}\n@enduml`, 9)
|
deflate.zip_deflate(`${openMarker}\n${s}\n${closeMarker}`, 9)
|
||||||
)
|
)
|
||||||
return `${serverAddress}/${zippedCode}`
|
return `${plantUmlServerAddress}/${type}/${zippedCode}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.md.use(plantuml, {
|
||||||
|
generateSource: (umlCode) => parsePlantUml(umlCode, '@startuml', '@enduml', 'svg')
|
||||||
})
|
})
|
||||||
|
|
||||||
// Ditaa support
|
// Ditaa support. PlantUML server doesn't support Ditaa in SVG, so we set the format as PNG at the moment.
|
||||||
this.md.use(require('markdown-it-plantuml'), {
|
this.md.use(plantuml, {
|
||||||
openMarker: '@startditaa',
|
openMarker: '@startditaa',
|
||||||
closeMarker: '@endditaa',
|
closeMarker: '@endditaa',
|
||||||
generateSource: function (umlCode) {
|
generateSource: (umlCode) => parsePlantUml(umlCode, '@startditaa', '@endditaa', 'png')
|
||||||
const stripTrailingSlash = (url) => url.endsWith('/') ? url.slice(0, -1) : url
|
})
|
||||||
// Currently PlantUML server doesn't support Ditaa in SVG, so we set the format as PNG at the moment.
|
|
||||||
const serverAddress = stripTrailingSlash(config.preview.plantUMLServerAddress) + '/png'
|
// Mindmap support
|
||||||
const s = unescape(encodeURIComponent(umlCode))
|
this.md.use(plantuml, {
|
||||||
const zippedCode = deflate.encode64(
|
openMarker: '@startmindmap',
|
||||||
deflate.zip_deflate(`@startditaa\n${s}\n@endditaa`, 9)
|
closeMarker: '@endmindmap',
|
||||||
)
|
generateSource: (umlCode) => parsePlantUml(umlCode, '@startmindmap', '@endmindmap', 'svg')
|
||||||
return `${serverAddress}/${zippedCode}`
|
})
|
||||||
}
|
|
||||||
|
// WBS support
|
||||||
|
this.md.use(plantuml, {
|
||||||
|
openMarker: '@startwbs',
|
||||||
|
closeMarker: '@endwbs',
|
||||||
|
generateSource: (umlCode) => parsePlantUml(umlCode, '@startwbs', '@endwbs', 'svg')
|
||||||
|
})
|
||||||
|
|
||||||
|
// Gantt support
|
||||||
|
this.md.use(plantuml, {
|
||||||
|
openMarker: '@startgantt',
|
||||||
|
closeMarker: '@endgantt',
|
||||||
|
generateSource: (umlCode) => parsePlantUml(umlCode, '@startgantt', '@endgantt', 'svg')
|
||||||
})
|
})
|
||||||
|
|
||||||
// Override task item
|
// Override task item
|
||||||
@@ -287,7 +318,9 @@ class Markdown {
|
|||||||
case 'list_item_open':
|
case 'list_item_open':
|
||||||
case 'paragraph_open':
|
case 'paragraph_open':
|
||||||
case 'table_open':
|
case 'table_open':
|
||||||
token.attrPush(['data-line', token.map[0]])
|
if (token.map) {
|
||||||
|
token.attrPush(['data-line', token.map[0]])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const result = originalRender.call(this.md.renderer, tokens, options, env)
|
const result = originalRender.call(this.md.renderer, tokens, options, env)
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { hashHistory } from 'react-router'
|
|
||||||
import dataApi from 'browser/main/lib/dataApi'
|
import dataApi from 'browser/main/lib/dataApi'
|
||||||
import ee from 'browser/main/lib/eventEmitter'
|
import ee from 'browser/main/lib/eventEmitter'
|
||||||
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
||||||
|
import queryString from 'query-string'
|
||||||
|
import { push } from 'connected-react-router'
|
||||||
|
|
||||||
export function createMarkdownNote (storage, folder, dispatch, location, params, config) {
|
export function createMarkdownNote (storage, folder, dispatch, location, params, config) {
|
||||||
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_MARKDOWN')
|
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_MARKDOWN')
|
||||||
@@ -28,10 +29,10 @@ export function createMarkdownNote (storage, folder, dispatch, location, params,
|
|||||||
note: note
|
note: note
|
||||||
})
|
})
|
||||||
|
|
||||||
hashHistory.push({
|
dispatch(push({
|
||||||
pathname: location.pathname,
|
pathname: location.pathname,
|
||||||
query: { key: noteHash }
|
search: queryString.stringify({ key: noteHash })
|
||||||
})
|
}))
|
||||||
ee.emit('list:jump', noteHash)
|
ee.emit('list:jump', noteHash)
|
||||||
ee.emit('detail:focus')
|
ee.emit('detail:focus')
|
||||||
})
|
})
|
||||||
@@ -70,10 +71,10 @@ export function createSnippetNote (storage, folder, dispatch, location, params,
|
|||||||
type: 'UPDATE_NOTE',
|
type: 'UPDATE_NOTE',
|
||||||
note: note
|
note: note
|
||||||
})
|
})
|
||||||
hashHistory.push({
|
dispatch(push({
|
||||||
pathname: location.pathname,
|
pathname: location.pathname,
|
||||||
query: { key: noteHash }
|
search: queryString.stringify({ key: noteHash })
|
||||||
})
|
}))
|
||||||
ee.emit('list:jump', noteHash)
|
ee.emit('list:jump', noteHash)
|
||||||
ee.emit('detail:focus')
|
ee.emit('detail:focus')
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,17 +1,11 @@
|
|||||||
import diacritics from 'diacritics-map'
|
|
||||||
|
|
||||||
function replaceDiacritics (str) {
|
|
||||||
return str.replace(/[À-ž]/g, function (ch) {
|
|
||||||
return diacritics[ch] || ch
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = function slugify (title) {
|
module.exports = function slugify (title) {
|
||||||
let slug = title.trim()
|
const slug = encodeURI(
|
||||||
|
title.trim()
|
||||||
|
.replace(/^\s+/, '')
|
||||||
|
.replace(/\s+$/, '')
|
||||||
|
.replace(/\s+/g, '-')
|
||||||
|
.replace(/[\]\[\!\'\#\$\%\&\(\)\*\+\,\.\/\:\;\<\=\>\?\@\\\^\{\|\}\~\`]/g, '')
|
||||||
|
)
|
||||||
|
|
||||||
slug = replaceDiacritics(slug)
|
return slug
|
||||||
|
|
||||||
slug = slug.replace(/[^\w\s-]/g, '').replace(/\s+/g, '-')
|
|
||||||
|
|
||||||
return encodeURI(slug).replace(/\-+$/, '')
|
|
||||||
}
|
}
|
||||||
|
|||||||
9
browser/lib/turndown.js
Normal file
9
browser/lib/turndown.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
const TurndownService = require('turndown')
|
||||||
|
const { gfm } = require('turndown-plugin-gfm')
|
||||||
|
|
||||||
|
export const createTurndownService = function () {
|
||||||
|
const turndown = new TurndownService()
|
||||||
|
turndown.use(gfm)
|
||||||
|
turndown.remove('script')
|
||||||
|
return turndown
|
||||||
|
}
|
||||||
@@ -136,9 +136,24 @@ export function isMarkdownTitleURL (str) {
|
|||||||
return /(^#{1,6}\s)(?:\w+:|^)\/\/(?:[^\s\.]+\.\S{2}|localhost[\:?\d]*)/.test(str)
|
return /(^#{1,6}\s)(?:\w+:|^)\/\/(?:[^\s\.]+\.\S{2}|localhost[\:?\d]*)/.test(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function humanFileSize (bytes) {
|
||||||
|
const threshold = 1000
|
||||||
|
if (Math.abs(bytes) < threshold) {
|
||||||
|
return bytes + ' B'
|
||||||
|
}
|
||||||
|
var units = ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||||
|
var u = -1
|
||||||
|
do {
|
||||||
|
bytes /= threshold
|
||||||
|
++u
|
||||||
|
} while (Math.abs(bytes) >= threshold && u < units.length - 1)
|
||||||
|
return bytes.toFixed(1) + ' ' + units[u]
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
lastFindInArray,
|
lastFindInArray,
|
||||||
escapeHtmlCharacters,
|
escapeHtmlCharacters,
|
||||||
isObjectEqual,
|
isObjectEqual,
|
||||||
isMarkdownTitleURL
|
isMarkdownTitleURL,
|
||||||
|
humanFileSize
|
||||||
}
|
}
|
||||||
|
|||||||
69
browser/main/Detail/FromUrlButton.js
Normal file
69
browser/main/Detail/FromUrlButton.js
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import React from 'react'
|
||||||
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
|
import styles from './FromUrlButton.styl'
|
||||||
|
import _ from 'lodash'
|
||||||
|
import i18n from 'browser/lib/i18n'
|
||||||
|
|
||||||
|
class FromUrlButton extends React.Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
isActive: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMouseDown (e) {
|
||||||
|
this.setState({
|
||||||
|
isActive: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMouseUp (e) {
|
||||||
|
this.setState({
|
||||||
|
isActive: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMouseLeave (e) {
|
||||||
|
this.setState({
|
||||||
|
isActive: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { className } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button className={_.isString(className)
|
||||||
|
? 'FromUrlButton ' + className
|
||||||
|
: 'FromUrlButton'
|
||||||
|
}
|
||||||
|
styleName={this.state.isActive || this.props.isActive
|
||||||
|
? 'root--active'
|
||||||
|
: 'root'
|
||||||
|
}
|
||||||
|
onMouseDown={(e) => this.handleMouseDown(e)}
|
||||||
|
onMouseUp={(e) => this.handleMouseUp(e)}
|
||||||
|
onMouseLeave={(e) => this.handleMouseLeave(e)}
|
||||||
|
onClick={this.props.onClick}>
|
||||||
|
<img styleName='icon'
|
||||||
|
src={this.state.isActive || this.props.isActive
|
||||||
|
? '../resources/icon/icon-external.svg'
|
||||||
|
: '../resources/icon/icon-external.svg'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span styleName='tooltip'>{i18n.__('Convert URL to Markdown')}</span>
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FromUrlButton.propTypes = {
|
||||||
|
isActive: PropTypes.bool,
|
||||||
|
onClick: PropTypes.func,
|
||||||
|
className: PropTypes.string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CSSModules(FromUrlButton, styles)
|
||||||
41
browser/main/Detail/FromUrlButton.styl
Normal file
41
browser/main/Detail/FromUrlButton.styl
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
.root
|
||||||
|
top 45px
|
||||||
|
topBarButtonRight()
|
||||||
|
&:hover
|
||||||
|
transition 0.2s
|
||||||
|
color alpha($ui-favorite-star-button-color, 0.6)
|
||||||
|
&:hover .tooltip
|
||||||
|
opacity 1
|
||||||
|
|
||||||
|
.tooltip
|
||||||
|
tooltip()
|
||||||
|
position absolute
|
||||||
|
pointer-events none
|
||||||
|
top 50px
|
||||||
|
right 125px
|
||||||
|
width 90px
|
||||||
|
z-index 200
|
||||||
|
padding 5px
|
||||||
|
line-height normal
|
||||||
|
border-radius 2px
|
||||||
|
opacity 0
|
||||||
|
transition 0.1s
|
||||||
|
|
||||||
|
.root--active
|
||||||
|
@extend .root
|
||||||
|
transition 0.15s
|
||||||
|
color $ui-favorite-star-button-color
|
||||||
|
&:hover
|
||||||
|
transition 0.2s
|
||||||
|
color alpha($ui-favorite-star-button-color, 0.6)
|
||||||
|
|
||||||
|
.icon
|
||||||
|
transition transform 0.15s
|
||||||
|
height 13px
|
||||||
|
|
||||||
|
body[data-theme="dark"]
|
||||||
|
.root
|
||||||
|
topBarButtonDark()
|
||||||
|
&:hover
|
||||||
|
transition 0.2s
|
||||||
|
color alpha($ui-favorite-star-button-color, 0.6)
|
||||||
@@ -11,7 +11,7 @@ const FullscreenButton = ({
|
|||||||
const hotkey = (OSX ? i18n.__('Command(⌘)') : i18n.__('Ctrl(^)')) + '+B'
|
const hotkey = (OSX ? i18n.__('Command(⌘)') : i18n.__('Ctrl(^)')) + '+B'
|
||||||
return (
|
return (
|
||||||
<button styleName='control-fullScreenButton' title={i18n.__('Fullscreen')} onMouseDown={(e) => onClick(e)}>
|
<button styleName='control-fullScreenButton' title={i18n.__('Fullscreen')} onMouseDown={(e) => onClick(e)}>
|
||||||
<img styleName='iconInfo' src='../resources/icon/icon-full.svg' />
|
<img src='../resources/icon/icon-full.svg' />
|
||||||
<span lang={i18n.locale} styleName='tooltip'>{i18n.__('Fullscreen')}({hotkey})</span>
|
<span lang={i18n.locale} styleName='tooltip'>{i18n.__('Fullscreen')}({hotkey})</span>
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class InfoPanel extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<input styleName='infoPanel-noteLink' ref='noteLink' value={noteLink} onClick={(e) => { e.target.select() }} />
|
<input styleName='infoPanel-noteLink' ref='noteLink' defaultValue={noteLink} onClick={(e) => { e.target.select() }} />
|
||||||
<button onClick={() => this.copyNoteLink()} styleName='infoPanel-copyButton'>
|
<button onClick={() => this.copyNoteLink()} styleName='infoPanel-copyButton'>
|
||||||
<i className='fa fa-clipboard' />
|
<i className='fa fa-clipboard' />
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import StarButton from './StarButton'
|
|||||||
import TagSelect from './TagSelect'
|
import TagSelect from './TagSelect'
|
||||||
import FolderSelect from './FolderSelect'
|
import FolderSelect from './FolderSelect'
|
||||||
import dataApi from 'browser/main/lib/dataApi'
|
import dataApi from 'browser/main/lib/dataApi'
|
||||||
import { hashHistory } from 'react-router'
|
|
||||||
import ee from 'browser/main/lib/eventEmitter'
|
import ee from 'browser/main/lib/eventEmitter'
|
||||||
import markdown from 'browser/lib/markdownTextHelper'
|
import markdown from 'browser/lib/markdownTextHelper'
|
||||||
import StatusBar from '../StatusBar'
|
import StatusBar from '../StatusBar'
|
||||||
@@ -30,6 +29,8 @@ import { getTodoPercentageOfCompleted } from 'browser/lib/getTodoStatus'
|
|||||||
import striptags from 'striptags'
|
import striptags from 'striptags'
|
||||||
import { confirmDeleteNote } from 'browser/lib/confirmDeleteNote'
|
import { confirmDeleteNote } from 'browser/lib/confirmDeleteNote'
|
||||||
import markdownToc from 'browser/lib/markdown-toc-generator'
|
import markdownToc from 'browser/lib/markdown-toc-generator'
|
||||||
|
import queryString from 'query-string'
|
||||||
|
import { replace } from 'connected-react-router'
|
||||||
|
|
||||||
class MarkdownNoteDetail extends React.Component {
|
class MarkdownNoteDetail extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
@@ -66,9 +67,6 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
})
|
})
|
||||||
ee.on('hotkey:deletenote', this.handleDeleteNote.bind(this))
|
ee.on('hotkey:deletenote', this.handleDeleteNote.bind(this))
|
||||||
ee.on('code:generate-toc', this.generateToc)
|
ee.on('code:generate-toc', this.generateToc)
|
||||||
|
|
||||||
// Focus content if using blur or double click
|
|
||||||
if (this.state.switchPreview === 'BLUR' || this.state.switchPreview === 'DBL_CLICK') this.focus()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps (nextProps) {
|
componentWillReceiveProps (nextProps) {
|
||||||
@@ -83,6 +81,20 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
if (this.refs.tags) this.refs.tags.reset()
|
if (this.refs.tags) this.refs.tags.reset()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Focus content if using blur or double click
|
||||||
|
// --> Moved here from componentDidMount so a re-render during search won't set focus to the editor
|
||||||
|
const {switchPreview} = nextProps.config.editor
|
||||||
|
|
||||||
|
if (this.state.switchPreview !== switchPreview) {
|
||||||
|
this.setState({
|
||||||
|
switchPreview
|
||||||
|
})
|
||||||
|
if (switchPreview === 'BLUR' || switchPreview === 'DBL_CLICK') {
|
||||||
|
console.log('setting focus', switchPreview)
|
||||||
|
this.focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount () {
|
componentWillUnmount () {
|
||||||
@@ -159,12 +171,12 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
originNote: note,
|
originNote: note,
|
||||||
note: newNote
|
note: newNote
|
||||||
})
|
})
|
||||||
hashHistory.replace({
|
dispatch(replace({
|
||||||
pathname: location.pathname,
|
pathname: location.pathname,
|
||||||
query: {
|
search: queryString.stringify({
|
||||||
key: newNote.key
|
key: newNote.key
|
||||||
}
|
})
|
||||||
})
|
}))
|
||||||
this.setState({
|
this.setState({
|
||||||
isMovingNote: false
|
isMovingNote: false
|
||||||
})
|
})
|
||||||
@@ -298,7 +310,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getToggleLockButton () {
|
getToggleLockButton () {
|
||||||
return this.state.isLocked ? '../resources/icon/icon-previewoff-on.svg' : '../resources/icon/icon-previewoff-off.svg'
|
return this.state.isLocked ? '../resources/icon/icon-lock.svg' : '../resources/icon/icon-unlock.svg'
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDeleteKeyDown (e) {
|
handleDeleteKeyDown (e) {
|
||||||
@@ -397,7 +409,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { data, location, config } = this.props
|
const { data, dispatch, location, config } = this.props
|
||||||
const { note, editorType } = this.state
|
const { note, editorType } = this.state
|
||||||
const storageKey = note.storage
|
const storageKey = note.storage
|
||||||
const folderKey = note.folder
|
const folderKey = note.folder
|
||||||
@@ -437,7 +449,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
|
|
||||||
const detailTopBar = <div styleName='info'>
|
const detailTopBar = <div styleName='info'>
|
||||||
<div styleName='info-left'>
|
<div styleName='info-left'>
|
||||||
<div styleName='info-left-top'>
|
<div>
|
||||||
<FolderSelect styleName='info-left-top-folderSelect'
|
<FolderSelect styleName='info-left-top-folderSelect'
|
||||||
value={this.state.note.storage + '-' + this.state.note.folder}
|
value={this.state.note.storage + '-' + this.state.note.folder}
|
||||||
ref='folder'
|
ref='folder'
|
||||||
@@ -452,6 +464,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
saveTagsAlphabetically={config.ui.saveTagsAlphabetically}
|
saveTagsAlphabetically={config.ui.saveTagsAlphabetically}
|
||||||
showTagsAlphabetically={config.ui.showTagsAlphabetically}
|
showTagsAlphabetically={config.ui.showTagsAlphabetically}
|
||||||
data={data}
|
data={data}
|
||||||
|
dispatch={dispatch}
|
||||||
onChange={this.handleUpdateTag.bind(this)}
|
onChange={this.handleUpdateTag.bind(this)}
|
||||||
coloredTags={config.coloredTags}
|
coloredTags={config.coloredTags}
|
||||||
/>
|
/>
|
||||||
@@ -459,6 +472,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
<div styleName='info-right'>
|
<div styleName='info-right'>
|
||||||
<ToggleModeButton onClick={(e) => this.handleSwitchMode(e)} editorType={editorType} />
|
<ToggleModeButton onClick={(e) => this.handleSwitchMode(e)} editorType={editorType} />
|
||||||
|
|
||||||
<StarButton
|
<StarButton
|
||||||
onClick={(e) => this.handleStarButtonClick(e)}
|
onClick={(e) => this.handleStarButtonClick(e)}
|
||||||
isActive={note.isStarred}
|
isActive={note.isStarred}
|
||||||
@@ -471,7 +485,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
onFocus={(e) => this.handleFocus(e)}
|
onFocus={(e) => this.handleFocus(e)}
|
||||||
onMouseDown={(e) => this.handleLockButtonMouseDown(e)}
|
onMouseDown={(e) => this.handleLockButtonMouseDown(e)}
|
||||||
>
|
>
|
||||||
<img styleName='iconInfo' src={imgSrc} />
|
<img src={imgSrc} />
|
||||||
{this.state.isLocked ? <span styleName='tooltip'>Unlock</span> : <span styleName='tooltip'>Lock</span>}
|
{this.state.isLocked ? <span styleName='tooltip'>Unlock</span> : <span styleName='tooltip'>Lock</span>}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -491,14 +505,14 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
<InfoPanel
|
<InfoPanel
|
||||||
storageName={currentOption.storage.name}
|
storageName={currentOption.storage.name}
|
||||||
folderName={currentOption.folder.name}
|
folderName={currentOption.folder.name}
|
||||||
noteLink={`[${note.title}](:note:${location.query.key})`}
|
noteLink={`[${note.title}](:note:${queryString.parse(location.search).key})`}
|
||||||
updatedAt={formatDate(note.updatedAt)}
|
updatedAt={formatDate(note.updatedAt)}
|
||||||
createdAt={formatDate(note.createdAt)}
|
createdAt={formatDate(note.createdAt)}
|
||||||
exportAsMd={this.exportAsMd}
|
exportAsMd={this.exportAsMd}
|
||||||
exportAsTxt={this.exportAsTxt}
|
exportAsTxt={this.exportAsTxt}
|
||||||
exportAsHtml={this.exportAsHtml}
|
exportAsHtml={this.exportAsHtml}
|
||||||
exportAsPdf={this.exportAsPdf}
|
exportAsPdf={this.exportAsPdf}
|
||||||
wordCount={note.content.split(' ').length}
|
wordCount={note.content.trim().split(/\s+/g).length}
|
||||||
letterCount={note.content.replace(/\r?\n/g, '').length}
|
letterCount={note.content.replace(/\r?\n/g, '').length}
|
||||||
type={note.type}
|
type={note.type}
|
||||||
print={this.print}
|
print={this.print}
|
||||||
|
|||||||
@@ -80,4 +80,5 @@ body[data-theme="monokai"]
|
|||||||
body[data-theme="dracula"]
|
body[data-theme="dracula"]
|
||||||
.root
|
.root
|
||||||
border-left 1px solid $ui-dracula-borderColor
|
border-left 1px solid $ui-dracula-borderColor
|
||||||
background-color $ui-dracula-noteDetail-backgroundColor
|
background-color $ui-dracula-noteDetail-backgroundColor
|
||||||
|
|
||||||
|
|||||||
@@ -107,4 +107,12 @@ body[data-theme="monokai"]
|
|||||||
body[data-theme="dracula"]
|
body[data-theme="dracula"]
|
||||||
.info
|
.info
|
||||||
border-color $ui-dracula-borderColor
|
border-color $ui-dracula-borderColor
|
||||||
background-color $ui-dracula-noteDetail-backgroundColor
|
background-color $ui-dracula-noteDetail-backgroundColor
|
||||||
|
|
||||||
|
.info > div
|
||||||
|
> button
|
||||||
|
-webkit-user-drag none
|
||||||
|
user-select none
|
||||||
|
> img, span
|
||||||
|
-webkit-user-drag none
|
||||||
|
user-select none
|
||||||
@@ -10,7 +10,7 @@ const PermanentDeleteButton = ({
|
|||||||
<button styleName='control-trashButton--in-trash'
|
<button styleName='control-trashButton--in-trash'
|
||||||
onClick={(e) => onClick(e)}
|
onClick={(e) => onClick(e)}
|
||||||
>
|
>
|
||||||
<img styleName='iconInfo' src='../resources/icon/icon-trash.svg' />
|
<img src='../resources/icon/icon-trash.svg' />
|
||||||
<span styleName='tooltip'>{i18n.__('Permanent Delete')}</span>
|
<span styleName='tooltip'>{i18n.__('Permanent Delete')}</span>
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import StarButton from './StarButton'
|
|||||||
import TagSelect from './TagSelect'
|
import TagSelect from './TagSelect'
|
||||||
import FolderSelect from './FolderSelect'
|
import FolderSelect from './FolderSelect'
|
||||||
import dataApi from 'browser/main/lib/dataApi'
|
import dataApi from 'browser/main/lib/dataApi'
|
||||||
import {hashHistory} from 'react-router'
|
|
||||||
import ee from 'browser/main/lib/eventEmitter'
|
import ee from 'browser/main/lib/eventEmitter'
|
||||||
import CodeMirror from 'codemirror'
|
import CodeMirror from 'codemirror'
|
||||||
import 'codemirror-mode-elixir'
|
import 'codemirror-mode-elixir'
|
||||||
@@ -18,7 +17,6 @@ import context from 'browser/lib/context'
|
|||||||
import ConfigManager from 'browser/main/lib/ConfigManager'
|
import ConfigManager from 'browser/main/lib/ConfigManager'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import {findNoteTitle} from 'browser/lib/findNoteTitle'
|
import {findNoteTitle} from 'browser/lib/findNoteTitle'
|
||||||
import convertModeName from 'browser/lib/convertModeName'
|
|
||||||
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
||||||
import FullscreenButton from './FullscreenButton'
|
import FullscreenButton from './FullscreenButton'
|
||||||
import TrashButton from './TrashButton'
|
import TrashButton from './TrashButton'
|
||||||
@@ -31,6 +29,8 @@ import { formatDate } from 'browser/lib/date-formatter'
|
|||||||
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 markdownToc from 'browser/lib/markdown-toc-generator'
|
import markdownToc from 'browser/lib/markdown-toc-generator'
|
||||||
|
import queryString from 'query-string'
|
||||||
|
import { replace } from 'connected-react-router'
|
||||||
|
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
const { remote } = electron
|
const { remote } = electron
|
||||||
@@ -166,12 +166,12 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
originNote: note,
|
originNote: note,
|
||||||
note: newNote
|
note: newNote
|
||||||
})
|
})
|
||||||
hashHistory.replace({
|
dispatch(replace({
|
||||||
pathname: location.pathname,
|
pathname: location.pathname,
|
||||||
query: {
|
search: queryString.stringify({
|
||||||
key: newNote.key
|
key: newNote.key
|
||||||
}
|
})
|
||||||
})
|
}))
|
||||||
this.setState({
|
this.setState({
|
||||||
isMovingNote: false
|
isMovingNote: false
|
||||||
})
|
})
|
||||||
@@ -518,6 +518,19 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWrapLineButtonClick (e) {
|
||||||
|
context.popup([
|
||||||
|
{
|
||||||
|
label: 'on',
|
||||||
|
click: (e) => this.handleWrapLineItemClick(e, true)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'off',
|
||||||
|
click: (e) => this.handleWrapLineItemClick(e, false)
|
||||||
|
}
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
handleIndentSizeItemClick (e, indentSize) {
|
handleIndentSizeItemClick (e, indentSize) {
|
||||||
const { config, dispatch } = this.props
|
const { config, dispatch } = this.props
|
||||||
const editor = Object.assign({}, config.editor, {
|
const editor = Object.assign({}, config.editor, {
|
||||||
@@ -550,6 +563,22 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWrapLineItemClick (e, lineWrapping) {
|
||||||
|
const { config, dispatch } = this.props
|
||||||
|
const editor = Object.assign({}, config.editor, {
|
||||||
|
lineWrapping
|
||||||
|
})
|
||||||
|
ConfigManager.set({
|
||||||
|
editor
|
||||||
|
})
|
||||||
|
dispatch({
|
||||||
|
type: 'SET_CONFIG',
|
||||||
|
config: {
|
||||||
|
editor
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
focus () {
|
focus () {
|
||||||
this.refs.description.focus()
|
this.refs.description.focus()
|
||||||
}
|
}
|
||||||
@@ -670,7 +699,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { data, config, location } = this.props
|
const { data, dispatch, config, location } = this.props
|
||||||
const { note } = this.state
|
const { note } = this.state
|
||||||
|
|
||||||
const storageKey = note.storage
|
const storageKey = note.storage
|
||||||
@@ -720,6 +749,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
mode={snippet.mode || (autoDetect ? null : config.editor.snippetDefaultLanguage)}
|
mode={snippet.mode || (autoDetect ? null : config.editor.snippetDefaultLanguage)}
|
||||||
value={snippet.content}
|
value={snippet.content}
|
||||||
linesHighlighted={snippet.linesHighlighted}
|
linesHighlighted={snippet.linesHighlighted}
|
||||||
|
lineWrapping={config.editor.lineWrapping}
|
||||||
theme={config.editor.theme}
|
theme={config.editor.theme}
|
||||||
fontFamily={config.editor.fontFamily}
|
fontFamily={config.editor.fontFamily}
|
||||||
fontSize={editorFontSize}
|
fontSize={editorFontSize}
|
||||||
@@ -778,7 +808,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
|
|
||||||
const detailTopBar = <div styleName='info'>
|
const detailTopBar = <div styleName='info'>
|
||||||
<div styleName='info-left'>
|
<div styleName='info-left'>
|
||||||
<div styleName='info-left-top'>
|
<div>
|
||||||
<FolderSelect styleName='info-left-top-folderSelect'
|
<FolderSelect styleName='info-left-top-folderSelect'
|
||||||
value={this.state.note.storage + '-' + this.state.note.folder}
|
value={this.state.note.storage + '-' + this.state.note.folder}
|
||||||
ref='folder'
|
ref='folder'
|
||||||
@@ -793,6 +823,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
saveTagsAlphabetically={config.ui.saveTagsAlphabetically}
|
saveTagsAlphabetically={config.ui.saveTagsAlphabetically}
|
||||||
showTagsAlphabetically={config.ui.showTagsAlphabetically}
|
showTagsAlphabetically={config.ui.showTagsAlphabetically}
|
||||||
data={data}
|
data={data}
|
||||||
|
dispatch={dispatch}
|
||||||
onChange={(e) => this.handleChange(e)}
|
onChange={(e) => this.handleChange(e)}
|
||||||
coloredTags={config.coloredTags}
|
coloredTags={config.coloredTags}
|
||||||
/>
|
/>
|
||||||
@@ -814,7 +845,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
<InfoPanel
|
<InfoPanel
|
||||||
storageName={currentOption.storage.name}
|
storageName={currentOption.storage.name}
|
||||||
folderName={currentOption.folder.name}
|
folderName={currentOption.folder.name}
|
||||||
noteLink={`[${note.title}](:note:${location.query.key})`}
|
noteLink={`[${note.title}](:note:${queryString.parse(location.search).key})`}
|
||||||
updatedAt={formatDate(note.updatedAt)}
|
updatedAt={formatDate(note.updatedAt)}
|
||||||
createdAt={formatDate(note.createdAt)}
|
createdAt={formatDate(note.createdAt)}
|
||||||
exportAsMd={this.showWarning}
|
exportAsMd={this.showWarning}
|
||||||
@@ -899,6 +930,12 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
size: {config.editor.indentSize}
|
size: {config.editor.indentSize}
|
||||||
<i className='fa fa-caret-down' />
|
<i className='fa fa-caret-down' />
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={(e) => this.handleWrapLineButtonClick(e)}
|
||||||
|
>
|
||||||
|
Wrap Line: {config.editor.lineWrapping ? 'on' : 'off'}
|
||||||
|
<i className='fa fa-caret-down' />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<StatusBar
|
<StatusBar
|
||||||
|
|||||||
@@ -42,4 +42,4 @@ body[data-theme="dark"]
|
|||||||
topBarButtonDark()
|
topBarButtonDark()
|
||||||
&:hover
|
&:hover
|
||||||
transition 0.2s
|
transition 0.2s
|
||||||
color alpha($ui-favorite-star-button-color, 0.6)
|
color alpha($ui-favorite-star-button-color, 0.6)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
|||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
import ee from 'browser/main/lib/eventEmitter'
|
import ee from 'browser/main/lib/eventEmitter'
|
||||||
import Autosuggest from 'react-autosuggest'
|
import Autosuggest from 'react-autosuggest'
|
||||||
|
import { push } from 'connected-react-router'
|
||||||
|
|
||||||
class TagSelect extends React.Component {
|
class TagSelect extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
@@ -96,8 +97,11 @@ class TagSelect extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleTagLabelClick (tag) {
|
handleTagLabelClick (tag) {
|
||||||
const { router } = this.context
|
const { dispatch } = this.props
|
||||||
router.push(`/tags/${tag}`)
|
|
||||||
|
// Note: `tag` requires encoding later.
|
||||||
|
// E.g. % in tag is a problem (see issue #3170) - encodeURIComponent(tag) is not working.
|
||||||
|
dispatch(push(`/tags/${tag}`))
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTagRemoveButtonClick (tag) {
|
handleTagRemoveButtonClick (tag) {
|
||||||
@@ -255,11 +259,8 @@ class TagSelect extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TagSelect.contextTypes = {
|
|
||||||
router: PropTypes.shape({})
|
|
||||||
}
|
|
||||||
|
|
||||||
TagSelect.propTypes = {
|
TagSelect.propTypes = {
|
||||||
|
dispatch: PropTypes.func,
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
value: PropTypes.arrayOf(PropTypes.string),
|
value: PropTypes.arrayOf(PropTypes.string),
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ const ToggleModeButton = ({
|
|||||||
onClick, editorType
|
onClick, editorType
|
||||||
}) => (
|
}) => (
|
||||||
<div styleName='control-toggleModeButton'>
|
<div styleName='control-toggleModeButton'>
|
||||||
<div styleName={editorType === 'SPLIT' ? 'active' : 'non-active'} onClick={() => onClick('SPLIT')}>
|
<div styleName={editorType === 'SPLIT' ? 'active' : undefined} onClick={() => onClick('SPLIT')}>
|
||||||
<img styleName='item-star' src={editorType === 'EDITOR_PREVIEW' ? '../resources/icon/icon-mode-markdown-off-active.svg' : ''} />
|
<img src={editorType === 'EDITOR_PREVIEW' ? '../resources/icon/icon-mode-markdown-off-active.svg' : ''} />
|
||||||
</div>
|
</div>
|
||||||
<div styleName={editorType === 'EDITOR_PREVIEW' ? 'active' : 'non-active'} onClick={() => onClick('EDITOR_PREVIEW')}>
|
<div styleName={editorType === 'EDITOR_PREVIEW' ? 'active' : undefined} onClick={() => onClick('EDITOR_PREVIEW')}>
|
||||||
<img styleName='item-star' src={editorType === 'EDITOR_PREVIEW' ? '' : '../resources/icon/icon-mode-split-on-active.svg'} />
|
<img src={editorType === 'EDITOR_PREVIEW' ? '' : '../resources/icon/icon-mode-split-on-active.svg'} />
|
||||||
</div>
|
</div>
|
||||||
<span lang={i18n.locale} styleName='tooltip'>{i18n.__('Toggle Mode')}</span>
|
<span lang={i18n.locale} styleName='tooltip'>{i18n.__('Toggle Mode')}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -20,7 +20,7 @@ const ToggleModeButton = ({
|
|||||||
|
|
||||||
ToggleModeButton.propTypes = {
|
ToggleModeButton.propTypes = {
|
||||||
onClick: PropTypes.func.isRequired,
|
onClick: PropTypes.func.isRequired,
|
||||||
editorType: PropTypes.string.Required
|
editorType: PropTypes.string.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CSSModules(ToggleModeButton, styles)
|
export default CSSModules(ToggleModeButton, styles)
|
||||||
|
|||||||
@@ -75,3 +75,10 @@ body[data-theme="dracula"]
|
|||||||
.active
|
.active
|
||||||
background-color #bd93f9
|
background-color #bd93f9
|
||||||
box-shadow 2px 0px 7px #222222
|
box-shadow 2px 0px 7px #222222
|
||||||
|
|
||||||
|
.control-toggleModeButton
|
||||||
|
-webkit-user-drag none
|
||||||
|
user-select none
|
||||||
|
> div img
|
||||||
|
-webkit-user-drag none
|
||||||
|
user-select none
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const TrashButton = ({
|
|||||||
<button styleName='control-trashButton'
|
<button styleName='control-trashButton'
|
||||||
onClick={(e) => onClick(e)}
|
onClick={(e) => onClick(e)}
|
||||||
>
|
>
|
||||||
<img styleName='iconInfo' src='../resources/icon/icon-trash.svg' />
|
<img src='../resources/icon/icon-trash.svg' />
|
||||||
<span lang={i18n.locale} styleName='tooltip'>{i18n.__('Trash')}</span>
|
<span lang={i18n.locale} styleName='tooltip'>{i18n.__('Trash')}</span>
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import StatusBar from '../StatusBar'
|
|||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
import debounceRender from 'react-debounce-render'
|
import debounceRender from 'react-debounce-render'
|
||||||
import searchFromNotes from 'browser/lib/search'
|
import searchFromNotes from 'browser/lib/search'
|
||||||
|
import queryString from 'query-string'
|
||||||
|
|
||||||
const OSX = global.process.platform === 'darwin'
|
const OSX = global.process.platform === 'darwin'
|
||||||
|
|
||||||
@@ -36,11 +37,11 @@ class Detail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { location, data, params, config } = this.props
|
const { location, data, match: { params }, config } = this.props
|
||||||
|
const noteKey = location.search !== '' && queryString.parse(location.search).key
|
||||||
let note = null
|
let note = null
|
||||||
|
|
||||||
if (location.query.key != null) {
|
if (location.search !== '') {
|
||||||
const noteKey = location.query.key
|
|
||||||
const allNotes = data.noteMap.map(note => note)
|
const allNotes = data.noteMap.map(note => note)
|
||||||
const trashedNotes = data.trashedSet.toJS().map(uniqueKey => data.noteMap.get(uniqueKey))
|
const trashedNotes = data.trashedSet.toJS().map(uniqueKey => data.noteMap.get(uniqueKey))
|
||||||
let displayedNotes = allNotes
|
let displayedNotes = allNotes
|
||||||
@@ -49,16 +50,14 @@ class Detail extends React.Component {
|
|||||||
const searchStr = params.searchword
|
const searchStr = params.searchword
|
||||||
displayedNotes = searchStr === undefined || searchStr === '' ? allNotes
|
displayedNotes = searchStr === undefined || searchStr === '' ? allNotes
|
||||||
: searchFromNotes(allNotes, searchStr)
|
: searchFromNotes(allNotes, searchStr)
|
||||||
}
|
} else if (location.pathname.match(/^\/tags/)) {
|
||||||
|
|
||||||
if (location.pathname.match(/\/tags/)) {
|
|
||||||
const listOfTags = params.tagname.split(' ')
|
const listOfTags = params.tagname.split(' ')
|
||||||
displayedNotes = data.noteMap.map(note => note).filter(note =>
|
displayedNotes = data.noteMap.map(note => note).filter(note =>
|
||||||
listOfTags.every(tag => note.tags.includes(tag))
|
listOfTags.every(tag => note.tags.includes(tag))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (location.pathname.match(/\/trashed/)) {
|
if (location.pathname.match(/^\/trashed/)) {
|
||||||
displayedNotes = trashedNotes
|
displayedNotes = trashedNotes
|
||||||
} else {
|
} else {
|
||||||
displayedNotes = _.differenceWith(displayedNotes, trashedNotes, (note, trashed) => note.key === trashed.key)
|
displayedNotes = _.differenceWith(displayedNotes, trashedNotes, (note, trashed) => note.key === trashed.key)
|
||||||
|
|||||||
16
browser/main/DevTools/index.dev.js
Normal file
16
browser/main/DevTools/index.dev.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { createDevTools } from 'redux-devtools'
|
||||||
|
import LogMonitor from 'redux-devtools-log-monitor'
|
||||||
|
import DockMonitor from 'redux-devtools-dock-monitor'
|
||||||
|
|
||||||
|
const DevTools = createDevTools(
|
||||||
|
<DockMonitor
|
||||||
|
toggleVisibilityKey='ctrl-h'
|
||||||
|
changePositionKey='ctrl-q'
|
||||||
|
defaultIsVisible={false}
|
||||||
|
>
|
||||||
|
<LogMonitor theme='tomorrow' />
|
||||||
|
</DockMonitor>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default DevTools
|
||||||
8
browser/main/DevTools/index.js
Normal file
8
browser/main/DevTools/index.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/* eslint-disable no-undef */
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
// eslint-disable-next-line global-require
|
||||||
|
module.exports = require('./index.dev').default
|
||||||
|
} else {
|
||||||
|
// eslint-disable-next-line global-require
|
||||||
|
module.exports = require('./index.prod').default
|
||||||
|
}
|
||||||
6
browser/main/DevTools/index.prod.js
Normal file
6
browser/main/DevTools/index.prod.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const DevTools = () => <div />
|
||||||
|
DevTools.instrument = () => {}
|
||||||
|
|
||||||
|
export default DevTools
|
||||||
@@ -12,11 +12,11 @@ import _ from 'lodash'
|
|||||||
import ConfigManager from 'browser/main/lib/ConfigManager'
|
import ConfigManager from 'browser/main/lib/ConfigManager'
|
||||||
import mobileAnalytics from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
import mobileAnalytics from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
||||||
import eventEmitter from 'browser/main/lib/eventEmitter'
|
import eventEmitter from 'browser/main/lib/eventEmitter'
|
||||||
import { hashHistory } from 'react-router'
|
import { store } from 'browser/main/store'
|
||||||
import store from 'browser/main/store'
|
|
||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
import { getLocales } from 'browser/lib/Languages'
|
import { getLocales } from 'browser/lib/Languages'
|
||||||
import applyShortcuts from 'browser/main/lib/shortcutManager'
|
import applyShortcuts from 'browser/main/lib/shortcutManager'
|
||||||
|
import { push } from 'connected-react-router'
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
const { remote } = electron
|
const { remote } = electron
|
||||||
@@ -102,7 +102,7 @@ class Main extends React.Component {
|
|||||||
{
|
{
|
||||||
name: 'example.js',
|
name: 'example.js',
|
||||||
mode: 'javascript',
|
mode: 'javascript',
|
||||||
content: "var boostnote = document.getElementById('enjoy').innerHTML\n\nconsole.log(boostnote)",
|
content: "var boostnote = document.getElementById('hello').innerHTML\n\nconsole.log(boostnote)",
|
||||||
linesHighlighted: []
|
linesHighlighted: []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -132,7 +132,7 @@ class Main extends React.Component {
|
|||||||
.then(() => data.storage)
|
.then(() => data.storage)
|
||||||
})
|
})
|
||||||
.then(storage => {
|
.then(storage => {
|
||||||
hashHistory.push('/storages/' + storage.key)
|
store.dispatch(push('/storages/' + storage.key))
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
throw err
|
throw err
|
||||||
@@ -169,6 +169,7 @@ class Main extends React.Component {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
delete CodeMirror.keyMap.emacs['Ctrl-V']
|
delete CodeMirror.keyMap.emacs['Ctrl-V']
|
||||||
|
|
||||||
eventEmitter.on('editor:fullscreen', this.toggleFullScreen)
|
eventEmitter.on('editor:fullscreen', this.toggleFullScreen)
|
||||||
@@ -311,7 +312,7 @@ class Main extends React.Component {
|
|||||||
onMouseUp={e => this.handleMouseUp(e)}
|
onMouseUp={e => this.handleMouseUp(e)}
|
||||||
>
|
>
|
||||||
<SideNav
|
<SideNav
|
||||||
{..._.pick(this.props, ['dispatch', 'data', 'config', 'params', 'location'])}
|
{..._.pick(this.props, ['dispatch', 'data', 'config', 'match', 'location'])}
|
||||||
width={this.state.navWidth}
|
width={this.state.navWidth}
|
||||||
/>
|
/>
|
||||||
{!config.isSideNavFolded &&
|
{!config.isSideNavFolded &&
|
||||||
@@ -341,7 +342,7 @@ class Main extends React.Component {
|
|||||||
'dispatch',
|
'dispatch',
|
||||||
'config',
|
'config',
|
||||||
'data',
|
'data',
|
||||||
'params',
|
'match',
|
||||||
'location'
|
'location'
|
||||||
])}
|
])}
|
||||||
/>
|
/>
|
||||||
@@ -351,7 +352,7 @@ class Main extends React.Component {
|
|||||||
'dispatch',
|
'dispatch',
|
||||||
'data',
|
'data',
|
||||||
'config',
|
'config',
|
||||||
'params',
|
'match',
|
||||||
'location'
|
'location'
|
||||||
])}
|
])}
|
||||||
/>
|
/>
|
||||||
@@ -373,7 +374,7 @@ class Main extends React.Component {
|
|||||||
'dispatch',
|
'dispatch',
|
||||||
'data',
|
'data',
|
||||||
'config',
|
'config',
|
||||||
'params',
|
'match',
|
||||||
'location'
|
'location'
|
||||||
])}
|
])}
|
||||||
ignorePreviewPointerEvents={this.state.isRightSliderFocused}
|
ignorePreviewPointerEvents={this.state.isRightSliderFocused}
|
||||||
|
|||||||
@@ -21,23 +21,20 @@ class NewNoteButton extends React.Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.newNoteHandler = () => {
|
this.handleNewNoteButtonClick = this.handleNewNoteButtonClick.bind(this)
|
||||||
this.handleNewNoteButtonClick()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
eventEmitter.on('top:new-note', this.newNoteHandler)
|
eventEmitter.on('top:new-note', this.handleNewNoteButtonClick)
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount () {
|
componentWillUnmount () {
|
||||||
eventEmitter.off('top:new-note', this.newNoteHandler)
|
eventEmitter.off('top:new-note', this.handleNewNoteButtonClick)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleNewNoteButtonClick (e) {
|
handleNewNoteButtonClick (e) {
|
||||||
const { location, params, dispatch, config } = this.props
|
const { location, dispatch, match: { params }, config } = this.props
|
||||||
const { storage, folder } = this.resolveTargetFolder()
|
const { storage, folder } = this.resolveTargetFolder()
|
||||||
|
|
||||||
if (config.ui.defaultNote === 'MARKDOWN_NOTE') {
|
if (config.ui.defaultNote === 'MARKDOWN_NOTE') {
|
||||||
createMarkdownNote(storage.key, folder.key, dispatch, location, params, config)
|
createMarkdownNote(storage.key, folder.key, dispatch, location, params, config)
|
||||||
} else if (config.ui.defaultNote === 'SNIPPET_NOTE') {
|
} else if (config.ui.defaultNote === 'SNIPPET_NOTE') {
|
||||||
@@ -55,9 +52,8 @@ class NewNoteButton extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resolveTargetFolder () {
|
resolveTargetFolder () {
|
||||||
const { data, params } = this.props
|
const { data, match: { params } } = this.props
|
||||||
let storage = data.storageMap.get(params.storageKey)
|
let storage = data.storageMap.get(params.storageKey)
|
||||||
|
|
||||||
// Find first storage
|
// Find first storage
|
||||||
if (storage == null) {
|
if (storage == null) {
|
||||||
for (const kv of data.storageMap) {
|
for (const kv of data.storageMap) {
|
||||||
@@ -93,8 +89,8 @@ class NewNoteButton extends React.Component {
|
|||||||
>
|
>
|
||||||
<div styleName='control'>
|
<div styleName='control'>
|
||||||
<button styleName='control-newNoteButton'
|
<button styleName='control-newNoteButton'
|
||||||
onClick={(e) => this.handleNewNoteButtonClick(e)}>
|
onClick={this.handleNewNoteButtonClick}>
|
||||||
<img styleName='iconTag' src='../resources/icon/icon-newnote.svg' />
|
<img src='../resources/icon/icon-newnote.svg' />
|
||||||
<span styleName='control-newNoteButton-tooltip'>
|
<span styleName='control-newNoteButton-tooltip'>
|
||||||
{i18n.__('Make a note')} {OSX ? '⌘' : i18n.__('Ctrl')} + N
|
{i18n.__('Make a note')} {OSX ? '⌘' : i18n.__('Ctrl')} + N
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -14,13 +14,14 @@ import NoteItemSimple from 'browser/components/NoteItemSimple'
|
|||||||
import searchFromNotes from 'browser/lib/search'
|
import searchFromNotes from 'browser/lib/search'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { hashHistory } from 'react-router'
|
import { push, replace } from 'connected-react-router'
|
||||||
import copy from 'copy-to-clipboard'
|
import copy from 'copy-to-clipboard'
|
||||||
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
||||||
import Markdown from '../../lib/markdown'
|
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 queryString from 'query-string'
|
||||||
|
|
||||||
const { remote } = require('electron')
|
const { remote } = require('electron')
|
||||||
const { dialog } = remote
|
const { dialog } = remote
|
||||||
@@ -87,6 +88,7 @@ class NoteList extends React.Component {
|
|||||||
this.importFromFileHandler = this.importFromFile.bind(this)
|
this.importFromFileHandler = this.importFromFile.bind(this)
|
||||||
this.jumpNoteByHash = this.jumpNoteByHashHandler.bind(this)
|
this.jumpNoteByHash = this.jumpNoteByHashHandler.bind(this)
|
||||||
this.handleNoteListKeyUp = this.handleNoteListKeyUp.bind(this)
|
this.handleNoteListKeyUp = this.handleNoteListKeyUp.bind(this)
|
||||||
|
this.handleNoteListBlur = this.handleNoteListBlur.bind(this)
|
||||||
this.getNoteKeyFromTargetIndex = this.getNoteKeyFromTargetIndex.bind(this)
|
this.getNoteKeyFromTargetIndex = this.getNoteKeyFromTargetIndex.bind(this)
|
||||||
this.cloneNote = this.cloneNote.bind(this)
|
this.cloneNote = this.cloneNote.bind(this)
|
||||||
this.deleteNote = this.deleteNote.bind(this)
|
this.deleteNote = this.deleteNote.bind(this)
|
||||||
@@ -145,15 +147,15 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate (prevProps) {
|
componentDidUpdate (prevProps) {
|
||||||
const { location } = this.props
|
const { dispatch, location } = this.props
|
||||||
const { selectedNoteKeys } = this.state
|
const { selectedNoteKeys } = this.state
|
||||||
const visibleNoteKeys = this.notes.map(note => note.key)
|
const visibleNoteKeys = this.notes && this.notes.map(note => note.key)
|
||||||
const note = this.notes[0]
|
const note = this.notes && this.notes[0]
|
||||||
const prevKey = prevProps.location.query.key
|
const key = location.search && queryString.parse(location.search).key
|
||||||
|
const prevKey = prevProps.location.search && queryString.parse(prevProps.location.search).key
|
||||||
const noteKey = visibleNoteKeys.includes(prevKey) ? prevKey : note && note.key
|
const noteKey = visibleNoteKeys.includes(prevKey) ? prevKey : note && note.key
|
||||||
|
|
||||||
if (note && location.query.key == null) {
|
if (note && location.search === '') {
|
||||||
const { router } = this.context
|
|
||||||
if (!location.pathname.match(/\/searched/)) this.contextNotes = this.getContextNotes()
|
if (!location.pathname.match(/\/searched/)) this.contextNotes = this.getContextNotes()
|
||||||
|
|
||||||
// A visible note is an active note
|
// A visible note is an active note
|
||||||
@@ -163,17 +165,17 @@ class NoteList extends React.Component {
|
|||||||
ee.emit('list:moved')
|
ee.emit('list:moved')
|
||||||
}
|
}
|
||||||
|
|
||||||
router.replace({
|
dispatch(replace({ // was passed with context - we can use connected router here
|
||||||
pathname: location.pathname,
|
pathname: location.pathname,
|
||||||
query: {
|
search: queryString.stringify({
|
||||||
key: noteKey
|
key: noteKey
|
||||||
}
|
})
|
||||||
})
|
}))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auto scroll
|
// Auto scroll
|
||||||
if (_.isString(location.query.key) && prevProps.location.query.key === location.query.key) {
|
if (_.isString(key) && prevKey === key) {
|
||||||
const targetIndex = this.getTargetIndex()
|
const targetIndex = this.getTargetIndex()
|
||||||
if (targetIndex > -1) {
|
if (targetIndex > -1) {
|
||||||
const list = this.refs.list
|
const list = this.refs.list
|
||||||
@@ -194,18 +196,18 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
focusNote (selectedNoteKeys, noteKey, pathname) {
|
focusNote (selectedNoteKeys, noteKey, pathname) {
|
||||||
const { router } = this.context
|
const { dispatch } = this.props
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedNoteKeys
|
selectedNoteKeys
|
||||||
})
|
})
|
||||||
|
|
||||||
router.push({
|
dispatch(push({
|
||||||
pathname,
|
pathname,
|
||||||
query: {
|
search: queryString.stringify({
|
||||||
key: noteKey
|
key: noteKey
|
||||||
}
|
})
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
getNoteKeyFromTargetIndex (targetIndex) {
|
getNoteKeyFromTargetIndex (targetIndex) {
|
||||||
@@ -347,9 +349,15 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getNotes () {
|
handleNoteListBlur () {
|
||||||
const { data, params, location } = this.props
|
this.setState({
|
||||||
|
shiftKeyDown: false,
|
||||||
|
ctrlKeyDown: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getNotes () {
|
||||||
|
const { data, match: { params }, location } = this.props
|
||||||
if (location.pathname.match(/\/home/) || location.pathname.match(/alltags/)) {
|
if (location.pathname.match(/\/home/) || location.pathname.match(/alltags/)) {
|
||||||
const allNotes = data.noteMap.map((note) => note)
|
const allNotes = data.noteMap.map((note) => note)
|
||||||
this.contextNotes = allNotes
|
this.contextNotes = allNotes
|
||||||
@@ -390,7 +398,7 @@ class NoteList extends React.Component {
|
|||||||
|
|
||||||
// get notes in the current folder
|
// get notes in the current folder
|
||||||
getContextNotes () {
|
getContextNotes () {
|
||||||
const { data, params } = this.props
|
const { data, match: { params } } = this.props
|
||||||
const storageKey = params.storageKey
|
const storageKey = params.storageKey
|
||||||
const folderKey = params.folderKey
|
const folderKey = params.folderKey
|
||||||
const storage = data.storageMap.get(storageKey)
|
const storage = data.storageMap.get(storageKey)
|
||||||
@@ -430,8 +438,7 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleNoteClick (e, uniqueKey) {
|
handleNoteClick (e, uniqueKey) {
|
||||||
const { router } = this.context
|
const { dispatch, location } = this.props
|
||||||
const { location } = this.props
|
|
||||||
let { selectedNoteKeys, prevShiftNoteIndex } = this.state
|
let { selectedNoteKeys, prevShiftNoteIndex } = this.state
|
||||||
const { ctrlKeyDown, shiftKeyDown } = this.state
|
const { ctrlKeyDown, shiftKeyDown } = this.state
|
||||||
const hasSelectedNoteKey = selectedNoteKeys.length > 0
|
const hasSelectedNoteKey = selectedNoteKeys.length > 0
|
||||||
@@ -482,16 +489,16 @@ class NoteList extends React.Component {
|
|||||||
prevShiftNoteIndex
|
prevShiftNoteIndex
|
||||||
})
|
})
|
||||||
|
|
||||||
router.push({
|
dispatch(push({
|
||||||
pathname: location.pathname,
|
pathname: location.pathname,
|
||||||
query: {
|
search: queryString.stringify({
|
||||||
key: uniqueKey
|
key: uniqueKey
|
||||||
}
|
})
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSortByChange (e) {
|
handleSortByChange (e) {
|
||||||
const { dispatch, params: { folderKey } } = this.props
|
const { dispatch, match: { params: { folderKey } } } = this.props
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
[folderKey]: { sortBy: e.target.value }
|
[folderKey]: { sortBy: e.target.value }
|
||||||
@@ -764,10 +771,10 @@ class NoteList extends React.Component {
|
|||||||
selectedNoteKeys: [note.key]
|
selectedNoteKeys: [note.key]
|
||||||
})
|
})
|
||||||
|
|
||||||
hashHistory.push({
|
dispatch(push({
|
||||||
pathname: location.pathname,
|
pathname: location.pathname,
|
||||||
query: {key: note.key}
|
search: queryString.stringify({key: note.key})
|
||||||
})
|
}))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -777,13 +784,13 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
navigate (sender, pathname) {
|
navigate (sender, pathname) {
|
||||||
const { router } = this.context
|
const { dispatch } = this.props
|
||||||
router.push({
|
dispatch(push({
|
||||||
pathname,
|
pathname,
|
||||||
query: {
|
search: queryString.stringify({
|
||||||
// key: noteKey
|
// key: noteKey
|
||||||
}
|
})
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
save (note) {
|
save (note) {
|
||||||
@@ -947,10 +954,10 @@ class NoteList extends React.Component {
|
|||||||
type: 'UPDATE_NOTE',
|
type: 'UPDATE_NOTE',
|
||||||
note: note
|
note: note
|
||||||
})
|
})
|
||||||
hashHistory.push({
|
dispatch(push({
|
||||||
pathname: location.pathname,
|
pathname: location.pathname,
|
||||||
query: {key: getNoteKey(note)}
|
search: queryString.stringify({key: getNoteKey(note)})
|
||||||
})
|
}))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -960,14 +967,15 @@ class NoteList extends React.Component {
|
|||||||
|
|
||||||
getTargetIndex () {
|
getTargetIndex () {
|
||||||
const { location } = this.props
|
const { location } = this.props
|
||||||
|
const key = queryString.parse(location.search).key
|
||||||
const targetIndex = _.findIndex(this.notes, (note) => {
|
const targetIndex = _.findIndex(this.notes, (note) => {
|
||||||
return getNoteKey(note) === location.query.key
|
return getNoteKey(note) === key
|
||||||
})
|
})
|
||||||
return targetIndex
|
return targetIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
resolveTargetFolder () {
|
resolveTargetFolder () {
|
||||||
const { data, params } = this.props
|
const { data, match: { params } } = this.props
|
||||||
let storage = data.storageMap.get(params.storageKey)
|
let storage = data.storageMap.get(params.storageKey)
|
||||||
|
|
||||||
// Find first storage
|
// Find first storage
|
||||||
@@ -1015,7 +1023,7 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { location, config, params: { folderKey } } = this.props
|
const { location, config, match: { params: { folderKey } } } = this.props
|
||||||
let { notes } = this.props
|
let { notes } = this.props
|
||||||
const { selectedNoteKeys } = this.state
|
const { selectedNoteKeys } = this.state
|
||||||
const sortBy = _.get(config, [folderKey, 'sortBy'], config.sortBy.default)
|
const sortBy = _.get(config, [folderKey, 'sortBy'], config.sortBy.default)
|
||||||
@@ -1138,7 +1146,7 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
onClick={(e) => this.handleListStyleButtonClick(e, 'DEFAULT')}
|
onClick={(e) => this.handleListStyleButtonClick(e, 'DEFAULT')}
|
||||||
>
|
>
|
||||||
<img styleName='iconTag' src='../resources/icon/icon-column.svg' />
|
<img src='../resources/icon/icon-column.svg' />
|
||||||
</button>
|
</button>
|
||||||
<button title={i18n.__('Compressed View')} styleName={config.listStyle === 'SMALL'
|
<button title={i18n.__('Compressed View')} styleName={config.listStyle === 'SMALL'
|
||||||
? 'control-button--active'
|
? 'control-button--active'
|
||||||
@@ -1146,7 +1154,7 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
onClick={(e) => this.handleListStyleButtonClick(e, 'SMALL')}
|
onClick={(e) => this.handleListStyleButtonClick(e, 'SMALL')}
|
||||||
>
|
>
|
||||||
<img styleName='iconTag' src='../resources/icon/icon-column-list.svg' />
|
<img src='../resources/icon/icon-column-list.svg' />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1155,6 +1163,7 @@ class NoteList extends React.Component {
|
|||||||
tabIndex='-1'
|
tabIndex='-1'
|
||||||
onKeyDown={(e) => this.handleNoteListKeyDown(e)}
|
onKeyDown={(e) => this.handleNoteListKeyDown(e)}
|
||||||
onKeyUp={this.handleNoteListKeyUp}
|
onKeyUp={this.handleNoteListKeyUp}
|
||||||
|
onBlur={this.handleNoteListBlur}
|
||||||
>
|
>
|
||||||
{noteList}
|
{noteList}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const PreferenceButton = ({
|
|||||||
onClick
|
onClick
|
||||||
}) => (
|
}) => (
|
||||||
<button styleName='top-menu-preference' onClick={(e) => onClick(e)}>
|
<button styleName='top-menu-preference' onClick={(e) => onClick(e)}>
|
||||||
<img styleName='iconTag' src='../resources/icon/icon-setting.svg' />
|
<img src='../resources/icon/icon-setting.svg' />
|
||||||
<span styleName='tooltip'>{i18n.__('Preferences')}</span>
|
<span styleName='tooltip'>{i18n.__('Preferences')}</span>
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import PropTypes from 'prop-types'
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './StorageItem.styl'
|
import styles from './StorageItem.styl'
|
||||||
import { hashHistory } from 'react-router'
|
|
||||||
import modal from 'browser/main/lib/modal'
|
import modal from 'browser/main/lib/modal'
|
||||||
import CreateFolderModal from 'browser/main/modals/CreateFolderModal'
|
import CreateFolderModal from 'browser/main/modals/CreateFolderModal'
|
||||||
import RenameFolderModal from 'browser/main/modals/RenameFolderModal'
|
import RenameFolderModal from 'browser/main/modals/RenameFolderModal'
|
||||||
@@ -12,6 +11,7 @@ import _ from 'lodash'
|
|||||||
import { SortableElement } from 'react-sortable-hoc'
|
import { SortableElement } from 'react-sortable-hoc'
|
||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
import context from 'browser/lib/context'
|
import context from 'browser/lib/context'
|
||||||
|
import { push } from 'connected-react-router'
|
||||||
|
|
||||||
const { remote } = require('electron')
|
const { remote } = require('electron')
|
||||||
const { dialog } = remote
|
const { dialog } = remote
|
||||||
@@ -134,14 +134,14 @@ class StorageItem extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleHeaderInfoClick (e) {
|
handleHeaderInfoClick (e) {
|
||||||
const { storage } = this.props
|
const { storage, dispatch } = this.props
|
||||||
hashHistory.push('/storages/' + storage.key)
|
dispatch(push('/storages/' + storage.key))
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFolderButtonClick (folderKey) {
|
handleFolderButtonClick (folderKey) {
|
||||||
return (e) => {
|
return (e) => {
|
||||||
const { storage } = this.props
|
const { storage, dispatch } = this.props
|
||||||
hashHistory.push('/storages/' + storage.key + '/folders/' + folderKey)
|
dispatch(push('/storages/' + storage.key + '/folders/' + folderKey))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,14 +362,14 @@ class StorageItem extends React.Component {
|
|||||||
<button styleName='header-addFolderButton'
|
<button styleName='header-addFolderButton'
|
||||||
onClick={(e) => this.handleAddFolderButtonClick(e)}
|
onClick={(e) => this.handleAddFolderButtonClick(e)}
|
||||||
>
|
>
|
||||||
<img styleName='iconTag' src='../resources/icon/icon-plus.svg' />
|
<img src='../resources/icon/icon-plus.svg' />
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
|
|
||||||
<button styleName='header-info'
|
<button styleName='header-info'
|
||||||
onClick={(e) => this.handleHeaderInfoClick(e)}
|
onClick={(e) => this.handleHeaderInfoClick(e)}
|
||||||
>
|
>
|
||||||
<span styleName='header-info-name'>
|
<span>
|
||||||
{isFolded ? _.truncate(storage.name, {length: 1, omission: ''}) : storage.name}
|
{isFolded ? _.truncate(storage.name, {length: 1, omission: ''}) : storage.name}
|
||||||
</span>
|
</span>
|
||||||
{isFolded &&
|
{isFolded &&
|
||||||
@@ -380,7 +380,7 @@ class StorageItem extends React.Component {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{this.state.isOpen &&
|
{this.state.isOpen &&
|
||||||
<div styleName='folderList' >
|
<div>
|
||||||
{folderList}
|
{folderList}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { push } from 'connected-react-router'
|
||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
import dataApi from 'browser/main/lib/dataApi'
|
import dataApi from 'browser/main/lib/dataApi'
|
||||||
import styles from './SideNav.styl'
|
import styles from './SideNav.styl'
|
||||||
@@ -21,9 +22,10 @@ import context from 'browser/lib/context'
|
|||||||
import { remote } from 'electron'
|
import { remote } from 'electron'
|
||||||
import { confirmDeleteNote } from 'browser/lib/confirmDeleteNote'
|
import { confirmDeleteNote } from 'browser/lib/confirmDeleteNote'
|
||||||
import ColorPicker from 'browser/components/ColorPicker'
|
import ColorPicker from 'browser/components/ColorPicker'
|
||||||
|
import { every, sortBy } from 'lodash'
|
||||||
|
|
||||||
function matchActiveTags (tags, activeTags) {
|
function matchActiveTags (tags, activeTags) {
|
||||||
return _.every(activeTags, v => tags.indexOf(v) >= 0)
|
return every(activeTags, v => tags.indexOf(v) >= 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
class SideNav extends React.Component {
|
class SideNav extends React.Component {
|
||||||
@@ -55,14 +57,14 @@ class SideNav extends React.Component {
|
|||||||
|
|
||||||
deleteTag (tag) {
|
deleteTag (tag) {
|
||||||
const selectedButton = remote.dialog.showMessageBox(remote.getCurrentWindow(), {
|
const selectedButton = remote.dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||||
ype: '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 { data, dispatch, location, params } = this.props
|
const { data, dispatch, location, match: { params } } = this.props
|
||||||
|
|
||||||
const notes = data.noteMap
|
const notes = data.noteMap
|
||||||
.map(note => note)
|
.map(note => note)
|
||||||
@@ -92,7 +94,7 @@ class SideNav extends React.Component {
|
|||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
tags.splice(index, 1)
|
tags.splice(index, 1)
|
||||||
|
|
||||||
this.context.router.push(`/tags/${tags.map(tag => encodeURIComponent(tag)).join(' ')}`)
|
dispatch(push(`/tags/${tags.map(tag => encodeURIComponent(tag)).join(' ')}`))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -104,13 +106,13 @@ class SideNav extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleHomeButtonClick (e) {
|
handleHomeButtonClick (e) {
|
||||||
const { router } = this.context
|
const { dispatch } = this.props
|
||||||
router.push('/home')
|
dispatch(push('/home'))
|
||||||
}
|
}
|
||||||
|
|
||||||
handleStarredButtonClick (e) {
|
handleStarredButtonClick (e) {
|
||||||
const { router } = this.context
|
const { dispatch } = this.props
|
||||||
router.push('/starred')
|
dispatch(push('/starred'))
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTagContextMenu (e, tag) {
|
handleTagContextMenu (e, tag) {
|
||||||
@@ -190,18 +192,18 @@ class SideNav extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleTrashedButtonClick (e) {
|
handleTrashedButtonClick (e) {
|
||||||
const { router } = this.context
|
const { dispatch } = this.props
|
||||||
router.push('/trashed')
|
dispatch(push('/trashed'))
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSwitchFoldersButtonClick () {
|
handleSwitchFoldersButtonClick () {
|
||||||
const { router } = this.context
|
const { dispatch } = this.props
|
||||||
router.push('/home')
|
dispatch(push('/home'))
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSwitchTagsButtonClick () {
|
handleSwitchTagsButtonClick () {
|
||||||
const { router } = this.context
|
const { dispatch } = this.props
|
||||||
router.push('/alltags')
|
dispatch(push('/alltags'))
|
||||||
}
|
}
|
||||||
|
|
||||||
onSortEnd (storage) {
|
onSortEnd (storage) {
|
||||||
@@ -270,6 +272,7 @@ class SideNav extends React.Component {
|
|||||||
<div styleName='tagList'>
|
<div styleName='tagList'>
|
||||||
{this.tagListComponent(data)}
|
{this.tagListComponent(data)}
|
||||||
</div>
|
</div>
|
||||||
|
<NavToggleButton isFolded={isFolded} handleToggleButtonClick={this.handleToggleButtonClick.bind(this)} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -282,7 +285,7 @@ class SideNav extends React.Component {
|
|||||||
const { colorPicker } = this.state
|
const { colorPicker } = this.state
|
||||||
const activeTags = this.getActiveTags(location.pathname)
|
const activeTags = this.getActiveTags(location.pathname)
|
||||||
const relatedTags = this.getRelatedTags(activeTags, data.noteMap)
|
const relatedTags = this.getRelatedTags(activeTags, data.noteMap)
|
||||||
let tagList = _.sortBy(data.tagNoteMap.map(
|
let tagList = sortBy(data.tagNoteMap.map(
|
||||||
(tag, name) => ({ name, size: tag.size, related: relatedTags.has(name) })
|
(tag, name) => ({ name, size: tag.size, related: relatedTags.has(name) })
|
||||||
).filter(
|
).filter(
|
||||||
tag => tag.size > 0
|
tag => tag.size > 0
|
||||||
@@ -295,7 +298,7 @@ class SideNav extends React.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (config.sortTagsBy === 'COUNTER') {
|
if (config.sortTagsBy === 'COUNTER') {
|
||||||
tagList = _.sortBy(tagList, item => (0 - item.size))
|
tagList = sortBy(tagList, item => (0 - item.size))
|
||||||
}
|
}
|
||||||
if (config.ui.showOnlyRelatedTags && (relatedTags.size > 0)) {
|
if (config.ui.showOnlyRelatedTags && (relatedTags.size > 0)) {
|
||||||
tagList = tagList.filter(
|
tagList = tagList.filter(
|
||||||
@@ -348,8 +351,8 @@ class SideNav extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleClickTagListItem (name) {
|
handleClickTagListItem (name) {
|
||||||
const { router } = this.context
|
const { dispatch } = this.props
|
||||||
router.push(`/tags/${encodeURIComponent(name)}`)
|
dispatch(push(`/tags/${encodeURIComponent(name)}`))
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSortTagsByChange (e) {
|
handleSortTagsByChange (e) {
|
||||||
@@ -367,8 +370,7 @@ class SideNav extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleClickNarrowToTag (tag) {
|
handleClickNarrowToTag (tag) {
|
||||||
const { router } = this.context
|
const { dispatch, location } = this.props
|
||||||
const { location } = this.props
|
|
||||||
const listOfTags = this.getActiveTags(location.pathname)
|
const listOfTags = this.getActiveTags(location.pathname)
|
||||||
const indexOfTag = listOfTags.indexOf(tag)
|
const indexOfTag = listOfTags.indexOf(tag)
|
||||||
if (indexOfTag > -1) {
|
if (indexOfTag > -1) {
|
||||||
@@ -376,7 +378,7 @@ class SideNav extends React.Component {
|
|||||||
} else {
|
} else {
|
||||||
listOfTags.push(tag)
|
listOfTags.push(tag)
|
||||||
}
|
}
|
||||||
router.push(`/tags/${encodeURIComponent(listOfTags.join(' '))}`)
|
dispatch(push(`/tags/${encodeURIComponent(listOfTags.join(' '))}`))
|
||||||
}
|
}
|
||||||
|
|
||||||
emptyTrash (entries) {
|
emptyTrash (entries) {
|
||||||
@@ -440,7 +442,7 @@ class SideNav extends React.Component {
|
|||||||
|
|
||||||
const style = {}
|
const style = {}
|
||||||
if (!isFolded) style.width = this.props.width
|
if (!isFolded) style.width = this.props.width
|
||||||
const isTagActive = location.pathname.match(/tag/)
|
const isTagActive = /tag/.test(location.pathname)
|
||||||
return (
|
return (
|
||||||
<div className='SideNav'
|
<div className='SideNav'
|
||||||
styleName={isFolded ? 'root--folded' : 'root'}
|
styleName={isFolded ? 'root--folded' : 'root'}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import ee from 'browser/main/lib/eventEmitter'
|
|||||||
import NewNoteButton from 'browser/main/NewNoteButton'
|
import NewNoteButton from 'browser/main/NewNoteButton'
|
||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
import debounce from 'lodash/debounce'
|
import debounce from 'lodash/debounce'
|
||||||
|
import CInput from 'react-composition-input'
|
||||||
|
import { push } from 'connected-react-router'
|
||||||
|
|
||||||
class TopBar extends React.Component {
|
class TopBar extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
@@ -15,26 +17,36 @@ class TopBar extends React.Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
search: '',
|
search: '',
|
||||||
searchOptions: [],
|
searchOptions: [],
|
||||||
isSearching: false,
|
isSearching: false
|
||||||
isAlphabet: false,
|
|
||||||
isIME: false,
|
|
||||||
isConfirmTranslation: false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { dispatch } = this.props
|
||||||
|
|
||||||
this.focusSearchHandler = () => {
|
this.focusSearchHandler = () => {
|
||||||
this.handleOnSearchFocus()
|
this.handleOnSearchFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.codeInitHandler = this.handleCodeInit.bind(this)
|
this.codeInitHandler = this.handleCodeInit.bind(this)
|
||||||
|
this.handleKeyDown = this.handleKeyDown.bind(this)
|
||||||
|
this.handleSearchFocus = this.handleSearchFocus.bind(this)
|
||||||
|
this.handleSearchBlur = this.handleSearchBlur.bind(this)
|
||||||
|
this.handleSearchChange = this.handleSearchChange.bind(this)
|
||||||
|
this.handleSearchClearButton = this.handleSearchClearButton.bind(this)
|
||||||
|
|
||||||
this.updateKeyword = debounce(this.updateKeyword, 1000 / 60, {
|
this.debouncedUpdateKeyword = debounce((keyword) => {
|
||||||
|
dispatch(push(`/searched/${encodeURIComponent(keyword)}`))
|
||||||
|
this.setState({
|
||||||
|
search: keyword
|
||||||
|
})
|
||||||
|
ee.emit('top:search', keyword)
|
||||||
|
}, 1000 / 60, {
|
||||||
maxWait: 1000 / 8
|
maxWait: 1000 / 8
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
const { params } = this.props
|
const { match: { params } } = this.props
|
||||||
const searchWord = params.searchword
|
const searchWord = params && params.searchword
|
||||||
if (searchWord !== undefined) {
|
if (searchWord !== undefined) {
|
||||||
this.setState({
|
this.setState({
|
||||||
search: searchWord,
|
search: searchWord,
|
||||||
@@ -51,22 +63,22 @@ class TopBar extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleSearchClearButton (e) {
|
handleSearchClearButton (e) {
|
||||||
const { router } = this.context
|
const { dispatch } = this.props
|
||||||
this.setState({
|
this.setState({
|
||||||
search: '',
|
search: '',
|
||||||
isSearching: false
|
isSearching: false
|
||||||
})
|
})
|
||||||
this.refs.search.childNodes[0].blur
|
this.refs.search.childNodes[0].blur
|
||||||
router.push('/searched')
|
dispatch(push('/searched'))
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
this.debouncedUpdateKeyword('')
|
||||||
}
|
}
|
||||||
|
|
||||||
handleKeyDown (e) {
|
handleKeyDown (e) {
|
||||||
// reset states
|
// Re-apply search field on ENTER key
|
||||||
this.setState({
|
if (e.keyCode === 13) {
|
||||||
isAlphabet: false,
|
this.debouncedUpdateKeyword(e.target.value)
|
||||||
isIME: false
|
}
|
||||||
})
|
|
||||||
|
|
||||||
// Clear search on ESC
|
// Clear search on ESC
|
||||||
if (e.keyCode === 27) {
|
if (e.keyCode === 27) {
|
||||||
@@ -84,51 +96,11 @@ class TopBar extends React.Component {
|
|||||||
ee.emit('list:prior')
|
ee.emit('list:prior')
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the key is an alphabet, del, enter or ctr
|
|
||||||
if (e.keyCode <= 90 || e.keyCode >= 186 && e.keyCode <= 222) {
|
|
||||||
this.setState({
|
|
||||||
isAlphabet: true
|
|
||||||
})
|
|
||||||
// When the key is an IME input (Japanese, Chinese)
|
|
||||||
} else if (e.keyCode === 229) {
|
|
||||||
this.setState({
|
|
||||||
isIME: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleKeyUp (e) {
|
|
||||||
// reset states
|
|
||||||
this.setState({
|
|
||||||
isConfirmTranslation: false
|
|
||||||
})
|
|
||||||
|
|
||||||
// When the key is translation confirmation (Enter, Space)
|
|
||||||
if (this.state.isIME && (e.keyCode === 32 || e.keyCode === 13)) {
|
|
||||||
this.setState({
|
|
||||||
isConfirmTranslation: true
|
|
||||||
})
|
|
||||||
const keyword = this.refs.searchInput.value
|
|
||||||
this.updateKeyword(keyword)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSearchChange (e) {
|
handleSearchChange (e) {
|
||||||
if (this.state.isAlphabet || this.state.isConfirmTranslation) {
|
const keyword = e.target.value
|
||||||
const keyword = this.refs.searchInput.value
|
this.debouncedUpdateKeyword(keyword)
|
||||||
this.updateKeyword(keyword)
|
|
||||||
} else {
|
|
||||||
e.preventDefault()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateKeyword (keyword) {
|
|
||||||
this.context.router.push(`/searched/${encodeURIComponent(keyword)}`)
|
|
||||||
this.setState({
|
|
||||||
search: keyword
|
|
||||||
})
|
|
||||||
ee.emit('top:search', keyword)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSearchFocus (e) {
|
handleSearchFocus (e) {
|
||||||
@@ -136,6 +108,7 @@ class TopBar extends React.Component {
|
|||||||
isSearching: true
|
isSearching: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSearchBlur (e) {
|
handleSearchBlur (e) {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
|
|
||||||
@@ -165,7 +138,7 @@ class TopBar extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleCodeInit () {
|
handleCodeInit () {
|
||||||
ee.emit('top:search', this.refs.searchInput.value)
|
ee.emit('top:search', this.refs.searchInput.value || '')
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
@@ -178,24 +151,23 @@ class TopBar extends React.Component {
|
|||||||
<div styleName='control'>
|
<div styleName='control'>
|
||||||
<div styleName='control-search'>
|
<div styleName='control-search'>
|
||||||
<div styleName='control-search-input'
|
<div styleName='control-search-input'
|
||||||
onFocus={(e) => this.handleSearchFocus(e)}
|
onFocus={this.handleSearchFocus}
|
||||||
onBlur={(e) => this.handleSearchBlur(e)}
|
onBlur={this.handleSearchBlur}
|
||||||
tabIndex='-1'
|
tabIndex='-1'
|
||||||
ref='search'
|
ref='search'
|
||||||
>
|
>
|
||||||
<input
|
<CInput
|
||||||
ref='searchInput'
|
ref='searchInput'
|
||||||
value={this.state.search}
|
value={this.state.search}
|
||||||
onChange={(e) => this.handleSearchChange(e)}
|
onInputChange={this.handleSearchChange}
|
||||||
onKeyDown={(e) => this.handleKeyDown(e)}
|
onKeyDown={this.handleKeyDown}
|
||||||
onKeyUp={(e) => this.handleKeyUp(e)}
|
|
||||||
placeholder={i18n.__('Search')}
|
placeholder={i18n.__('Search')}
|
||||||
type='text'
|
type='text'
|
||||||
className='searchInput'
|
className='searchInput'
|
||||||
/>
|
/>
|
||||||
{this.state.search !== '' &&
|
{this.state.search !== '' &&
|
||||||
<button styleName='control-search-input-clear'
|
<button styleName='control-search-input-clear'
|
||||||
onClick={(e) => this.handleSearchClearButton(e)}
|
onClick={this.handleSearchClearButton}
|
||||||
>
|
>
|
||||||
<i className='fa fa-fw fa-times' />
|
<i className='fa fa-fw fa-times' />
|
||||||
<span styleName='control-search-input-clear-tooltip'>{i18n.__('Clear Search')}</span>
|
<span styleName='control-search-input-clear-tooltip'>{i18n.__('Clear Search')}</span>
|
||||||
@@ -210,8 +182,8 @@ class TopBar extends React.Component {
|
|||||||
'dispatch',
|
'dispatch',
|
||||||
'data',
|
'data',
|
||||||
'config',
|
'config',
|
||||||
'params',
|
'location',
|
||||||
'location'
|
'match'
|
||||||
])}
|
])}
|
||||||
/>}
|
/>}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import { Provider } from 'react-redux'
|
import { Provider } from 'react-redux'
|
||||||
import Main from './Main'
|
import Main from './Main'
|
||||||
import store from './store'
|
import { store, history } from './store'
|
||||||
import React from 'react'
|
import React, { Fragment } from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
require('!!style!css!stylus?sourceMap!./global.styl')
|
require('!!style!css!stylus?sourceMap!./global.styl')
|
||||||
import { Router, Route, IndexRoute, IndexRedirect, hashHistory } from 'react-router'
|
import { Route, Switch, Redirect } from 'react-router-dom'
|
||||||
import { syncHistoryWithStore } from 'react-router-redux'
|
import { ConnectedRouter } from 'connected-react-router'
|
||||||
|
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'
|
||||||
@@ -77,7 +79,6 @@ document.addEventListener('click', function (e) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const el = document.getElementById('content')
|
const el = document.getElementById('content')
|
||||||
const history = syncHistoryWithStore(hashHistory, store)
|
|
||||||
|
|
||||||
function notify (...args) {
|
function notify (...args) {
|
||||||
return new window.Notification(...args)
|
return new window.Notification(...args)
|
||||||
@@ -98,29 +99,24 @@ function updateApp () {
|
|||||||
|
|
||||||
ReactDOM.render((
|
ReactDOM.render((
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<Router history={history}>
|
<ConnectedRouter history={history}>
|
||||||
<Route path='/' component={Main}>
|
<Fragment>
|
||||||
<IndexRedirect to='/home' />
|
<Switch>
|
||||||
<Route path='home' />
|
<Redirect path='/' to='/home' exact />
|
||||||
<Route path='starred' />
|
<Route path='/(home|alltags|starred|trashed)' component={Main} />
|
||||||
<Route path='searched'>
|
<Route path='/searched' component={Main} exact />
|
||||||
<Route path=':searchword' />
|
<Route path='/searched/:searchword' component={Main} />
|
||||||
</Route>
|
<Redirect path='/tags' to='/alltags' exact />
|
||||||
<Route path='trashed' />
|
<Route path='/tags/:tagname' component={Main} />
|
||||||
<Route path='alltags' />
|
|
||||||
<Route path='tags'>
|
{/* storages */}
|
||||||
<IndexRedirect to='/alltags' />
|
<Redirect path='/storages' to='/home' exact />
|
||||||
<Route path=':tagname' />
|
<Route path='/storages/:storageKey' component={Main} exact />
|
||||||
</Route>
|
<Route path='/storages/:storageKey/folders/:folderKey' component={Main} />
|
||||||
<Route path='storages'>
|
</Switch>
|
||||||
<IndexRedirect to='/home' />
|
<DevTools />
|
||||||
<Route path=':storageKey'>
|
</Fragment>
|
||||||
<IndexRoute />
|
</ConnectedRouter>
|
||||||
<Route path='folders/:folderKey' />
|
|
||||||
</Route>
|
|
||||||
</Route>
|
|
||||||
</Route>
|
|
||||||
</Router>
|
|
||||||
</Provider>
|
</Provider>
|
||||||
), el, function () {
|
), el, function () {
|
||||||
const loadingCover = document.getElementById('loadingCover')
|
const loadingCover = document.getElementById('loadingCover')
|
||||||
|
|||||||
@@ -8,9 +8,14 @@ const win = global.process.platform === 'win32'
|
|||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
const { ipcRenderer } = electron
|
const { ipcRenderer } = electron
|
||||||
const consts = require('browser/lib/consts')
|
const consts = require('browser/lib/consts')
|
||||||
|
const electronConfig = new (require('electron-config'))()
|
||||||
|
|
||||||
let isInitialized = false
|
let isInitialized = false
|
||||||
|
|
||||||
|
const DEFAULT_MARKDOWN_LINT_CONFIG = `{
|
||||||
|
"default": true
|
||||||
|
}`
|
||||||
|
|
||||||
export const DEFAULT_CONFIG = {
|
export const DEFAULT_CONFIG = {
|
||||||
zoom: 1,
|
zoom: 1,
|
||||||
isSideNavFolded: false,
|
isSideNavFolded: false,
|
||||||
@@ -22,11 +27,16 @@ export const DEFAULT_CONFIG = {
|
|||||||
sortTagsBy: 'ALPHABETICAL', // 'ALPHABETICAL', 'COUNTER'
|
sortTagsBy: 'ALPHABETICAL', // 'ALPHABETICAL', 'COUNTER'
|
||||||
listStyle: 'DEFAULT', // 'DEFAULT', 'SMALL'
|
listStyle: 'DEFAULT', // 'DEFAULT', 'SMALL'
|
||||||
amaEnabled: true,
|
amaEnabled: true,
|
||||||
|
autoUpdateEnabled: true,
|
||||||
hotkey: {
|
hotkey: {
|
||||||
toggleMain: OSX ? 'Command + Alt + L' : 'Super + Alt + E',
|
toggleMain: OSX ? 'Command + Alt + L' : 'Super + Alt + E',
|
||||||
toggleMode: OSX ? 'Command + Alt + M' : 'Ctrl + M',
|
toggleMode: OSX ? 'Command + Alt + M' : 'Ctrl + M',
|
||||||
deleteNote: OSX ? 'Command + Shift + Backspace' : 'Ctrl + Shift + Backspace',
|
deleteNote: OSX ? 'Command + Shift + Backspace' : 'Ctrl + Shift + Backspace',
|
||||||
pasteSmartly: OSX ? 'Command + Shift + V' : 'Ctrl + Shift + V',
|
pasteSmartly: OSX ? 'Command + Shift + V' : 'Ctrl + Shift + V',
|
||||||
|
prettifyMarkdown: OSX ? 'Command + Shift + F' : 'Ctrl + Shift + F',
|
||||||
|
sortLines: OSX ? 'Command + Shift + S' : 'Ctrl + Shift + S',
|
||||||
|
insertDate: OSX ? 'Command + /' : 'Ctrl + /',
|
||||||
|
insertDateTime: OSX ? 'Command + Alt + /' : 'Ctrl + Shift + /',
|
||||||
toggleMenuBar: 'Alt'
|
toggleMenuBar: 'Alt'
|
||||||
},
|
},
|
||||||
ui: {
|
ui: {
|
||||||
@@ -44,6 +54,7 @@ export const DEFAULT_CONFIG = {
|
|||||||
fontFamily: win ? 'Consolas' : 'Monaco',
|
fontFamily: win ? 'Consolas' : 'Monaco',
|
||||||
indentType: 'space',
|
indentType: 'space',
|
||||||
indentSize: '2',
|
indentSize: '2',
|
||||||
|
lineWrapping: true,
|
||||||
enableRulers: false,
|
enableRulers: false,
|
||||||
rulers: [80, 120],
|
rulers: [80, 120],
|
||||||
displayLineNumbers: true,
|
displayLineNumbers: true,
|
||||||
@@ -59,7 +70,16 @@ export const DEFAULT_CONFIG = {
|
|||||||
enableFrontMatterTitle: true,
|
enableFrontMatterTitle: true,
|
||||||
frontMatterTitleField: 'title',
|
frontMatterTitleField: 'title',
|
||||||
spellcheck: false,
|
spellcheck: false,
|
||||||
enableSmartPaste: false
|
enableSmartPaste: false,
|
||||||
|
enableMarkdownLint: false,
|
||||||
|
customMarkdownLintConfig: DEFAULT_MARKDOWN_LINT_CONFIG,
|
||||||
|
prettierConfig: ` {
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"tabWidth": 4,
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true
|
||||||
|
}`,
|
||||||
|
deleteUnusedAttachments: true
|
||||||
},
|
},
|
||||||
preview: {
|
preview: {
|
||||||
fontSize: '14',
|
fontSize: '14',
|
||||||
@@ -77,8 +97,10 @@ export const DEFAULT_CONFIG = {
|
|||||||
breaks: true,
|
breaks: true,
|
||||||
smartArrows: false,
|
smartArrows: false,
|
||||||
allowCustomCSS: false,
|
allowCustomCSS: false,
|
||||||
customCSS: '',
|
|
||||||
|
customCSS: '/* Drop Your Custom CSS Code Here */',
|
||||||
sanitize: 'STRICT', // 'STRICT', 'ALLOW_STYLES', 'NONE'
|
sanitize: 'STRICT', // 'STRICT', 'ALLOW_STYLES', 'NONE'
|
||||||
|
mermaidHTMLLabel: false,
|
||||||
lineThroughCheckbox: true
|
lineThroughCheckbox: true
|
||||||
},
|
},
|
||||||
blog: {
|
blog: {
|
||||||
@@ -102,7 +124,6 @@ function validate (config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _save (config) {
|
function _save (config) {
|
||||||
console.log(config)
|
|
||||||
window.localStorage.setItem('config', JSON.stringify(config))
|
window.localStorage.setItem('config', JSON.stringify(config))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,6 +143,8 @@ function get () {
|
|||||||
_save(config)
|
_save(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config.autoUpdateEnabled = electronConfig.get('autoUpdateEnabled', config.autoUpdateEnabled)
|
||||||
|
|
||||||
if (!isInitialized) {
|
if (!isInitialized) {
|
||||||
isInitialized = true
|
isInitialized = true
|
||||||
let editorTheme = document.getElementById('editorTheme')
|
let editorTheme = document.getElementById('editorTheme')
|
||||||
@@ -135,7 +158,7 @@ function get () {
|
|||||||
const theme = consts.THEMES.find(theme => theme.name === config.editor.theme)
|
const theme = consts.THEMES.find(theme => theme.name === config.editor.theme)
|
||||||
|
|
||||||
if (theme) {
|
if (theme) {
|
||||||
editorTheme.setAttribute('href', `../${theme.path}`)
|
editorTheme.setAttribute('href', theme.path)
|
||||||
} else {
|
} else {
|
||||||
config.editor.theme = 'default'
|
config.editor.theme = 'default'
|
||||||
}
|
}
|
||||||
@@ -146,7 +169,13 @@ function get () {
|
|||||||
|
|
||||||
function set (updates) {
|
function set (updates) {
|
||||||
const currentConfig = get()
|
const currentConfig = get()
|
||||||
const newConfig = Object.assign({}, DEFAULT_CONFIG, currentConfig, updates)
|
|
||||||
|
const arrangedUpdates = updates
|
||||||
|
if (updates.preview !== undefined && updates.preview.customCSS === '') {
|
||||||
|
arrangedUpdates.preview.customCSS = DEFAULT_CONFIG.preview.customCSS
|
||||||
|
}
|
||||||
|
|
||||||
|
const newConfig = Object.assign({}, DEFAULT_CONFIG, currentConfig, arrangedUpdates)
|
||||||
if (!validate(newConfig)) throw new Error('INVALID CONFIG')
|
if (!validate(newConfig)) throw new Error('INVALID CONFIG')
|
||||||
_save(newConfig)
|
_save(newConfig)
|
||||||
|
|
||||||
@@ -177,9 +206,11 @@ function set (updates) {
|
|||||||
const newTheme = consts.THEMES.find(theme => theme.name === newConfig.editor.theme)
|
const newTheme = consts.THEMES.find(theme => theme.name === newConfig.editor.theme)
|
||||||
|
|
||||||
if (newTheme) {
|
if (newTheme) {
|
||||||
editorTheme.setAttribute('href', `../${newTheme.path}`)
|
editorTheme.setAttribute('href', newTheme.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
electronConfig.set('autoUpdateEnabled', newConfig.autoUpdateEnabled)
|
||||||
|
|
||||||
ipcRenderer.send('config-renew', {
|
ipcRenderer.send('config-renew', {
|
||||||
config: get()
|
config: get()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ const escapeStringRegexp = require('escape-string-regexp')
|
|||||||
const sander = require('sander')
|
const sander = require('sander')
|
||||||
const url = require('url')
|
const url = require('url')
|
||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
|
import { isString } from 'lodash'
|
||||||
|
|
||||||
const STORAGE_FOLDER_PLACEHOLDER = ':storage'
|
const STORAGE_FOLDER_PLACEHOLDER = ':storage'
|
||||||
const DESTINATION_FOLDER = 'attachments'
|
const DESTINATION_FOLDER = 'attachments'
|
||||||
@@ -19,7 +20,7 @@ const PATH_SEPARATORS = escapeStringRegexp(path.posix.sep) + escapeStringRegexp(
|
|||||||
* @returns {Promise<Image>} Image element created
|
* @returns {Promise<Image>} Image element created
|
||||||
*/
|
*/
|
||||||
function getImage (file) {
|
function getImage (file) {
|
||||||
if (_.isString(file)) {
|
if (isString(file)) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const img = new Image()
|
const img = new Image()
|
||||||
img.onload = () => resolve(img)
|
img.onload = () => resolve(img)
|
||||||
@@ -241,6 +242,10 @@ function migrateAttachments (markdownContent, storagePath, noteKey) {
|
|||||||
* @returns {String} postprocessed HTML in which all :storage references are mapped to the actual paths.
|
* @returns {String} postprocessed HTML in which all :storage references are mapped to the actual paths.
|
||||||
*/
|
*/
|
||||||
function fixLocalURLS (renderedHTML, storagePath) {
|
function fixLocalURLS (renderedHTML, storagePath) {
|
||||||
|
const encodedWin32SeparatorRegex = /%5C/g
|
||||||
|
const storageRegex = new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER, 'g')
|
||||||
|
const storageUrl = 'file:///' + path.join(storagePath, DESTINATION_FOLDER).replace(/\\/g, '/')
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A :storage reference is like `:storage/3b6f8bd6-4edd-4b15-96e0-eadc4475b564/f939b2c3.jpg`.
|
A :storage reference is like `:storage/3b6f8bd6-4edd-4b15-96e0-eadc4475b564/f939b2c3.jpg`.
|
||||||
|
|
||||||
@@ -250,8 +255,7 @@ function fixLocalURLS (renderedHTML, storagePath) {
|
|||||||
- `(?:\\\/|%5C)` match the path seperator. `\\\/` for posix systems and `%5C` for windows.
|
- `(?:\\\/|%5C)` match the path seperator. `\\\/` for posix systems and `%5C` for windows.
|
||||||
*/
|
*/
|
||||||
return renderedHTML.replace(new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER + '(?:(?:\\\/|%5C)[-.\\w]+)+', 'g'), function (match) {
|
return renderedHTML.replace(new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER + '(?:(?:\\\/|%5C)[-.\\w]+)+', 'g'), function (match) {
|
||||||
var encodedPathSeparators = new RegExp(mdurl.encode(path.win32.sep) + '|' + mdurl.encode(path.posix.sep), 'g')
|
return match.replace(encodedWin32SeparatorRegex, '/').replace(storageRegex, storageUrl)
|
||||||
return match.replace(encodedPathSeparators, path.sep).replace(new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER, 'g'), 'file:///' + path.join(storagePath, DESTINATION_FOLDER))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -617,11 +621,79 @@ function deleteAttachmentsNotPresentInNote (markdownContent, storageKey, noteKey
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
} else {
|
|
||||||
console.info('Attachment folder ("' + attachmentFolder + '") did not exist..')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Get all existing attachments related to a specific note
|
||||||
|
including their status (in use or not) and their path. Return null if there're no attachment related to note or specified parametters are invalid
|
||||||
|
* @param markdownContent markdownContent of the current note
|
||||||
|
* @param storageKey StorageKey of the current note
|
||||||
|
* @param noteKey NoteKey of the currentNote
|
||||||
|
* @return {Promise<Array<{path: String, isInUse: bool}>>} Promise returning the
|
||||||
|
list of attachments with their properties */
|
||||||
|
function getAttachmentsPathAndStatus (markdownContent, storageKey, noteKey) {
|
||||||
|
if (storageKey == null || noteKey == null || markdownContent == null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const targetStorage = findStorage.findStorage(storageKey)
|
||||||
|
const attachmentFolder = path.join(targetStorage.path, DESTINATION_FOLDER, noteKey)
|
||||||
|
const attachmentsInNote = getAttachmentsInMarkdownContent(markdownContent)
|
||||||
|
const attachmentsInNoteOnlyFileNames = []
|
||||||
|
if (attachmentsInNote) {
|
||||||
|
for (let i = 0; i < attachmentsInNote.length; i++) {
|
||||||
|
attachmentsInNoteOnlyFileNames.push(attachmentsInNote[i].replace(new RegExp(STORAGE_FOLDER_PLACEHOLDER + escapeStringRegexp(path.sep) + noteKey + escapeStringRegexp(path.sep), 'g'), ''))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fs.existsSync(attachmentFolder)) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
fs.readdir(attachmentFolder, (err, files) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Error reading directory "' + attachmentFolder + '". Error:')
|
||||||
|
console.error(err)
|
||||||
|
reject(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const attachments = []
|
||||||
|
for (const file of files) {
|
||||||
|
const absolutePathOfFile = path.join(targetStorage.path, DESTINATION_FOLDER, noteKey, file)
|
||||||
|
if (!attachmentsInNoteOnlyFileNames.includes(file)) {
|
||||||
|
attachments.push({ path: absolutePathOfFile, isInUse: false })
|
||||||
|
} else {
|
||||||
|
attachments.push({ path: absolutePathOfFile, isInUse: true })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolve(attachments)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Remove all specified attachment paths
|
||||||
|
* @param attachments attachment paths
|
||||||
|
* @return {Promise} Promise after all attachments are removed */
|
||||||
|
function removeAttachmentsByPaths (attachments) {
|
||||||
|
const promises = []
|
||||||
|
for (const attachment of attachments) {
|
||||||
|
const promise = new Promise((resolve, reject) => {
|
||||||
|
fs.unlink(attachment, (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Could not delete "%s"', attachment)
|
||||||
|
console.error(err)
|
||||||
|
reject(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
promises.push(promise)
|
||||||
|
}
|
||||||
|
return Promise.all(promises)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clones the attachments of a given note.
|
* Clones the attachments of a given note.
|
||||||
* Copies the attachments to their new destination and updates the content of the new note so that the attachment-links again point to the correct destination.
|
* Copies the attachments to their new destination and updates the content of the new note so that the attachment-links again point to the correct destination.
|
||||||
@@ -724,8 +796,10 @@ module.exports = {
|
|||||||
getAbsolutePathsOfAttachmentsInContent,
|
getAbsolutePathsOfAttachmentsInContent,
|
||||||
importAttachments,
|
importAttachments,
|
||||||
removeStorageAndNoteReferences,
|
removeStorageAndNoteReferences,
|
||||||
|
removeAttachmentsByPaths,
|
||||||
deleteAttachmentFolder,
|
deleteAttachmentFolder,
|
||||||
deleteAttachmentsNotPresentInNote,
|
deleteAttachmentsNotPresentInNote,
|
||||||
|
getAttachmentsPathAndStatus,
|
||||||
moveAttachments,
|
moveAttachments,
|
||||||
cloneAttachments,
|
cloneAttachments,
|
||||||
isAttachmentLink,
|
isAttachmentLink,
|
||||||
|
|||||||
86
browser/main/lib/dataApi/createNoteFromUrl.js
Normal file
86
browser/main/lib/dataApi/createNoteFromUrl.js
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
const http = require('http')
|
||||||
|
const https = require('https')
|
||||||
|
const { createTurndownService } = require('../../../lib/turndown')
|
||||||
|
const createNote = require('./createNote')
|
||||||
|
|
||||||
|
import { push } from 'connected-react-router'
|
||||||
|
import ee from 'browser/main/lib/eventEmitter'
|
||||||
|
|
||||||
|
function validateUrl (str) {
|
||||||
|
if (/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(str)) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ERROR_MESSAGES = {
|
||||||
|
ENOTFOUND: 'URL not found. Please check the URL, or your internet connection and try again.',
|
||||||
|
VALIDATION_ERROR: 'Please check if the URL follows this format: https://www.google.com',
|
||||||
|
UNEXPECTED: 'Unexpected error! Please check console for details!'
|
||||||
|
}
|
||||||
|
|
||||||
|
function createNoteFromUrl (url, storage, folder, dispatch = null, location = null) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const td = createTurndownService()
|
||||||
|
|
||||||
|
if (!validateUrl(url)) {
|
||||||
|
reject({result: false, error: ERROR_MESSAGES.VALIDATION_ERROR})
|
||||||
|
}
|
||||||
|
|
||||||
|
const request = url.startsWith('https') ? https : http
|
||||||
|
|
||||||
|
const req = request.request(url, (res) => {
|
||||||
|
let data = ''
|
||||||
|
|
||||||
|
res.on('data', (chunk) => {
|
||||||
|
data += chunk
|
||||||
|
})
|
||||||
|
|
||||||
|
res.on('end', () => {
|
||||||
|
const markdownHTML = td.turndown(data)
|
||||||
|
|
||||||
|
if (dispatch !== null) {
|
||||||
|
createNote(storage, {
|
||||||
|
type: 'MARKDOWN_NOTE',
|
||||||
|
folder: folder,
|
||||||
|
title: '',
|
||||||
|
content: markdownHTML
|
||||||
|
})
|
||||||
|
.then((note) => {
|
||||||
|
const noteHash = note.key
|
||||||
|
dispatch({
|
||||||
|
type: 'UPDATE_NOTE',
|
||||||
|
note: note
|
||||||
|
})
|
||||||
|
dispatch(push({
|
||||||
|
pathname: location.pathname,
|
||||||
|
query: {key: noteHash}
|
||||||
|
}))
|
||||||
|
ee.emit('list:jump', noteHash)
|
||||||
|
ee.emit('detail:focus')
|
||||||
|
resolve({result: true, error: null})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
createNote(storage, {
|
||||||
|
type: 'MARKDOWN_NOTE',
|
||||||
|
folder: folder,
|
||||||
|
title: '',
|
||||||
|
content: markdownHTML
|
||||||
|
}).then((note) => {
|
||||||
|
resolve({result: true, note, error: null})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
req.on('error', (e) => {
|
||||||
|
console.error('error in parsing URL', e)
|
||||||
|
reject({result: false, error: ERROR_MESSAGES[e.code] || ERROR_MESSAGES.UNEXPECTED})
|
||||||
|
})
|
||||||
|
|
||||||
|
req.end()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = createNoteFromUrl
|
||||||
@@ -3,7 +3,6 @@ const path = require('path')
|
|||||||
const resolveStorageData = require('./resolveStorageData')
|
const resolveStorageData = require('./resolveStorageData')
|
||||||
const resolveStorageNotes = require('./resolveStorageNotes')
|
const resolveStorageNotes = require('./resolveStorageNotes')
|
||||||
const CSON = require('@rokt33r/season')
|
const CSON = require('@rokt33r/season')
|
||||||
const sander = require('sander')
|
|
||||||
const { findStorage } = require('browser/lib/findStorage')
|
const { findStorage } = require('browser/lib/findStorage')
|
||||||
const deleteSingleNote = require('./deleteNote')
|
const deleteSingleNote = require('./deleteNote')
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ function exportNote (nodeKey, storageKey, noteContent, targetPath, outputFormatt
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (outputFormatter) {
|
if (outputFormatter) {
|
||||||
exportedData = outputFormatter(exportedData, exportTasks, path.dirname(targetPath))
|
exportedData = outputFormatter(exportedData, exportTasks, targetPath)
|
||||||
} else {
|
} else {
|
||||||
exportedData = Promise.resolve(exportedData)
|
exportedData = Promise.resolve(exportedData)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ const dataApi = {
|
|||||||
exportFolder: require('./exportFolder'),
|
exportFolder: require('./exportFolder'),
|
||||||
exportStorage: require('./exportStorage'),
|
exportStorage: require('./exportStorage'),
|
||||||
createNote: require('./createNote'),
|
createNote: require('./createNote'),
|
||||||
|
createNoteFromUrl: require('./createNoteFromUrl'),
|
||||||
updateNote: require('./updateNote'),
|
updateNote: require('./updateNote'),
|
||||||
deleteNote: require('./deleteNote'),
|
deleteNote: require('./deleteNote'),
|
||||||
moveNote: require('./moveNote'),
|
moveNote: require('./moveNote'),
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
const resolveStorageData = require('./resolveStorageData')
|
const resolveStorageData = require('./resolveStorageData')
|
||||||
const _ = require('lodash')
|
const _ = require('lodash')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const fs = require('fs')
|
|
||||||
const CSON = require('@rokt33r/season')
|
const CSON = require('@rokt33r/season')
|
||||||
const keygen = require('browser/lib/keygen')
|
const keygen = require('browser/lib/keygen')
|
||||||
const sander = require('sander')
|
const sander = require('sander')
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Provider } from 'react-redux'
|
import { Provider } from 'react-redux'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import store from '../store'
|
import { store } from '../store'
|
||||||
|
|
||||||
class ModalBase extends React.Component {
|
class ModalBase extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from 'react'
|
|||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './CreateFolderModal.styl'
|
import styles from './CreateFolderModal.styl'
|
||||||
import dataApi from 'browser/main/lib/dataApi'
|
import dataApi from 'browser/main/lib/dataApi'
|
||||||
import store from 'browser/main/store'
|
import { store } from 'browser/main/store'
|
||||||
import consts from 'browser/lib/consts'
|
import consts from 'browser/lib/consts'
|
||||||
import ModalEscButton from 'browser/components/ModalEscButton'
|
import ModalEscButton from 'browser/components/ModalEscButton'
|
||||||
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
||||||
|
|||||||
118
browser/main/modals/CreateMarkdownFromURLModal.js
Normal file
118
browser/main/modals/CreateMarkdownFromURLModal.js
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import React from 'react'
|
||||||
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
|
import styles from './CreateMarkdownFromURLModal.styl'
|
||||||
|
import dataApi from 'browser/main/lib/dataApi'
|
||||||
|
import ModalEscButton from 'browser/components/ModalEscButton'
|
||||||
|
import i18n from 'browser/lib/i18n'
|
||||||
|
|
||||||
|
class CreateMarkdownFromURLModal extends React.Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
name: '',
|
||||||
|
showerror: false,
|
||||||
|
errormessage: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount () {
|
||||||
|
this.refs.name.focus()
|
||||||
|
this.refs.name.select()
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCloseButtonClick (e) {
|
||||||
|
this.props.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange (e) {
|
||||||
|
this.setState({
|
||||||
|
name: this.refs.name.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
handleKeyDown (e) {
|
||||||
|
if (e.keyCode === 27) {
|
||||||
|
this.props.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleInputKeyDown (e) {
|
||||||
|
switch (e.keyCode) {
|
||||||
|
case 13:
|
||||||
|
this.confirm()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleConfirmButtonClick (e) {
|
||||||
|
this.confirm()
|
||||||
|
}
|
||||||
|
|
||||||
|
showError (message) {
|
||||||
|
this.setState({
|
||||||
|
showerror: true,
|
||||||
|
errormessage: message
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
hideError () {
|
||||||
|
this.setState({
|
||||||
|
showerror: false,
|
||||||
|
errormessage: ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
confirm () {
|
||||||
|
this.hideError()
|
||||||
|
const { storage, folder, dispatch, location } = this.props
|
||||||
|
|
||||||
|
dataApi.createNoteFromUrl(this.state.name, storage, folder, dispatch, location).then((result) => {
|
||||||
|
this.props.close()
|
||||||
|
}).catch((result) => {
|
||||||
|
this.showError(result.error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
return (
|
||||||
|
<div styleName='root'
|
||||||
|
tabIndex='-1'
|
||||||
|
onKeyDown={(e) => this.handleKeyDown(e)}
|
||||||
|
>
|
||||||
|
<div styleName='header'>
|
||||||
|
<div styleName='title'>{i18n.__('Import Markdown From URL')}</div>
|
||||||
|
</div>
|
||||||
|
<ModalEscButton handleEscButtonClick={(e) => this.handleCloseButtonClick(e)} />
|
||||||
|
<div styleName='control'>
|
||||||
|
<div styleName='control-folder'>
|
||||||
|
<div styleName='control-folder-label'>{i18n.__('Insert URL Here')}</div>
|
||||||
|
<input styleName='control-folder-input'
|
||||||
|
ref='name'
|
||||||
|
value={this.state.name}
|
||||||
|
onChange={(e) => this.handleChange(e)}
|
||||||
|
onKeyDown={(e) => this.handleInputKeyDown(e)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button styleName='control-confirmButton'
|
||||||
|
onClick={(e) => this.handleConfirmButtonClick(e)}
|
||||||
|
>
|
||||||
|
{i18n.__('Import')}
|
||||||
|
</button>
|
||||||
|
<div className='error' styleName='error'>{this.state.errormessage}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateMarkdownFromURLModal.propTypes = {
|
||||||
|
storage: PropTypes.string,
|
||||||
|
folder: PropTypes.string,
|
||||||
|
dispatch: PropTypes.func,
|
||||||
|
location: PropTypes.shape({
|
||||||
|
pathname: PropTypes.string
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CSSModules(CreateMarkdownFromURLModal, styles)
|
||||||
160
browser/main/modals/CreateMarkdownFromURLModal.styl
Normal file
160
browser/main/modals/CreateMarkdownFromURLModal.styl
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
.root
|
||||||
|
modal()
|
||||||
|
width 500px
|
||||||
|
height 270px
|
||||||
|
overflow hidden
|
||||||
|
position relative
|
||||||
|
|
||||||
|
.header
|
||||||
|
height 80px
|
||||||
|
margin-bottom 10px
|
||||||
|
margin-top 20px
|
||||||
|
font-size 18px
|
||||||
|
line-height 50px
|
||||||
|
background-color $ui-backgroundColor
|
||||||
|
color $ui-text-color
|
||||||
|
|
||||||
|
.title
|
||||||
|
font-size 36px
|
||||||
|
font-weight 600
|
||||||
|
|
||||||
|
.control-folder-label
|
||||||
|
text-align left
|
||||||
|
font-size 14px
|
||||||
|
color $ui-text-color
|
||||||
|
|
||||||
|
.control-folder-input
|
||||||
|
display block
|
||||||
|
height 40px
|
||||||
|
width 490px
|
||||||
|
padding 0 5px
|
||||||
|
margin 10px 0
|
||||||
|
border 1px solid $ui-input--create-folder-modal
|
||||||
|
border-radius 2px
|
||||||
|
background-color transparent
|
||||||
|
outline none
|
||||||
|
vertical-align middle
|
||||||
|
font-size 16px
|
||||||
|
&:disabled
|
||||||
|
background-color $ui-input--disabled-backgroundColor
|
||||||
|
&:focus, &:active
|
||||||
|
border-color $ui-active-color
|
||||||
|
|
||||||
|
.control-confirmButton
|
||||||
|
display block
|
||||||
|
height 35px
|
||||||
|
width 140px
|
||||||
|
border none
|
||||||
|
border-radius 2px
|
||||||
|
padding 0 25px
|
||||||
|
margin 20px auto
|
||||||
|
font-size 14px
|
||||||
|
colorPrimaryButton()
|
||||||
|
|
||||||
|
body[data-theme="dark"]
|
||||||
|
.root
|
||||||
|
modalDark()
|
||||||
|
width 500px
|
||||||
|
height 270px
|
||||||
|
overflow hidden
|
||||||
|
position relative
|
||||||
|
|
||||||
|
.header
|
||||||
|
background-color transparent
|
||||||
|
border-color $ui-dark-borderColor
|
||||||
|
color $ui-dark-text-color
|
||||||
|
|
||||||
|
.control-folder-label
|
||||||
|
color $ui-dark-text-color
|
||||||
|
|
||||||
|
.control-folder-input
|
||||||
|
border 1px solid $ui-input--create-folder-modal
|
||||||
|
color white
|
||||||
|
|
||||||
|
.description
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
|
.control-confirmButton
|
||||||
|
colorDarkPrimaryButton()
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root
|
||||||
|
modalSolarizedDark()
|
||||||
|
width 500px
|
||||||
|
height 270px
|
||||||
|
overflow hidden
|
||||||
|
position relative
|
||||||
|
|
||||||
|
.header
|
||||||
|
background-color transparent
|
||||||
|
border-color $ui-dark-borderColor
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.control-folder-label
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.control-folder-input
|
||||||
|
border 1px solid $ui-input--create-folder-modal
|
||||||
|
color white
|
||||||
|
|
||||||
|
.description
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
|
.control-confirmButton
|
||||||
|
colorSolarizedDarkPrimaryButton()
|
||||||
|
|
||||||
|
.error
|
||||||
|
text-align center
|
||||||
|
color #F44336
|
||||||
|
|
||||||
|
body[data-theme="monokai"]
|
||||||
|
.root
|
||||||
|
modalMonokai()
|
||||||
|
width 500px
|
||||||
|
height 270px
|
||||||
|
overflow hidden
|
||||||
|
position relative
|
||||||
|
|
||||||
|
.header
|
||||||
|
background-color transparent
|
||||||
|
border-color $ui-dark-borderColor
|
||||||
|
color $ui-monokai-text-color
|
||||||
|
|
||||||
|
.control-folder-label
|
||||||
|
color $ui-monokai-text-color
|
||||||
|
|
||||||
|
.control-folder-input
|
||||||
|
border 1px solid $ui-input--create-folder-modal
|
||||||
|
color white
|
||||||
|
|
||||||
|
.description
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
|
.control-confirmButton
|
||||||
|
colorMonokaiPrimaryButton()
|
||||||
|
|
||||||
|
body[data-theme="dracula"]
|
||||||
|
.root
|
||||||
|
modalDracula()
|
||||||
|
width 500px
|
||||||
|
height 270px
|
||||||
|
overflow hidden
|
||||||
|
position relative
|
||||||
|
|
||||||
|
.header
|
||||||
|
background-color transparent
|
||||||
|
border-color $ui-dracula-borderColor
|
||||||
|
color $ui-dracula-text-color
|
||||||
|
|
||||||
|
.control-folder-label
|
||||||
|
color $ui-dracula-text-color
|
||||||
|
|
||||||
|
.control-folder-input
|
||||||
|
border 1px solid $ui-input--create-folder-modal
|
||||||
|
color white
|
||||||
|
|
||||||
|
.description
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
|
.control-confirmButton
|
||||||
|
colorDraculaPrimaryButton()
|
||||||
@@ -3,7 +3,10 @@ import CSSModules from 'browser/lib/CSSModules'
|
|||||||
import styles from './NewNoteModal.styl'
|
import styles from './NewNoteModal.styl'
|
||||||
import ModalEscButton from 'browser/components/ModalEscButton'
|
import ModalEscButton from 'browser/components/ModalEscButton'
|
||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
|
import { openModal } from 'browser/main/lib/modal'
|
||||||
|
import CreateMarkdownFromURLModal from '../modals/CreateMarkdownFromURLModal'
|
||||||
import { createMarkdownNote, createSnippetNote } from 'browser/lib/newNote'
|
import { createMarkdownNote, createSnippetNote } from 'browser/lib/newNote'
|
||||||
|
import queryString from 'query-string'
|
||||||
|
|
||||||
class NewNoteModal extends React.Component {
|
class NewNoteModal extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
@@ -20,8 +23,21 @@ class NewNoteModal extends React.Component {
|
|||||||
this.props.close()
|
this.props.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleCreateMarkdownFromUrlClick (e) {
|
||||||
|
this.props.close()
|
||||||
|
|
||||||
|
const { storage, folder, dispatch, location } = this.props
|
||||||
|
openModal(CreateMarkdownFromURLModal, {
|
||||||
|
storage: storage,
|
||||||
|
folder: folder,
|
||||||
|
dispatch,
|
||||||
|
location
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
handleMarkdownNoteButtonClick (e) {
|
handleMarkdownNoteButtonClick (e) {
|
||||||
const { storage, folder, dispatch, location, params, config } = this.props
|
const { storage, folder, dispatch, location, config } = this.props
|
||||||
|
const params = location.search !== '' && queryString.parse(location.search)
|
||||||
if (!this.lock) {
|
if (!this.lock) {
|
||||||
this.lock = true
|
this.lock = true
|
||||||
createMarkdownNote(storage, folder, dispatch, location, params, config).then(() => {
|
createMarkdownNote(storage, folder, dispatch, location, params, config).then(() => {
|
||||||
@@ -38,7 +54,8 @@ class NewNoteModal extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleSnippetNoteButtonClick (e) {
|
handleSnippetNoteButtonClick (e) {
|
||||||
const { storage, folder, dispatch, location, params, config } = this.props
|
const { storage, folder, dispatch, location, config } = this.props
|
||||||
|
const params = location.search !== '' && queryString.parse(location.search)
|
||||||
if (!this.lock) {
|
if (!this.lock) {
|
||||||
this.lock = true
|
this.lock = true
|
||||||
createSnippetNote(storage, folder, dispatch, location, params, config).then(() => {
|
createSnippetNote(storage, folder, dispatch, location, params, config).then(() => {
|
||||||
@@ -112,10 +129,8 @@ class NewNoteModal extends React.Component {
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div styleName='description'>
|
<div styleName='description'><i className='fa fa-arrows-h' />{i18n.__('Tab to switch format')}</div>
|
||||||
<i className='fa fa-arrows-h' />{i18n.__('Tab to switch format')}
|
<div styleName='from-url' onClick={(e) => this.handleCreateMarkdownFromUrlClick(e)}>Or, create a new markdown note from a URL</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
.control
|
.control
|
||||||
padding 25px 0px
|
padding 25px 0px
|
||||||
text-align center
|
text-align center
|
||||||
|
display: flex
|
||||||
|
|
||||||
.control-button
|
.control-button
|
||||||
width 240px
|
width 240px
|
||||||
@@ -47,6 +48,12 @@
|
|||||||
text-align center
|
text-align center
|
||||||
margin-bottom 25px
|
margin-bottom 25px
|
||||||
|
|
||||||
|
.from-url
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
text-align center
|
||||||
|
margin-bottom 25px
|
||||||
|
cursor pointer
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.root
|
.root
|
||||||
modalDark()
|
modalDark()
|
||||||
@@ -61,7 +68,7 @@ body[data-theme="dark"]
|
|||||||
&:focus
|
&:focus
|
||||||
colorDarkPrimaryButton()
|
colorDarkPrimaryButton()
|
||||||
|
|
||||||
.description
|
.description, .from-url
|
||||||
color $ui-inactive-text-color
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
body[data-theme="solarized-dark"]
|
body[data-theme="solarized-dark"]
|
||||||
@@ -78,7 +85,7 @@ body[data-theme="solarized-dark"]
|
|||||||
&:focus
|
&:focus
|
||||||
colorDarkPrimaryButton()
|
colorDarkPrimaryButton()
|
||||||
|
|
||||||
.description
|
.description, .from-url
|
||||||
color $ui-solarized-dark-text-color
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
body[data-theme="monokai"]
|
body[data-theme="monokai"]
|
||||||
@@ -95,7 +102,7 @@ body[data-theme="monokai"]
|
|||||||
&:focus
|
&:focus
|
||||||
colorDarkPrimaryButton()
|
colorDarkPrimaryButton()
|
||||||
|
|
||||||
.description
|
.description, .from-url
|
||||||
color $ui-monokai-text-color
|
color $ui-monokai-text-color
|
||||||
|
|
||||||
body[data-theme="dracula"]
|
body[data-theme="dracula"]
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React from 'react'
|
|||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './ConfigTab.styl'
|
import styles from './ConfigTab.styl'
|
||||||
import ConfigManager from 'browser/main/lib/ConfigManager'
|
import ConfigManager from 'browser/main/lib/ConfigManager'
|
||||||
import store from 'browser/main/store'
|
import { store } from 'browser/main/store'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import CSSModules from 'browser/lib/CSSModules'
|
|||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import styles from './FolderItem.styl'
|
import styles from './FolderItem.styl'
|
||||||
import dataApi from 'browser/main/lib/dataApi'
|
import dataApi from 'browser/main/lib/dataApi'
|
||||||
import store from 'browser/main/store'
|
import { store } from 'browser/main/store'
|
||||||
import { SketchPicker } from 'react-color'
|
import { SketchPicker } from 'react-color'
|
||||||
import { SortableElement, SortableHandle } from 'react-sortable-hoc'
|
import { SortableElement, SortableHandle } from 'react-sortable-hoc'
|
||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
@@ -225,7 +225,7 @@ class FolderItem extends React.Component {
|
|||||||
<div styleName='folderItem-left'
|
<div styleName='folderItem-left'
|
||||||
style={{borderColor: folder.color}}
|
style={{borderColor: folder.color}}
|
||||||
>
|
>
|
||||||
<span styleName='folderItem-left-name'>{folder.name}</span>
|
<span>{folder.name}</span>
|
||||||
<span styleName='folderItem-left-key'>({folder.key})</span>
|
<span styleName='folderItem-left-key'>({folder.key})</span>
|
||||||
</div>
|
</div>
|
||||||
<div styleName='folderItem-right'>
|
<div styleName='folderItem-right'>
|
||||||
@@ -288,10 +288,10 @@ class Handle extends React.Component {
|
|||||||
|
|
||||||
class SortableFolderItemComponent extends React.Component {
|
class SortableFolderItemComponent extends React.Component {
|
||||||
render () {
|
render () {
|
||||||
const StyledHandle = CSSModules(Handle, this.props.styles)
|
const StyledHandle = CSSModules(Handle, styles)
|
||||||
const DragHandle = SortableHandle(StyledHandle)
|
const DragHandle = SortableHandle(StyledHandle)
|
||||||
|
|
||||||
const StyledFolderItem = CSSModules(FolderItem, this.props.styles)
|
const StyledFolderItem = CSSModules(FolderItem, styles)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from 'react'
|
|||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
import dataApi from 'browser/main/lib/dataApi'
|
import dataApi from 'browser/main/lib/dataApi'
|
||||||
import styles from './FolderList.styl'
|
import styles from './FolderList.styl'
|
||||||
import store from 'browser/main/store'
|
import { store } from 'browser/main/store'
|
||||||
import FolderItem from './FolderItem'
|
import FolderItem from './FolderItem'
|
||||||
import { SortableContainer } from 'react-sortable-hoc'
|
import { SortableContainer } from 'react-sortable-hoc'
|
||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
@@ -22,7 +22,7 @@ class FolderList extends React.Component {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div styleName='folderList'>
|
<div>
|
||||||
{folderList.length > 0
|
{folderList.length > 0
|
||||||
? folderList
|
? folderList
|
||||||
: <div styleName='folderList-empty'>{i18n.__('No Folders')}</div>
|
: <div styleName='folderList-empty'>{i18n.__('No Folders')}</div>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from 'react'
|
|||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './ConfigTab.styl'
|
import styles from './ConfigTab.styl'
|
||||||
import ConfigManager from 'browser/main/lib/ConfigManager'
|
import ConfigManager from 'browser/main/lib/ConfigManager'
|
||||||
import store from 'browser/main/store'
|
import { store } from 'browser/main/store'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
|
|
||||||
@@ -76,13 +76,16 @@ class HotkeyTab extends React.Component {
|
|||||||
|
|
||||||
handleHotkeyChange (e) {
|
handleHotkeyChange (e) {
|
||||||
const { config } = this.state
|
const { config } = this.state
|
||||||
config.hotkey = {
|
config.hotkey = Object.assign({}, config.hotkey, {
|
||||||
toggleMain: this.refs.toggleMain.value,
|
toggleMain: this.refs.toggleMain.value,
|
||||||
toggleMode: this.refs.toggleMode.value,
|
toggleMode: this.refs.toggleMode.value,
|
||||||
deleteNote: this.refs.deleteNote.value,
|
deleteNote: this.refs.deleteNote.value,
|
||||||
pasteSmartly: this.refs.pasteSmartly.value,
|
pasteSmartly: this.refs.pasteSmartly.value,
|
||||||
toggleMenuBar: this.refs.toggleMenuBar.value
|
prettifyMarkdown: this.refs.prettifyMarkdown.value,
|
||||||
}
|
toggleMenuBar: this.refs.toggleMenuBar.value,
|
||||||
|
insertDate: this.refs.insertDate.value,
|
||||||
|
insertDateTime: this.refs.insertDateTime.value
|
||||||
|
})
|
||||||
this.setState({
|
this.setState({
|
||||||
config
|
config
|
||||||
})
|
})
|
||||||
@@ -173,6 +176,38 @@ class HotkeyTab extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div styleName='group-section'>
|
||||||
|
<div styleName='group-section-label'>{i18n.__('Prettify Markdown')}</div>
|
||||||
|
<div styleName='group-section-control'>
|
||||||
|
<input styleName='group-section-control-input'
|
||||||
|
onChange={(e) => this.handleHotkeyChange(e)}
|
||||||
|
ref='prettifyMarkdown'
|
||||||
|
value={config.hotkey.prettifyMarkdown}
|
||||||
|
type='text' />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section'>
|
||||||
|
<div styleName='group-section-label'>{i18n.__('Insert Current Date')}</div>
|
||||||
|
<div styleName='group-section-control'>
|
||||||
|
<input styleName='group-section-control-input'
|
||||||
|
ref='insertDate'
|
||||||
|
value={config.hotkey.insertDate}
|
||||||
|
type='text'
|
||||||
|
disabled='true'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section'>
|
||||||
|
<div styleName='group-section-label'>{i18n.__('Insert Current Date and Time')}</div>
|
||||||
|
<div styleName='group-section-control'>
|
||||||
|
<input styleName='group-section-control-input'
|
||||||
|
ref='insertDateTime'
|
||||||
|
value={config.hotkey.insertDateTime}
|
||||||
|
type='text'
|
||||||
|
disabled='true'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div styleName='group-control'>
|
<div styleName='group-control'>
|
||||||
<button styleName='group-control-leftButton'
|
<button styleName='group-control-leftButton'
|
||||||
onClick={(e) => this.handleHintToggleButtonClick(e)}
|
onClick={(e) => this.handleHintToggleButtonClick(e)}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React from 'react'
|
|||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './InfoTab.styl'
|
import styles from './InfoTab.styl'
|
||||||
import ConfigManager from 'browser/main/lib/ConfigManager'
|
import ConfigManager from 'browser/main/lib/ConfigManager'
|
||||||
import store from 'browser/main/store'
|
import { store } from 'browser/main/store'
|
||||||
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
@@ -61,6 +61,15 @@ 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
|
||||||
@@ -140,6 +149,8 @@ class InfoTab extends React.Component {
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<div><label><input type='checkbox' onChange={this.toggleAutoUpdate.bind(this)} checked={this.state.config.autoUpdateEnabled} />{i18n.__('Enable Auto Update')}</label></div>
|
||||||
|
|
||||||
<hr styleName='separate-line' />
|
<hr styleName='separate-line' />
|
||||||
|
|
||||||
<div styleName='group-header2--sub'>{i18n.__('Analytics')}</div>
|
<div styleName='group-header2--sub'>{i18n.__('Analytics')}</div>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import CSSModules from 'browser/lib/CSSModules'
|
|||||||
import styles from './StorageItem.styl'
|
import styles from './StorageItem.styl'
|
||||||
import consts from 'browser/lib/consts'
|
import consts from 'browser/lib/consts'
|
||||||
import dataApi from 'browser/main/lib/dataApi'
|
import dataApi from 'browser/main/lib/dataApi'
|
||||||
import store from 'browser/main/store'
|
import { store } from 'browser/main/store'
|
||||||
import FolderList from './FolderList'
|
import FolderList from './FolderList'
|
||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
|
|
||||||
|
|||||||
@@ -101,4 +101,12 @@ body[data-theme="solarized-dark"]
|
|||||||
.header-control-button
|
.header-control-button
|
||||||
border-color $ui-solarized-dark-button-backgroundColor
|
border-color $ui-solarized-dark-button-backgroundColor
|
||||||
background-color $ui-solarized-dark-button-backgroundColor
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
color $ui-solarized-dark-text-color
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
body[data-theme="dracula"]
|
||||||
|
.header
|
||||||
|
border-color $ui-dracula-borderColor
|
||||||
|
|
||||||
|
.header-control-button
|
||||||
|
colorDraculaDefaultButton()
|
||||||
|
border-color $ui-dracula-borderColor
|
||||||
@@ -3,8 +3,11 @@ import React from 'react'
|
|||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './StoragesTab.styl'
|
import styles from './StoragesTab.styl'
|
||||||
import dataApi from 'browser/main/lib/dataApi'
|
import dataApi from 'browser/main/lib/dataApi'
|
||||||
|
import attachmentManagement from 'browser/main/lib/dataApi/attachmentManagement'
|
||||||
import StorageItem from './StorageItem'
|
import StorageItem from './StorageItem'
|
||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
|
import { humanFileSize } from 'browser/lib/utils'
|
||||||
|
import fs from 'fs'
|
||||||
|
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
const { shell, remote } = electron
|
const { shell, remote } = electron
|
||||||
@@ -35,8 +38,29 @@ class StoragesTab extends React.Component {
|
|||||||
name: 'Unnamed',
|
name: 'Unnamed',
|
||||||
type: 'FILESYSTEM',
|
type: 'FILESYSTEM',
|
||||||
path: ''
|
path: ''
|
||||||
}
|
},
|
||||||
|
attachments: []
|
||||||
}
|
}
|
||||||
|
this.loadAttachmentStorage()
|
||||||
|
}
|
||||||
|
|
||||||
|
loadAttachmentStorage () {
|
||||||
|
const promises = []
|
||||||
|
this.props.data.noteMap.map(note => {
|
||||||
|
const promise = attachmentManagement.getAttachmentsPathAndStatus(
|
||||||
|
note.content,
|
||||||
|
note.storage,
|
||||||
|
note.key
|
||||||
|
)
|
||||||
|
if (promise) promises.push(promise)
|
||||||
|
})
|
||||||
|
|
||||||
|
Promise.all(promises)
|
||||||
|
.then(data => {
|
||||||
|
const result = data.reduce((acc, curr) => acc.concat(curr), [])
|
||||||
|
this.setState({attachments: result})
|
||||||
|
})
|
||||||
|
.catch(console.error)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAddStorageButton (e) {
|
handleAddStorageButton (e) {
|
||||||
@@ -57,8 +81,39 @@ class StoragesTab extends React.Component {
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleRemoveUnusedAttachments (attachments) {
|
||||||
|
attachmentManagement.removeAttachmentsByPaths(attachments)
|
||||||
|
.then(() => this.loadAttachmentStorage())
|
||||||
|
.catch(console.error)
|
||||||
|
}
|
||||||
|
|
||||||
renderList () {
|
renderList () {
|
||||||
const { data, boundingBox } = this.props
|
const { data, boundingBox } = this.props
|
||||||
|
const { attachments } = this.state
|
||||||
|
|
||||||
|
const unusedAttachments = attachments.filter(attachment => !attachment.isInUse)
|
||||||
|
const inUseAttachments = attachments.filter(attachment => attachment.isInUse)
|
||||||
|
|
||||||
|
const totalUnusedAttachments = unusedAttachments.length
|
||||||
|
const totalInuseAttachments = inUseAttachments.length
|
||||||
|
const totalAttachments = totalUnusedAttachments + totalInuseAttachments
|
||||||
|
|
||||||
|
const totalUnusedAttachmentsSize = unusedAttachments
|
||||||
|
.reduce((acc, curr) => {
|
||||||
|
const stats = fs.statSync(curr.path)
|
||||||
|
const fileSizeInBytes = stats.size
|
||||||
|
return acc + fileSizeInBytes
|
||||||
|
}, 0)
|
||||||
|
const totalInuseAttachmentsSize = inUseAttachments
|
||||||
|
.reduce((acc, curr) => {
|
||||||
|
const stats = fs.statSync(curr.path)
|
||||||
|
const fileSizeInBytes = stats.size
|
||||||
|
return acc + fileSizeInBytes
|
||||||
|
}, 0)
|
||||||
|
const totalAttachmentsSize = totalUnusedAttachmentsSize + totalInuseAttachmentsSize
|
||||||
|
|
||||||
|
const unusedAttachmentPaths = unusedAttachments
|
||||||
|
.reduce((acc, curr) => acc.concat(curr.path), [])
|
||||||
|
|
||||||
if (!boundingBox) { return null }
|
if (!boundingBox) { return null }
|
||||||
const storageList = data.storageMap.map((storage) => {
|
const storageList = data.storageMap.map((storage) => {
|
||||||
@@ -82,6 +137,20 @@ class StoragesTab extends React.Component {
|
|||||||
<i className='fa fa-plus' /> {i18n.__('Add Storage Location')}
|
<i className='fa fa-plus' /> {i18n.__('Add Storage Location')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div styleName='header'>{i18n.__('Attachment storage')}</div>
|
||||||
|
<p styleName='list-attachment-label'>
|
||||||
|
Unused attachments size: {humanFileSize(totalUnusedAttachmentsSize)} ({totalUnusedAttachments} items)
|
||||||
|
</p>
|
||||||
|
<p styleName='list-attachment-label'>
|
||||||
|
In use attachments size: {humanFileSize(totalInuseAttachmentsSize)} ({totalInuseAttachments} items)
|
||||||
|
</p>
|
||||||
|
<p styleName='list-attachment-label'>
|
||||||
|
Total attachments size: {humanFileSize(totalAttachmentsSize)} ({totalAttachments} items)
|
||||||
|
</p>
|
||||||
|
<button styleName='list-attachement-clear-button'
|
||||||
|
onClick={() => this.handleRemoveUnusedAttachments(unusedAttachmentPaths)}>
|
||||||
|
{i18n.__('Clear unused attachments')}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,17 @@
|
|||||||
colorDefaultButton()
|
colorDefaultButton()
|
||||||
font-size $tab--button-font-size
|
font-size $tab--button-font-size
|
||||||
border-radius 2px
|
border-radius 2px
|
||||||
|
.list-attachment-label
|
||||||
|
margin-bottom 10px
|
||||||
|
color $ui-text-color
|
||||||
|
.list-attachement-clear-button
|
||||||
|
height 30px
|
||||||
|
border none
|
||||||
|
border-top-right-radius 2px
|
||||||
|
border-bottom-right-radius 2px
|
||||||
|
colorPrimaryButton()
|
||||||
|
vertical-align middle
|
||||||
|
padding 0 20px
|
||||||
|
|
||||||
.addStorage
|
.addStorage
|
||||||
margin-bottom 15px
|
margin-bottom 15px
|
||||||
@@ -154,8 +165,8 @@ body[data-theme="dark"]
|
|||||||
.addStorage-body-control-cancelButton
|
.addStorage-body-control-cancelButton
|
||||||
colorDarkDefaultButton()
|
colorDarkDefaultButton()
|
||||||
border-color $ui-dark-borderColor
|
border-color $ui-dark-borderColor
|
||||||
|
.list-attachement-clear-button
|
||||||
|
colorDarkPrimaryButton()
|
||||||
|
|
||||||
body[data-theme="solarized-dark"]
|
body[data-theme="solarized-dark"]
|
||||||
.root
|
.root
|
||||||
@@ -194,6 +205,8 @@ body[data-theme="solarized-dark"]
|
|||||||
.addStorage-body-control-cancelButton
|
.addStorage-body-control-cancelButton
|
||||||
colorDarkDefaultButton()
|
colorDarkDefaultButton()
|
||||||
border-color $ui-solarized-dark-borderColor
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
.list-attachement-clear-button
|
||||||
|
colorSolarizedDarkPrimaryButton()
|
||||||
|
|
||||||
body[data-theme="monokai"]
|
body[data-theme="monokai"]
|
||||||
.root
|
.root
|
||||||
@@ -232,6 +245,8 @@ body[data-theme="monokai"]
|
|||||||
.addStorage-body-control-cancelButton
|
.addStorage-body-control-cancelButton
|
||||||
colorDarkDefaultButton()
|
colorDarkDefaultButton()
|
||||||
border-color $ui-monokai-borderColor
|
border-color $ui-monokai-borderColor
|
||||||
|
.list-attachement-clear-button
|
||||||
|
colorMonokaiPrimaryButton()
|
||||||
|
|
||||||
body[data-theme="dracula"]
|
body[data-theme="dracula"]
|
||||||
.root
|
.root
|
||||||
@@ -269,4 +284,6 @@ body[data-theme="dracula"]
|
|||||||
colorDarkPrimaryButton()
|
colorDarkPrimaryButton()
|
||||||
.addStorage-body-control-cancelButton
|
.addStorage-body-control-cancelButton
|
||||||
colorDarkDefaultButton()
|
colorDarkDefaultButton()
|
||||||
border-color $ui-dracula-borderColor
|
border-color $ui-dracula-borderColor
|
||||||
|
.list-attachement-clear-button
|
||||||
|
colorDraculaPrimaryButton()
|
||||||
@@ -3,7 +3,7 @@ import React from 'react'
|
|||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './ConfigTab.styl'
|
import styles from './ConfigTab.styl'
|
||||||
import ConfigManager from 'browser/main/lib/ConfigManager'
|
import ConfigManager from 'browser/main/lib/ConfigManager'
|
||||||
import store from 'browser/main/store'
|
import { store } from 'browser/main/store'
|
||||||
import consts from 'browser/lib/consts'
|
import consts from 'browser/lib/consts'
|
||||||
import ReactCodeMirror from 'react-codemirror'
|
import ReactCodeMirror from 'react-codemirror'
|
||||||
import CodeMirror from 'codemirror'
|
import CodeMirror from 'codemirror'
|
||||||
@@ -30,7 +30,13 @@ class UiTab extends React.Component {
|
|||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
CodeMirror.autoLoadMode(this.codeMirrorInstance.getCodeMirror(), 'javascript')
|
CodeMirror.autoLoadMode(this.codeMirrorInstance.getCodeMirror(), 'javascript')
|
||||||
CodeMirror.autoLoadMode(this.customCSSCM.getCodeMirror(), 'css')
|
CodeMirror.autoLoadMode(this.customCSSCM.getCodeMirror(), 'css')
|
||||||
|
CodeMirror.autoLoadMode(this.customMarkdownLintConfigCM.getCodeMirror(), 'javascript')
|
||||||
|
CodeMirror.autoLoadMode(this.prettierConfigCM.getCodeMirror(), 'javascript')
|
||||||
|
// Set CM editor Sizes
|
||||||
this.customCSSCM.getCodeMirror().setSize('400px', '400px')
|
this.customCSSCM.getCodeMirror().setSize('400px', '400px')
|
||||||
|
this.prettierConfigCM.getCodeMirror().setSize('400px', '400px')
|
||||||
|
this.customMarkdownLintConfigCM.getCodeMirror().setSize('400px', '200px')
|
||||||
|
|
||||||
this.handleSettingDone = () => {
|
this.handleSettingDone = () => {
|
||||||
this.setState({UiAlert: {
|
this.setState({UiAlert: {
|
||||||
type: 'success',
|
type: 'success',
|
||||||
@@ -89,6 +95,7 @@ class UiTab extends React.Component {
|
|||||||
enableRulers: this.refs.enableEditorRulers.value === 'true',
|
enableRulers: this.refs.enableEditorRulers.value === 'true',
|
||||||
rulers: this.refs.editorRulers.value.replace(/[^0-9,]/g, '').split(','),
|
rulers: this.refs.editorRulers.value.replace(/[^0-9,]/g, '').split(','),
|
||||||
displayLineNumbers: this.refs.editorDisplayLineNumbers.checked,
|
displayLineNumbers: this.refs.editorDisplayLineNumbers.checked,
|
||||||
|
lineWrapping: this.refs.editorLineWrapping.checked,
|
||||||
switchPreview: this.refs.editorSwitchPreview.value,
|
switchPreview: this.refs.editorSwitchPreview.value,
|
||||||
keyMap: this.refs.editorKeyMap.value,
|
keyMap: this.refs.editorKeyMap.value,
|
||||||
snippetDefaultLanguage: this.refs.editorSnippetDefaultLanguage.value,
|
snippetDefaultLanguage: this.refs.editorSnippetDefaultLanguage.value,
|
||||||
@@ -101,7 +108,11 @@ class UiTab extends React.Component {
|
|||||||
matchingTriples: this.refs.matchingTriples.value,
|
matchingTriples: this.refs.matchingTriples.value,
|
||||||
explodingPairs: this.refs.explodingPairs.value,
|
explodingPairs: this.refs.explodingPairs.value,
|
||||||
spellcheck: this.refs.spellcheck.checked,
|
spellcheck: this.refs.spellcheck.checked,
|
||||||
enableSmartPaste: this.refs.enableSmartPaste.checked
|
enableSmartPaste: this.refs.enableSmartPaste.checked,
|
||||||
|
enableMarkdownLint: this.refs.enableMarkdownLint.checked,
|
||||||
|
customMarkdownLintConfig: this.customMarkdownLintConfigCM.getCodeMirror().getValue(),
|
||||||
|
prettierConfig: this.prettierConfigCM.getCodeMirror().getValue(),
|
||||||
|
deleteUnusedAttachments: this.refs.deleteUnusedAttachments.checked
|
||||||
},
|
},
|
||||||
preview: {
|
preview: {
|
||||||
fontSize: this.refs.previewFontSize.value,
|
fontSize: this.refs.previewFontSize.value,
|
||||||
@@ -119,6 +130,7 @@ class UiTab extends React.Component {
|
|||||||
breaks: this.refs.previewBreaks.checked,
|
breaks: this.refs.previewBreaks.checked,
|
||||||
smartArrows: this.refs.previewSmartArrows.checked,
|
smartArrows: this.refs.previewSmartArrows.checked,
|
||||||
sanitize: this.refs.previewSanitize.value,
|
sanitize: this.refs.previewSanitize.value,
|
||||||
|
mermaidHTMLLabel: this.refs.previewMermaidHTMLLabel.checked,
|
||||||
allowCustomCSS: this.refs.previewAllowCustomCSS.checked,
|
allowCustomCSS: this.refs.previewAllowCustomCSS.checked,
|
||||||
lineThroughCheckbox: this.refs.lineThroughCheckbox.checked,
|
lineThroughCheckbox: this.refs.lineThroughCheckbox.checked,
|
||||||
customCSS: this.customCSSCM.getCodeMirror().getValue()
|
customCSS: this.customCSSCM.getCodeMirror().getValue()
|
||||||
@@ -131,7 +143,7 @@ class UiTab extends React.Component {
|
|||||||
const theme = consts.THEMES.find(theme => theme.name === newCodemirrorTheme)
|
const theme = consts.THEMES.find(theme => theme.name === newCodemirrorTheme)
|
||||||
|
|
||||||
if (theme) {
|
if (theme) {
|
||||||
checkHighLight.setAttribute('href', `../${theme.path}`)
|
checkHighLight.setAttribute('href', theme.path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,6 +553,17 @@ class UiTab extends React.Component {
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div styleName='group-checkBoxSection'>
|
||||||
|
<label>
|
||||||
|
<input onChange={(e) => this.handleUIChange(e)}
|
||||||
|
checked={this.state.config.editor.lineWrapping}
|
||||||
|
ref='editorLineWrapping'
|
||||||
|
type='checkbox'
|
||||||
|
/>
|
||||||
|
{i18n.__('Wrap line in Snippet Note')}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div styleName='group-checkBoxSection'>
|
<div styleName='group-checkBoxSection'>
|
||||||
<label>
|
<label>
|
||||||
<input onChange={(e) => this.handleUIChange(e)}
|
<input onChange={(e) => this.handleUIChange(e)}
|
||||||
@@ -595,6 +618,16 @@ class UiTab extends React.Component {
|
|||||||
{i18n.__('Enable spellcheck - Experimental feature!! :)')}
|
{i18n.__('Enable spellcheck - Experimental feature!! :)')}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div styleName='group-checkBoxSection'>
|
||||||
|
<label>
|
||||||
|
<input onChange={(e) => this.handleUIChange(e)}
|
||||||
|
checked={this.state.config.editor.deleteUnusedAttachments}
|
||||||
|
ref='deleteUnusedAttachments'
|
||||||
|
type='checkbox'
|
||||||
|
/>
|
||||||
|
{i18n.__('Delete attachments, that are not referenced in the text anymore')}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div styleName='group-section'>
|
<div styleName='group-section'>
|
||||||
<div styleName='group-section-label'>
|
<div styleName='group-section-label'>
|
||||||
@@ -637,6 +670,34 @@ class UiTab extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div styleName='group-section'>
|
||||||
|
<div styleName='group-section-label'>
|
||||||
|
{i18n.__('Custom MarkdownLint Rules')}
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section-control'>
|
||||||
|
<input onChange={(e) => this.handleUIChange(e)}
|
||||||
|
checked={this.state.config.editor.enableMarkdownLint}
|
||||||
|
ref='enableMarkdownLint'
|
||||||
|
type='checkbox'
|
||||||
|
/>
|
||||||
|
{i18n.__('Enable MarkdownLint')}
|
||||||
|
<div style={{fontFamily, display: this.state.config.editor.enableMarkdownLint ? 'block' : 'none'}}>
|
||||||
|
<ReactCodeMirror
|
||||||
|
width='400px'
|
||||||
|
height='200px'
|
||||||
|
onChange={e => this.handleUIChange(e)}
|
||||||
|
ref={e => (this.customMarkdownLintConfigCM = e)}
|
||||||
|
value={config.editor.customMarkdownLintConfig}
|
||||||
|
options={{
|
||||||
|
lineNumbers: true,
|
||||||
|
mode: 'application/json',
|
||||||
|
theme: codemirrorTheme,
|
||||||
|
lint: true,
|
||||||
|
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers']
|
||||||
|
}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div styleName='group-header2'>{i18n.__('Preview')}</div>
|
<div styleName='group-header2'>{i18n.__('Preview')}</div>
|
||||||
<div styleName='group-section'>
|
<div styleName='group-section'>
|
||||||
@@ -768,6 +829,16 @@ class UiTab extends React.Component {
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div styleName='group-checkBoxSection'>
|
||||||
|
<label>
|
||||||
|
<input onChange={(e) => this.handleUIChange(e)}
|
||||||
|
checked={this.state.config.preview.mermaidHTMLLabel}
|
||||||
|
ref='previewMermaidHTMLLabel'
|
||||||
|
type='checkbox'
|
||||||
|
/>
|
||||||
|
{i18n.__('Enable HTML label in mermaid flowcharts')}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<div styleName='group-section'>
|
<div styleName='group-section'>
|
||||||
<div styleName='group-section-label'>
|
<div styleName='group-section-label'>
|
||||||
{i18n.__('LaTeX Inline Open Delimiter')}
|
{i18n.__('LaTeX Inline Open Delimiter')}
|
||||||
@@ -851,7 +922,6 @@ class UiTab extends React.Component {
|
|||||||
onChange={e => this.handleUIChange(e)}
|
onChange={e => this.handleUIChange(e)}
|
||||||
ref={e => (this.customCSSCM = e)}
|
ref={e => (this.customCSSCM = e)}
|
||||||
value={config.preview.customCSS}
|
value={config.preview.customCSS}
|
||||||
defaultValue={'/* Drop Your Custom CSS Code Here */\n'}
|
|
||||||
options={{
|
options={{
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
mode: 'css',
|
mode: 'css',
|
||||||
@@ -860,7 +930,27 @@ class UiTab extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div styleName='group-section'>
|
||||||
|
<div styleName='group-section-label'>
|
||||||
|
{i18n.__('Prettier Config')}
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section-control'>
|
||||||
|
<div style={{fontFamily}}>
|
||||||
|
<ReactCodeMirror
|
||||||
|
width='400px'
|
||||||
|
height='400px'
|
||||||
|
onChange={e => this.handleUIChange(e)}
|
||||||
|
ref={e => (this.prettierConfigCM = e)}
|
||||||
|
value={config.editor.prettierConfig}
|
||||||
|
options={{
|
||||||
|
lineNumbers: true,
|
||||||
|
mode: 'application/json',
|
||||||
|
lint: true,
|
||||||
|
theme: codemirrorTheme
|
||||||
|
}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div styleName='group-control'>
|
<div styleName='group-control'>
|
||||||
<button styleName='group-control-rightButton'
|
<button styleName='group-control-rightButton'
|
||||||
onClick={(e) => this.handleSaveUIClick(e)}>{i18n.__('Save')}
|
onClick={(e) => this.handleSaveUIClick(e)}>{i18n.__('Save')}
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ class Preferences extends React.Component {
|
|||||||
key={tab.target}
|
key={tab.target}
|
||||||
onClick={(e) => this.handleNavButtonClick(tab.target)(e)}
|
onClick={(e) => this.handleNavButtonClick(tab.target)(e)}
|
||||||
>
|
>
|
||||||
<span styleName='nav-button-label'>
|
<span>
|
||||||
{tab.label}
|
{tab.label}
|
||||||
</span>
|
</span>
|
||||||
{isUiHotkeyTab ? this.haveToSaveNotif(tab[tab.label].type, tab[tab.label].message) : null}
|
{isUiHotkeyTab ? this.haveToSaveNotif(tab[tab.label].type, tab[tab.label].message) : null}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from 'react'
|
|||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './RenameFolderModal.styl'
|
import styles from './RenameFolderModal.styl'
|
||||||
import dataApi from 'browser/main/lib/dataApi'
|
import dataApi from 'browser/main/lib/dataApi'
|
||||||
import store from 'browser/main/store'
|
import { store } from 'browser/main/store'
|
||||||
import ModalEscButton from 'browser/components/ModalEscButton'
|
import ModalEscButton from 'browser/components/ModalEscButton'
|
||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { combineReducers, createStore } from 'redux'
|
import { combineReducers, createStore, compose, applyMiddleware } from 'redux'
|
||||||
import { routerReducer } from 'react-router-redux'
|
import { connectRouter, routerMiddleware } from 'connected-react-router'
|
||||||
|
import { createHashHistory as createHistory } from 'history'
|
||||||
import ConfigManager from 'browser/main/lib/ConfigManager'
|
import ConfigManager from 'browser/main/lib/ConfigManager'
|
||||||
import { Map, Set } from 'browser/lib/Mutable'
|
import { Map, Set } from 'browser/lib/Mutable'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
import DevTools from './DevTools'
|
||||||
|
|
||||||
function defaultDataMap () {
|
function defaultDataMap () {
|
||||||
return {
|
return {
|
||||||
@@ -465,13 +467,17 @@ function getOrInitItem (target, key) {
|
|||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const history = createHistory()
|
||||||
|
|
||||||
const reducer = combineReducers({
|
const reducer = combineReducers({
|
||||||
data,
|
data,
|
||||||
config,
|
config,
|
||||||
status,
|
status,
|
||||||
routing: routerReducer
|
router: connectRouter(history)
|
||||||
})
|
})
|
||||||
|
|
||||||
const store = createStore(reducer)
|
const store = createStore(reducer, undefined, process.env.NODE_ENV === 'development'
|
||||||
|
? compose(applyMiddleware(routerMiddleware(history)), DevTools.instrument())
|
||||||
|
: applyMiddleware(routerMiddleware(history)))
|
||||||
|
|
||||||
export default store
|
export { store, history }
|
||||||
|
|||||||
@@ -410,6 +410,15 @@ $ui-dracula-button--active-color = #f8f8f2
|
|||||||
$ui-dracula-button--active-backgroundColor = #bd93f9
|
$ui-dracula-button--active-backgroundColor = #bd93f9
|
||||||
$ui-dracula-button--hover-backgroundColor = lighten($ui-dracula-backgroundColor, 10%)
|
$ui-dracula-button--hover-backgroundColor = lighten($ui-dracula-backgroundColor, 10%)
|
||||||
$ui-dracula-button--focus-borderColor = lighten(#44475a, 25%)
|
$ui-dracula-button--focus-borderColor = lighten(#44475a, 25%)
|
||||||
|
colorDraculaDefaultButton()
|
||||||
|
border-color $ui-dracula-borderColor
|
||||||
|
color $ui-dracula-text-color
|
||||||
|
background-color $ui-dracula-button-backgroundColor
|
||||||
|
&:hover
|
||||||
|
background-color $ui-dracula-button--hover-backgroundColor
|
||||||
|
&:active
|
||||||
|
&:active:hover
|
||||||
|
background-color $ui-dracula-button--active-backgroundColor
|
||||||
|
|
||||||
modalDracula()
|
modalDracula()
|
||||||
position relative
|
position relative
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
> [Please consider to contribute to the new Boost Note app too!](https://github.com/BoostIO/BoostNote.next)
|
||||||
|
|
||||||
# Contributing to Boostnote (English)
|
# Contributing to Boostnote (English)
|
||||||
|
|
||||||
### When you open an issue or a bug report
|
### When you open an issue or a bug report
|
||||||
@@ -87,17 +89,17 @@ Pull requestをすることはその変化分のコードの著作権をBoostIO
|
|||||||
# Contributing to Boostnote (Simplified Chinese)
|
# Contributing to Boostnote (Simplified Chinese)
|
||||||
|
|
||||||
### 当您创建一个issue的时候
|
### 当您创建一个issue的时候
|
||||||
我们对您的issue格式没有要求,但是我们有一个请求:
|
我们对您的issue格式没有要求,但是我们有一个请求:
|
||||||
|
|
||||||
**如果可能,请在开发者模式打开的情况下,为我们提供屏幕截图**
|
**如果可能,请在开发者模式打开的情况下,为我们提供屏幕截图**
|
||||||
|
|
||||||
(您可以通过`Ctrl+Shift+I`打开开发者模式)。
|
(您可以通过`Ctrl+Shift+I`打开开发者模式)。
|
||||||
感谢您对我们的支持。
|
感谢您对我们的支持。
|
||||||
|
|
||||||
### 关于您提供的Pull Request的著作权(版权)问题
|
### 关于您提供的Pull Request的著作权(版权)问题
|
||||||
如果您提供了一个Pull Request,这表示您将您所修改的代码的著作权移交给BoostIO。
|
如果您提供了一个Pull Request,这表示您将您所修改的代码的著作权移交给BoostIO。
|
||||||
|
|
||||||
这并不表示Boostnote会成为一个需要付费的软件。如果我们想获得收益,我们会尝试一些其他的方法,比如说云存储、绑定手机软件等。
|
这并不表示Boostnote会成为一个需要付费的软件。如果我们想获得收益,我们会尝试一些其他的方法,比如说云存储、绑定手机软件等。
|
||||||
因为GPLv3过于严格,不能和其他的一些协议兼容,所以我们有可能在将来会把BoostNote的协议改为一些较为宽松的协议,比如说BSD、MIT。
|
因为GPLv3过于严格,不能和其他的一些协议兼容,所以我们有可能在将来会把BoostNote的协议改为一些较为宽松的协议,比如说BSD、MIT。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -42,7 +42,9 @@ Então nós preparamos um _script_ separado, o qual somente cria um executável.
|
|||||||
grunt pre-build
|
grunt pre-build
|
||||||
```
|
```
|
||||||
|
|
||||||
Você irá encontrar o executável na pasta `dist`. Nota: o atualizador automático não funciona porque o app não está certificado.
|
Você irá encontrar o executável na pasta `dist`.
|
||||||
|
|
||||||
|
**Nota:** o atualizador automático não funciona porque o app não está certificado.
|
||||||
|
|
||||||
Se você achar isto necessário, você pode usar o _codesign_ ou o _authenticode_ com esse executável.
|
Se você achar isto necessário, você pode usar o _codesign_ ou o _authenticode_ com esse executável.
|
||||||
|
|
||||||
@@ -50,7 +52,7 @@ Se você achar isto necessário, você pode usar o _codesign_ ou o _authenticode
|
|||||||
|
|
||||||
Pacotes de distribuição são gerados através do comando `grunt build` em plataforma Linux (e.g. Ubuntu, Fedora).
|
Pacotes de distribuição são gerados através do comando `grunt build` em plataforma Linux (e.g. Ubuntu, Fedora).
|
||||||
|
|
||||||
> Nota: você pode criar `.deb` e `.rpm` em um mesmo ambiente.
|
**Nota:** você pode criar `.deb` e `.rpm` em um mesmo ambiente.
|
||||||
|
|
||||||
Depois de instalar uma versão suportada do `node` e do `npm`, deve-se instalar as dependências para gerar os pacotes.
|
Depois de instalar uma versão suportada do `node` e do `npm`, deve-se instalar as dependências para gerar os pacotes.
|
||||||
|
|
||||||
|
|||||||
@@ -4,25 +4,25 @@ const Menu = electron.Menu
|
|||||||
const ipc = electron.ipcMain
|
const ipc = electron.ipcMain
|
||||||
const GhReleases = require('electron-gh-releases')
|
const GhReleases = require('electron-gh-releases')
|
||||||
const { isPackaged } = app
|
const { isPackaged } = app
|
||||||
|
const electronConfig = new (require('electron-config'))()
|
||||||
// electron.crashReporter.start()
|
// electron.crashReporter.start()
|
||||||
|
const singleInstance = app.requestSingleInstanceLock()
|
||||||
|
|
||||||
var ipcServer = null
|
var ipcServer = null
|
||||||
|
|
||||||
var mainWindow = null
|
var mainWindow = null
|
||||||
|
|
||||||
var shouldQuit = app.makeSingleInstance(function (commandLine, workingDirectory) {
|
// Single Instance Lock
|
||||||
if (mainWindow) {
|
if (!singleInstance) {
|
||||||
if (process.platform === 'win32') {
|
|
||||||
mainWindow.minimize()
|
|
||||||
mainWindow.restore()
|
|
||||||
}
|
|
||||||
mainWindow.focus()
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
if (shouldQuit) {
|
|
||||||
app.quit()
|
app.quit()
|
||||||
|
} else {
|
||||||
|
app.on('second-instance', () => {
|
||||||
|
// Someone tried to run a second instance, it should focus the existing instance.
|
||||||
|
if (mainWindow) {
|
||||||
|
if (!mainWindow.isVisible()) mainWindow.show()
|
||||||
|
mainWindow.focus()
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var isUpdateReady = false
|
var isUpdateReady = false
|
||||||
@@ -41,6 +41,7 @@ function checkUpdate () {
|
|||||||
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) {
|
if (process.platform === 'linux' || isUpdateReady) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ const BrowserWindow = electron.BrowserWindow
|
|||||||
const shell = electron.shell
|
const shell = electron.shell
|
||||||
const ipc = electron.ipcMain
|
const ipc = electron.ipcMain
|
||||||
const mainWindow = require('./main-window')
|
const mainWindow = require('./main-window')
|
||||||
|
const os = require('os')
|
||||||
|
|
||||||
const macOS = process.platform === 'darwin'
|
const macOS = process.platform === 'darwin'
|
||||||
// const WIN = process.platform === 'win32'
|
// const WIN = process.platform === 'win32'
|
||||||
@@ -85,21 +86,21 @@ const file = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Focus Note',
|
label: 'Focus Note',
|
||||||
accelerator: macOS ? 'Command+E' : 'Control+E',
|
accelerator: 'CommandOrControl+E',
|
||||||
click () {
|
click () {
|
||||||
mainWindow.webContents.send('detail:focus')
|
mainWindow.webContents.send('detail:focus')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Delete Note',
|
label: 'Delete Note',
|
||||||
accelerator: macOS ? 'Command+Shift+Backspace' : 'Control+Shift+Backspace',
|
accelerator: 'CommandOrControl+Shift+Backspace',
|
||||||
click () {
|
click () {
|
||||||
mainWindow.webContents.send('detail:delete')
|
mainWindow.webContents.send('detail:delete')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Clone Note',
|
label: 'Clone Note',
|
||||||
accelerator: macOS ? 'Command+D' : 'Control+D',
|
accelerator: 'CommandOrControl+D',
|
||||||
click () {
|
click () {
|
||||||
mainWindow.webContents.send('list:clone')
|
mainWindow.webContents.send('list:clone')
|
||||||
}
|
}
|
||||||
@@ -259,7 +260,7 @@ const view = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Toggle Developer Tools',
|
label: 'Toggle Developer Tools',
|
||||||
accelerator: macOS ? 'Command+Alt+I' : 'Control+Shift+I',
|
accelerator: 'CommandOrControl+Alt+I',
|
||||||
click () {
|
click () {
|
||||||
BrowserWindow.getFocusedWindow().toggleDevTools()
|
BrowserWindow.getFocusedWindow().toggleDevTools()
|
||||||
}
|
}
|
||||||
@@ -313,21 +314,21 @@ const view = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Actual Size',
|
label: 'Actual Size',
|
||||||
accelerator: macOS ? 'CommandOrControl+0' : 'Control+0',
|
accelerator: 'CommandOrControl+0',
|
||||||
click () {
|
click () {
|
||||||
mainWindow.webContents.send('status:zoomreset')
|
mainWindow.webContents.send('status:zoomreset')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Zoom In',
|
label: 'Zoom In',
|
||||||
accelerator: macOS ? 'CommandOrControl+=' : 'Control+=',
|
accelerator: 'CommandOrControl+=',
|
||||||
click () {
|
click () {
|
||||||
mainWindow.webContents.send('status:zoomin')
|
mainWindow.webContents.send('status:zoomin')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Zoom Out',
|
label: 'Zoom Out',
|
||||||
accelerator: macOS ? 'CommandOrControl+-' : 'Control+-',
|
accelerator: 'CommandOrControl+-',
|
||||||
click () {
|
click () {
|
||||||
mainWindow.webContents.send('status:zoomout')
|
mainWindow.webContents.send('status:zoomout')
|
||||||
}
|
}
|
||||||
@@ -411,6 +412,28 @@ const help = {
|
|||||||
click () { shell.openExternal('https://github.com/TobseF/boostnote-markdown-cheatsheet/blob/master/BOOSTNOTE_MARKDOWN_CHEAT_SHEET.md') }
|
click () { shell.openExternal('https://github.com/TobseF/boostnote-markdown-cheatsheet/blob/master/BOOSTNOTE_MARKDOWN_CHEAT_SHEET.md') }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'separator'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'About',
|
||||||
|
click () {
|
||||||
|
const version = electron.app.getVersion()
|
||||||
|
const electronVersion = process.versions.electron
|
||||||
|
const chromeVersion = process.versions.chrome
|
||||||
|
const nodeVersion = process.versions.node
|
||||||
|
const v8Version = process.versions.v8
|
||||||
|
const OSInfo = `${os.type()} ${os.arch()} ${os.release()}`
|
||||||
|
const detail = `Version: ${version}\nElectron: ${electronVersion}\nChrome: ${chromeVersion}\nNode.js: ${nodeVersion}\nV8: ${v8Version}\nOS: ${OSInfo}`
|
||||||
|
electron.dialog.showMessageBox(BrowserWindow.getFocusedWindow(),
|
||||||
|
{
|
||||||
|
title: 'BoostNote',
|
||||||
|
message: 'BoostNote',
|
||||||
|
type: 'info',
|
||||||
|
detail: `\n${detail}`
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,33 @@ const Config = require('electron-config')
|
|||||||
const config = new Config()
|
const config = new Config()
|
||||||
const _ = require('lodash')
|
const _ = require('lodash')
|
||||||
|
|
||||||
|
// set up some chrome extensions
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
const {
|
||||||
|
default: installExtension,
|
||||||
|
REACT_DEVELOPER_TOOLS,
|
||||||
|
REACT_PERF
|
||||||
|
} = require('electron-devtools-installer')
|
||||||
|
|
||||||
|
require('electron-debug')({ showDevTools: false })
|
||||||
|
|
||||||
|
const ChromeLens = {
|
||||||
|
// ID of the extension (https://chrome.google.com/webstore/detail/chromelens/idikgljglpfilbhaboonnpnnincjhjkd)
|
||||||
|
id: 'idikgljglpfilbhaboonnpnnincjhjkd',
|
||||||
|
electron: '>=1.2.1'
|
||||||
|
}
|
||||||
|
|
||||||
|
const extensions = [REACT_DEVELOPER_TOOLS, REACT_PERF, ChromeLens]
|
||||||
|
|
||||||
|
for (const extension of extensions) {
|
||||||
|
try {
|
||||||
|
installExtension(extension)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`[ELECTRON] Extension installation failed`, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const windowSize = config.get('windowsize') || {
|
const windowSize = config.get('windowsize') || {
|
||||||
x: null,
|
x: null,
|
||||||
y: null,
|
y: null,
|
||||||
@@ -27,8 +54,7 @@ const mainWindow = new BrowserWindow({
|
|||||||
},
|
},
|
||||||
icon: path.resolve(__dirname, '../resources/app.png')
|
icon: path.resolve(__dirname, '../resources/app.png')
|
||||||
})
|
})
|
||||||
|
const url = path.resolve(__dirname, process.env.NODE_ENV === 'development' ? './main.development.html' : './main.production.html')
|
||||||
const url = path.resolve(__dirname, './main.html')
|
|
||||||
|
|
||||||
mainWindow.loadURL('file://' + url)
|
mainWindow.loadURL('file://' + url)
|
||||||
mainWindow.setMenuBarVisibility(false)
|
mainWindow.setMenuBarVisibility(false)
|
||||||
|
|||||||
170
lib/main.development.html
Normal file
170
lib/main.development.html
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="../node_modules/font-awesome/css/font-awesome.min.css" media="screen" charset="utf-8">
|
||||||
|
<link rel="shortcut icon" href="../resources/favicon.ico">
|
||||||
|
<link rel="stylesheet" href="../node_modules/codemirror/lib/codemirror.css">
|
||||||
|
<link rel="stylesheet" href="../node_modules/katex/dist/katex.min.css">
|
||||||
|
<link rel="stylesheet" href="../node_modules/codemirror/addon/dialog/dialog.css">
|
||||||
|
<link rel="stylesheet" href="../node_modules/codemirror/addon/lint/lint.css">
|
||||||
|
<link rel="stylesheet" href="../extra_scripts/codemirror/mode/bfm/bfm.css">
|
||||||
|
|
||||||
|
<title>Boostnote</title>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: 'OpenSans';
|
||||||
|
src: url('../resources/fonts/Lato-Regular.woff2') format('woff2'), /* Modern Browsers */
|
||||||
|
url('../resources/fonts/Lato-Regular.woff') format('woff'), /* Modern Browsers */
|
||||||
|
url('../resources/fonts/Lato-Regular.ttf') format('truetype');
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Lato';
|
||||||
|
src: url('../resources/fonts/Lato-Regular.woff2') format('woff2'), /* Modern Browsers */
|
||||||
|
url('../resources/fonts/Lato-Regular.woff') format('woff'), /* Modern Browsers */
|
||||||
|
url('../resources/fonts/Lato-Regular.ttf') format('truetype');
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loadingCover {
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 65px 0;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loadingCover img {
|
||||||
|
display: block;
|
||||||
|
margin: 75px auto 5px;
|
||||||
|
width: 160px;
|
||||||
|
height: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loadingCover .message {
|
||||||
|
font-size: 30px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.6;
|
||||||
|
font-weight: 100;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeEditor {
|
||||||
|
opacity: 1 !important;
|
||||||
|
pointer-events: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-ruler {
|
||||||
|
border-left-color: rgba(142, 142, 142, 0.5);
|
||||||
|
mix-blend-mode: difference;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-scroll {
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-lint-tooltip {
|
||||||
|
z-index: 1003;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="loadingCover">
|
||||||
|
<img src="../resources/app.png">
|
||||||
|
<div class='message'>
|
||||||
|
<i class="fa fa-spinner fa-spin" spin></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="content"></div>
|
||||||
|
|
||||||
|
<script src="../node_modules/codemirror/lib/codemirror.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/mode/meta.js"></script>
|
||||||
|
<script src="../node_modules/codemirror-mode-elixir/dist/elixir.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/mode/overlay.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/mode/loadmode.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/mode/simple.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/mode/multiplex.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/keymap/sublime.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/keymap/vim.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/keymap/emacs.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/runmode/runmode.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/display/panel.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/mode/xml/xml.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/mode/markdown/markdown.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/mode/gfm/gfm.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/mode/yaml/yaml.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/mode/yaml-frontmatter/yaml-frontmatter.js"></script>
|
||||||
|
|
||||||
|
<script src="../extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js"></script>
|
||||||
|
<script src="../extra_scripts/codemirror/mode/bfm/bfm.js"></script>
|
||||||
|
<script src="../extra_scripts/codemirror/addon/hyperlink/hyperlink.js"></script>
|
||||||
|
|
||||||
|
<script src="../node_modules/codemirror/addon/edit/closebrackets.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/edit/matchbrackets.js"></script>
|
||||||
|
|
||||||
|
<script src="../node_modules/codemirror/addon/search/search.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/search/searchcursor.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/scroll/annotatescrollbar.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/scroll/scrollpastend.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/search/matchesonscrollbar.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/search/jump-to-line.js"></script>
|
||||||
|
|
||||||
|
<script src="../node_modules/codemirror/addon/fold/brace-fold.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/fold/markdown-fold.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/fold/foldgutter.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/fold/foldcode.js"></script>
|
||||||
|
|
||||||
|
<script src="../node_modules/codemirror/addon/dialog/dialog.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/display/rulers.js"></script>
|
||||||
|
|
||||||
|
<script src="../node_modules/jsonlint-mod/lib/jsonlint.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/lint/lint.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/lint/json-lint.js"></script>
|
||||||
|
|
||||||
|
<script src="../node_modules/raphael/raphael.min.js"></script>
|
||||||
|
<script src="../node_modules/flowchart.js/release/flowchart.min.js"></script>
|
||||||
|
<script>
|
||||||
|
window._ = require('lodash')
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script src="../node_modules/@rokt33r/js-sequence-diagrams/dist/sequence-diagram-min.js"></script>
|
||||||
|
<script src="../node_modules/react/umd/react.development.js"></script>
|
||||||
|
<script src="../node_modules/react-dom/umd/react-dom.development.js"></script>
|
||||||
|
<script src="../node_modules/redux/dist/redux.min.js"></script>
|
||||||
|
<script src="../node_modules/react-redux/dist/react-redux.min.js"></script>
|
||||||
|
<script type='text/javascript'>
|
||||||
|
const electron = require('electron')
|
||||||
|
electron.webFrame.setVisualZoomLevelLimits(1, 1)
|
||||||
|
var scriptUrl = window._.find(electron.remote.process.argv, (a) => a === '--hot')
|
||||||
|
? 'http://localhost:8080/assets/main.js'
|
||||||
|
: '../compiled/main.js'
|
||||||
|
var scriptEl = document.createElement('script')
|
||||||
|
scriptEl.setAttribute('type', 'text/javascript')
|
||||||
|
scriptEl.setAttribute('src', scriptUrl)
|
||||||
|
document.body.appendChild(scriptEl)
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.ace_search {
|
||||||
|
background-color: #d9d9d9;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -72,6 +72,11 @@
|
|||||||
border-left-color: rgba(142, 142, 142, 0.5);
|
border-left-color: rgba(142, 142, 142, 0.5);
|
||||||
mix-blend-mode: difference;
|
mix-blend-mode: difference;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.CodeMirror-scroll {
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@@ -106,7 +111,6 @@
|
|||||||
<script src="../extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js"></script>
|
<script src="../extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js"></script>
|
||||||
<script src="../extra_scripts/codemirror/mode/bfm/bfm.js"></script>
|
<script src="../extra_scripts/codemirror/mode/bfm/bfm.js"></script>
|
||||||
<script src="../extra_scripts/codemirror/addon/hyperlink/hyperlink.js"></script>
|
<script src="../extra_scripts/codemirror/addon/hyperlink/hyperlink.js"></script>
|
||||||
<script src="../extra_scripts/codemirror/mode/bfm/bfm.js"></script>
|
|
||||||
|
|
||||||
<script src="../node_modules/codemirror/addon/edit/closebrackets.js"></script>
|
<script src="../node_modules/codemirror/addon/edit/closebrackets.js"></script>
|
||||||
<script src="../node_modules/codemirror/addon/edit/matchbrackets.js"></script>
|
<script src="../node_modules/codemirror/addon/edit/matchbrackets.js"></script>
|
||||||
@@ -126,7 +130,9 @@
|
|||||||
<script src="../node_modules/codemirror/addon/dialog/dialog.js"></script>
|
<script src="../node_modules/codemirror/addon/dialog/dialog.js"></script>
|
||||||
<script src="../node_modules/codemirror/addon/display/rulers.js"></script>
|
<script src="../node_modules/codemirror/addon/display/rulers.js"></script>
|
||||||
|
|
||||||
|
<script src="../node_modules/jsonlint-mod/lib/jsonlint.js"></script>
|
||||||
<script src="../node_modules/codemirror/addon/lint/lint.js"></script>
|
<script src="../node_modules/codemirror/addon/lint/lint.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/lint/json-lint.js"></script>
|
||||||
|
|
||||||
<script src="../node_modules/raphael/raphael.min.js"></script>
|
<script src="../node_modules/raphael/raphael.min.js"></script>
|
||||||
<script src="../node_modules/flowchart.js/release/flowchart.min.js"></script>
|
<script src="../node_modules/flowchart.js/release/flowchart.min.js"></script>
|
||||||
@@ -135,8 +141,8 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script src="../node_modules/@rokt33r/js-sequence-diagrams/dist/sequence-diagram-min.js"></script>
|
<script src="../node_modules/@rokt33r/js-sequence-diagrams/dist/sequence-diagram-min.js"></script>
|
||||||
<script src="../node_modules/react/dist/react.min.js"></script>
|
<script src="../node_modules/react/umd/react.production.min.js"></script>
|
||||||
<script src="../node_modules/react-dom/dist/react-dom.min.js"></script>
|
<script src="../node_modules/react-dom/umd/react-dom.production.min.js"></script>
|
||||||
<script src="../node_modules/redux/dist/redux.min.js"></script>
|
<script src="../node_modules/redux/dist/redux.min.js"></script>
|
||||||
<script src="../node_modules/react-redux/dist/react-redux.min.js"></script>
|
<script src="../node_modules/react-redux/dist/react-redux.min.js"></script>
|
||||||
<script type='text/javascript'>
|
<script type='text/javascript'>
|
||||||
194
locales/cs.json
Normal file
194
locales/cs.json
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
{
|
||||||
|
"Notes": "Poznámky",
|
||||||
|
"Tags": "Štítky",
|
||||||
|
"Preferences": "Předvolby",
|
||||||
|
"Make a note": "Vytvořit poznámku",
|
||||||
|
"Ctrl": "Ctrl",
|
||||||
|
"Ctrl(^)": "Ctrl(^)",
|
||||||
|
"to create a new note": " pro vytvoření nové poznámky",
|
||||||
|
"Toggle Mode": "Přepnout režim",
|
||||||
|
"Add tag...": "Přidat štítek...",
|
||||||
|
"Trash": "Koš",
|
||||||
|
"Ok": "Ok",
|
||||||
|
"MODIFICATION DATE": "DATUM ZMĚNY",
|
||||||
|
"Words": "Slova",
|
||||||
|
"Letters": "Písmena",
|
||||||
|
"STORAGE": "ÚLOŽIŠTĚ",
|
||||||
|
"FOLDER": "SLOŽKA",
|
||||||
|
"CREATION DATE": "DATUM VYTVOŘENÍ",
|
||||||
|
"NOTE LINK": "ODKAZ NA POZNÁMKU",
|
||||||
|
".md": ".md",
|
||||||
|
".txt": ".txt",
|
||||||
|
".html": ".html",
|
||||||
|
".pdf": ".pdf",
|
||||||
|
"Print": "Tisk",
|
||||||
|
"Your preferences for Boostnote": "Vaše předvolby pro Boostnote",
|
||||||
|
"Help": "Nápověda",
|
||||||
|
"Hide Help": "Skrýt nápovědu",
|
||||||
|
"Storage Locations": "Umístění úložiště",
|
||||||
|
"Add Storage Location": "Přidat umístění úložiště",
|
||||||
|
"Add Folder": "Přidat složku",
|
||||||
|
"Select Folder": "Vybrat složku",
|
||||||
|
"Open Storage folder": "Otevřít složku úložiště",
|
||||||
|
"Unlink": "Zrušit odkaz",
|
||||||
|
"Edit": "Editovat",
|
||||||
|
"Delete": "Odstranit",
|
||||||
|
"Interface": "Rozhraní",
|
||||||
|
"Interface Theme": "Téma vzhledu rozhraní",
|
||||||
|
"Default": "Výchozí",
|
||||||
|
"White": "Bílé",
|
||||||
|
"Solarized Dark": "Solarizovaně tmavé",
|
||||||
|
"Dark": "Tmavé",
|
||||||
|
"Show a confirmation dialog when deleting notes": "Zobrazovat při odstraňování poznámek dialog pro potvrzení",
|
||||||
|
"Disable Direct Write (It will be applied after restarting)": "Zakázat přímý zápis (Bude aplikováno po restartu)",
|
||||||
|
"Show only related tags": "Zobrazit pouze související štítky",
|
||||||
|
"Editor Theme": "Téma vzhledu editoru",
|
||||||
|
"Editor Font Size": "Velikost písma editoru",
|
||||||
|
"Editor Font Family": "Rodiny písma editoru",
|
||||||
|
"Editor Indent Style": "Styl odsazení editoru",
|
||||||
|
"Spaces": "Mezery",
|
||||||
|
"Tabs": "Tabulátory",
|
||||||
|
"Switch to Preview": "Přepnout na náhled",
|
||||||
|
"When Editor Blurred": "Když se editor rozostří",
|
||||||
|
"When Editor Blurred, Edit On Double Click": "Při rozostření editoru, editovat po dvojím kliknutí",
|
||||||
|
"On Right Click": "Po kliknutí pravým tlačítkem myši",
|
||||||
|
"Editor Keymap": "Mapa kláves editoru",
|
||||||
|
"default": "výchozí",
|
||||||
|
"vim": "vim",
|
||||||
|
"emacs": "emacs",
|
||||||
|
"⚠️ Please restart boostnote after you change the keymap": "⚠️ Prosím restartujte boostnote po změně mapy kláves",
|
||||||
|
"Show line numbers in the editor": "Zobrazit v editoru čísla řádků",
|
||||||
|
"Allow editor to scroll past the last line": "Povolit v editoru scrolování za poslední řádek",
|
||||||
|
"Enable smart quotes": "Povolit chytré komentáře",
|
||||||
|
"Bring in web page title when pasting URL on editor": "Vložit název webové stránky při zkopírování URL do editoru",
|
||||||
|
"Preview": "Náhled",
|
||||||
|
"Preview Font Size": "Velikost písma v náhledu",
|
||||||
|
"Preview Font Family": "Rodina písma v náhledu",
|
||||||
|
"Code Block Theme": "Téma bloku kódu",
|
||||||
|
"Allow preview to scroll past the last line": "Povolit v náhledu scrolování za poslední řádek",
|
||||||
|
"Show line numbers for preview code blocks": "Zobrazit čísla řádků v náhledu bloků kódu",
|
||||||
|
"LaTeX Inline Open Delimiter": "inline otevírací oddělovač v LaTeX",
|
||||||
|
"LaTeX Inline Close Delimiter": "inline uzavírací oddělovač v LaTeX",
|
||||||
|
"LaTeX Block Open Delimiter": "otevírací oddělovač bloku v LaTeX",
|
||||||
|
"LaTeX Block Close Delimiter": "uzavírací oddělovač bloku v LaTeX",
|
||||||
|
"PlantUML Server": "PlantUML server",
|
||||||
|
"Community": "Komunita",
|
||||||
|
"Subscribe to Newsletter": "Přihlásit se k odběru novinek",
|
||||||
|
"GitHub": "GitHub",
|
||||||
|
"Blog": "Blog",
|
||||||
|
"Facebook Group": "Facebook Skupina",
|
||||||
|
"Twitter": "Twitter",
|
||||||
|
"About": "O aplikaci",
|
||||||
|
"Boostnote": "Boostnote",
|
||||||
|
"An open source note-taking app made for programmers just like you.": "Open source aplikace pro tvorbu poznámek vytvořená programátory jako jste vy.",
|
||||||
|
"Website": "Webová stránka",
|
||||||
|
"Development": "Vývoj",
|
||||||
|
" : Development configurations for Boostnote.": " : Vývojové konfigurace pro Boostnote.",
|
||||||
|
"Copyright (C) 2017 - 2019 BoostIO": "Copyright (C) 2017 - 2019 BoostIO",
|
||||||
|
"License: GPL v3": "License: GPL v3",
|
||||||
|
"Analytics": "Analytika",
|
||||||
|
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote sbírá anonymní data pouze pro účely zlepšování aplikace, a v žádném případě nesbírá žádné osobní údaje, jako je například obsah vašich poznámek.",
|
||||||
|
"You can see how it works on ": "Můžete se podívat, jak to funguje ",
|
||||||
|
"You can choose to enable or disable this option.": "Tuto možnost můžete povolit nebo zakázat.",
|
||||||
|
"Enable analytics to help improve Boostnote": "Povolit analytiku pro další zlepšování Boostnote",
|
||||||
|
"Crowdfunding": "Crowdfunding",
|
||||||
|
"Dear Boostnote users,": "Vážení uživatelé Boostnote,",
|
||||||
|
"Thank you for using Boostnote!": "Děkujeme, že používáte Boostnote!",
|
||||||
|
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote je používán v přibližně 200 různých zemích a regionech úžasnou komunitou vývojářů.",
|
||||||
|
"To support our growing userbase, and satisfy community expectations,": "Abychom podpořili rostoucí uživatelskou základnu a naplnili očekávání komunity,",
|
||||||
|
"we would like to invest more time and resources in this project.": "rádi bychom do tohoto projektu investovali více času a zdrojů.",
|
||||||
|
"If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "Pokud používáte Boostnote a vidíte jeho potenciál, pomozte nám podporou projektu na OpenCollective!",
|
||||||
|
"Thanks,": "Děkujeme,",
|
||||||
|
"The Boostnote Team": "Tým Boostnote",
|
||||||
|
"Support via OpenCollective": "Podpořit přes OpenCollective",
|
||||||
|
"Language": "Jazyk",
|
||||||
|
"Default New Note": "Výchozí nová poznámka",
|
||||||
|
"English": "Angličtina",
|
||||||
|
"German": "Němčina",
|
||||||
|
"French": "Francouzština",
|
||||||
|
"Show \"Saved to Clipboard\" notification when copying": "Zobrazit při kopírování upozornění \"Uloženo do schránky\"",
|
||||||
|
"All Notes": "Všechny poznámky",
|
||||||
|
"Starred": "Oblíbené",
|
||||||
|
"Are you sure to ": "Opravdu ",
|
||||||
|
" delete": " odstranit",
|
||||||
|
"this folder?": "tuto složku?",
|
||||||
|
"Confirm": "Potvrdit",
|
||||||
|
"Cancel": "Storno",
|
||||||
|
"Markdown Note": "Markdown poznámka",
|
||||||
|
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "Tento formát je pro tvorbu textových dokumentů. Zaškrtávací seznamy, bloky kódu a Latex bloky jsou dostupné.",
|
||||||
|
"Snippet Note": "Útržek kódu",
|
||||||
|
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "Tento formát je pro tvorbu útržků kódu. Do jedné poznámky lze seskupit více útržků.",
|
||||||
|
"Tab to switch format": "Pro přepnutí formátu zmáčkněte Tab",
|
||||||
|
"Updated": "Aktualizováno",
|
||||||
|
"Created": "Vytvořeno",
|
||||||
|
"Alphabetically": "Abecedně",
|
||||||
|
"Counter": "Počítadlo",
|
||||||
|
"Default View": "Výchozí zobrazení",
|
||||||
|
"Compressed View": "Komprimované zobrazení",
|
||||||
|
"Search": "Vyhledat",
|
||||||
|
"Blog Type": "Typ blogu",
|
||||||
|
"Blog Address": "Adresa blogu",
|
||||||
|
"Save": "Uložit",
|
||||||
|
"Auth": "Autentizace",
|
||||||
|
"Authentication Method": "Autentizační metoda",
|
||||||
|
"JWT": "JWT",
|
||||||
|
"USER": "UŽIVATEL",
|
||||||
|
"Token": "Token",
|
||||||
|
"Storage": "Uložiště",
|
||||||
|
"Hotkeys": "Klávesové zkratky",
|
||||||
|
"Show/Hide Boostnote": "Zobrazit/skrýt Boostnote",
|
||||||
|
"Toggle Editor Mode": "Přepnout režim editoru",
|
||||||
|
"Delete Note": "Odstranit poznámku",
|
||||||
|
"Restore": "Obnovit",
|
||||||
|
"Permanent Delete": "Trvale odstranit",
|
||||||
|
"Confirm note deletion": "Potvrdit odstranění poznámky",
|
||||||
|
"This will permanently remove this note.": "Tato akce trvale odstraní poznámku.",
|
||||||
|
"Successfully applied!": "Úspěšně aplikováno!",
|
||||||
|
"Albanian": "Albánština",
|
||||||
|
"Chinese (zh-CN)": "Čínština (zjednodušená)",
|
||||||
|
"Chinese (zh-TW)": "Čínština (tradiční)",
|
||||||
|
"Danish": "Dánština",
|
||||||
|
"Japanese": "Japonština",
|
||||||
|
"Korean": "Korejština",
|
||||||
|
"Norwegian": "Norština",
|
||||||
|
"Polish": "Polština",
|
||||||
|
"Portuguese": "Portugalština",
|
||||||
|
"Spanish": "Španělština",
|
||||||
|
"Unsaved Changes!": "Neuložené změny!",
|
||||||
|
"UserName": "Uživatelské jméno",
|
||||||
|
"Password": "Heslo",
|
||||||
|
"Russian": "Rusky",
|
||||||
|
"Hungarian": "Maďarsky",
|
||||||
|
"Thai": "Thajština (ภาษาไทย)",
|
||||||
|
"Command(⌘)": "Command(⌘)",
|
||||||
|
"Add Storage": "Přidat úložiště",
|
||||||
|
"Name": "Jméno",
|
||||||
|
"Type": "Typ",
|
||||||
|
"File System": "Souborový systém",
|
||||||
|
"Setting up 3rd-party cloud storage integration:": "Nastavení integrace s úložištěm třetí strany:",
|
||||||
|
"Cloud-Syncing-and-Backup": "Synchronizace a záloha do cloudu",
|
||||||
|
"Location": "Umístění",
|
||||||
|
"Add": "Přidat",
|
||||||
|
"Unlink Storage": "Odpojit úložiště",
|
||||||
|
"Unlinking removes this linked storage from Boostnote. No data is removed, please manually delete the folder from your hard drive if needed.": "Odpojení odstraní toto připojené úložiště z Boostnote. Žádná data nebudou odstraněna, prosím odstraňte složku z vašeho pevného disku manuálně.",
|
||||||
|
"Editor Rulers": "Pravítka v editoru",
|
||||||
|
"Enable": "Povolit",
|
||||||
|
"Disable": "Zakázat",
|
||||||
|
"Sanitization": "Sanitace",
|
||||||
|
"Only allow secure html tags (recommended)": "Povolit pouze bezpečné html tagy (doporučeno)",
|
||||||
|
"Render newlines in Markdown paragraphs as <br>": "Vykreslit konce řádků v Markdown jako <br>",
|
||||||
|
"Allow styles": "Povolit styly",
|
||||||
|
"Allow dangerous html tags": "Povolit nebezpečné html tagy",
|
||||||
|
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Převést textové šipky do překrásných symbolů. ⚠ Toto bude kolidovat s použitím HTML komentářů ve vašem Markdown.",
|
||||||
|
"⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ Vložili jste odkaz směrující na přílohu, kterou nebylo možné v umístění úložiště této poznámky najít. Vložením odkazu směrujícího na přílohy je podporováno pouze v případě, že se zdrojové a cílového úložiště shodují. Raději sem prosím přílohu přetáhněte! ⚠",
|
||||||
|
"Spellcheck disabled": "Kontrola pravopisu zakázána",
|
||||||
|
"Save tags of a note in alphabetical order": "Uložit štítky poznámky v abecedním pořadí",
|
||||||
|
"Enable live count of notes": "Povolit zobrazení aktuálního počtu poznámek",
|
||||||
|
"Enable smart table editor": "Povolit chytrý editor tabulek",
|
||||||
|
"Snippet Default Language": "Výchozí jazyk kódu",
|
||||||
|
"New notes are tagged with the filtering tags": "Nové poznámky jsou opatřeny štítky z filtru",
|
||||||
|
"Show menu bar": "Zobrazit lištu menu",
|
||||||
|
"Auto Detect": "Automatická detekce",
|
||||||
|
"Enable HTML label in mermaid flowcharts": "Povolit HTML label v mermaid flowcharts ⚠ Tato možnost je potenciálním zdrojem XSS.",
|
||||||
|
"Wrap line in Snippet Note": "Ukončovat řádky v útržcích kódu"
|
||||||
|
}
|
||||||
320
locales/da.json
320
locales/da.json
@@ -1,160 +1,164 @@
|
|||||||
{
|
{
|
||||||
"Notes": "Notes",
|
"Notes": "Notes",
|
||||||
"Tags": "Tags",
|
"Tags": "Tags",
|
||||||
"Preferences": "Preferences",
|
"Preferences": "Preferences",
|
||||||
"Make a note": "Make a note",
|
"Make a note": "Make a note",
|
||||||
"Ctrl": "Ctrl",
|
"Ctrl": "Ctrl",
|
||||||
"Ctrl(^)": "Ctrl",
|
"Ctrl(^)": "Ctrl",
|
||||||
"to create a new note": "to create a new note",
|
"to create a new note": "to create a new note",
|
||||||
"Toggle Mode": "Toggle Mode",
|
"Toggle Mode": "Toggle Mode",
|
||||||
"Trash": "Trash",
|
"Trash": "Trash",
|
||||||
"MODIFICATION DATE": "MODIFICATION DATE",
|
"Ok": "Ok",
|
||||||
"Words": "Words",
|
"MODIFICATION DATE": "MODIFICATION DATE",
|
||||||
"Letters": "Letters",
|
"Words": "Words",
|
||||||
"STORAGE": "STORAGE",
|
"Letters": "Letters",
|
||||||
"FOLDER": "FOLDER",
|
"STORAGE": "STORAGE",
|
||||||
"CREATION DATE": "CREATION DATE",
|
"FOLDER": "FOLDER",
|
||||||
"NOTE LINK": "NOTE LINK",
|
"CREATION DATE": "CREATION DATE",
|
||||||
".md": ".md",
|
"NOTE LINK": "NOTE LINK",
|
||||||
".txt": ".txt",
|
".md": ".md",
|
||||||
".html": ".html",
|
".txt": ".txt",
|
||||||
".pdf": ".pdf",
|
".html": ".html",
|
||||||
"Print": "Print",
|
".pdf": ".pdf",
|
||||||
"Your preferences for Boostnote": "Your preferences for Boostnote",
|
"Print": "Print",
|
||||||
"Storage Locations": "Storage Locations",
|
"Your preferences for Boostnote": "Your preferences for Boostnote",
|
||||||
"Add Storage Location": "Add Storage Location",
|
"Storage Locations": "Storage Locations",
|
||||||
"Add Folder": "Add Folder",
|
"Add Storage Location": "Add Storage Location",
|
||||||
"Open Storage folder": "Open Storage folder",
|
"Add Folder": "Add Folder",
|
||||||
"Unlink": "Unlink",
|
"Open Storage folder": "Open Storage folder",
|
||||||
"Edit": "Edit",
|
"Unlink": "Unlink",
|
||||||
"Delete": "Delete",
|
"Edit": "Edit",
|
||||||
"Interface": "Interface",
|
"Delete": "Delete",
|
||||||
"Interface Theme": "Interface Theme",
|
"Interface": "Interface",
|
||||||
"Default": "Default",
|
"Interface Theme": "Interface Theme",
|
||||||
"White": "White",
|
"Default": "Default",
|
||||||
"Solarized Dark": "Solarized Dark",
|
"White": "White",
|
||||||
"Dark": "Dark",
|
"Solarized Dark": "Solarized Dark",
|
||||||
"Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes",
|
"Dark": "Dark",
|
||||||
"Editor Theme": "Editor Theme",
|
"Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes",
|
||||||
"Editor Font Size": "Editor Font Size",
|
"Editor Theme": "Editor Theme",
|
||||||
"Editor Font Family": "Editor Font Family",
|
"Editor Font Size": "Editor Font Size",
|
||||||
"Editor Indent Style": "Editor Indent Style",
|
"Editor Font Family": "Editor Font Family",
|
||||||
"Spaces": "Spaces",
|
"Editor Indent Style": "Editor Indent Style",
|
||||||
"Tabs": "Tabs",
|
"Spaces": "Spaces",
|
||||||
"Switch to Preview": "Switch to Preview",
|
"Tabs": "Tabs",
|
||||||
"When Editor Blurred": "When Editor Blurred",
|
"Switch to Preview": "Switch to Preview",
|
||||||
"When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click",
|
"When Editor Blurred": "When Editor Blurred",
|
||||||
"On Right Click": "On Right Click",
|
"When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click",
|
||||||
"Editor Keymap": "Editor Keymap",
|
"On Right Click": "On Right Click",
|
||||||
"default": "default",
|
"Editor Keymap": "Editor Keymap",
|
||||||
"vim": "vim",
|
"default": "default",
|
||||||
"emacs": "emacs",
|
"vim": "vim",
|
||||||
"⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap",
|
"emacs": "emacs",
|
||||||
"Show line numbers in the editor": "Show line numbers in the editor",
|
"⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap",
|
||||||
"Allow editor to scroll past the last line": "Allow editor to scroll past the last line",
|
"Show line numbers in the editor": "Show line numbers in the editor",
|
||||||
"Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor",
|
"Allow editor to scroll past the last line": "Allow editor to scroll past the last line",
|
||||||
"Preview": "Preview",
|
"Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor",
|
||||||
"Preview Font Size": "Preview Font Size",
|
"Preview": "Preview",
|
||||||
"Preview Font Family": "Preview Font Family",
|
"Preview Font Size": "Preview Font Size",
|
||||||
"Code Block Theme": "Code Block Theme",
|
"Preview Font Family": "Preview Font Family",
|
||||||
"Allow preview to scroll past the last line": "Allow preview to scroll past the last line",
|
"Code Block Theme": "Code Block Theme",
|
||||||
"Show line numbers for preview code blocks": "Show line numbers for preview code blocks",
|
"Allow preview to scroll past the last line": "Allow preview to scroll past the last line",
|
||||||
"LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter",
|
"Show line numbers for preview code blocks": "Show line numbers for preview code blocks",
|
||||||
"LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter",
|
"LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter",
|
||||||
"LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter",
|
"LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter",
|
||||||
"LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter",
|
"LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter",
|
||||||
"PlantUML Server": "PlantUML Server",
|
"LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter",
|
||||||
"Community": "Community",
|
"PlantUML Server": "PlantUML Server",
|
||||||
"Subscribe to Newsletter": "Subscribe to Newsletter",
|
"Community": "Community",
|
||||||
"GitHub": "GitHub",
|
"Subscribe to Newsletter": "Subscribe to Newsletter",
|
||||||
"Blog": "Blog",
|
"GitHub": "GitHub",
|
||||||
"Facebook Group": "Facebook Group",
|
"Blog": "Blog",
|
||||||
"Twitter": "Twitter",
|
"Facebook Group": "Facebook Group",
|
||||||
"About": "About",
|
"Twitter": "Twitter",
|
||||||
"Boostnote": "Boostnote",
|
"About": "About",
|
||||||
"An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.",
|
"Boostnote": "Boostnote",
|
||||||
"Website": "Website",
|
"An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.",
|
||||||
"Development": "Development",
|
"Website": "Website",
|
||||||
" : Development configurations for Boostnote.": " : Development configurations for Boostnote.",
|
"Development": "Development",
|
||||||
"Copyright (C) 2017 - 2019 BoostIO": "Copyright (C) 2017 - 2019 BoostIO",
|
" : Development configurations for Boostnote.": " : Development configurations for Boostnote.",
|
||||||
"License: GPL v3": "License: GPL v3",
|
"Copyright (C) 2017 - 2019 BoostIO": "Copyright (C) 2017 - 2019 BoostIO",
|
||||||
"Analytics": "Analytics",
|
"License: GPL v3": "License: GPL v3",
|
||||||
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.",
|
"Analytics": "Analytics",
|
||||||
"You can see how it works on ": "You can see how it works on ",
|
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.",
|
||||||
"You can choose to enable or disable this option.": "You can choose to enable or disable this option.",
|
"You can see how it works on ": "You can see how it works on ",
|
||||||
"Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote",
|
"You can choose to enable or disable this option.": "You can choose to enable or disable this option.",
|
||||||
"Crowdfunding": "Crowdfunding",
|
"Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote",
|
||||||
"Dear Boostnote users,": "Dear Boostnote users,",
|
"Crowdfunding": "Crowdfunding",
|
||||||
"Thank you for using Boostnote!": "Thank you for using Boostnote!",
|
"Dear Boostnote users,": "Dear Boostnote users,",
|
||||||
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.",
|
"Thank you for using Boostnote!": "Thank you for using Boostnote!",
|
||||||
"To support our growing userbase, and satisfy community expectations,": "To support our growing userbase, and satisfy community expectations,",
|
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.",
|
||||||
"we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.",
|
"To support our growing userbase, and satisfy community expectations,": "To support our growing userbase, and satisfy community expectations,",
|
||||||
"If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!",
|
"we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.",
|
||||||
"Thanks,": "Thanks,",
|
"If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!",
|
||||||
"The Boostnote Team": "The Boostnote Team",
|
"Thanks,": "Thanks,",
|
||||||
"Support via OpenCollective": "Support via OpenCollective",
|
"The Boostnote Team": "The Boostnote Team",
|
||||||
"Language": "Language",
|
"Support via OpenCollective": "Support via OpenCollective",
|
||||||
"English": "English",
|
"Language": "Language",
|
||||||
"German": "German",
|
"English": "English",
|
||||||
"French": "French",
|
"German": "German",
|
||||||
"Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying",
|
"French": "French",
|
||||||
"All Notes": "All Notes",
|
"Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying",
|
||||||
"Starred": "Starred",
|
"All Notes": "All Notes",
|
||||||
"Are you sure to ": "Are you sure to ",
|
"Starred": "Starred",
|
||||||
" delete": " delete",
|
"Are you sure to ": "Are you sure to ",
|
||||||
"this folder?": "this folder?",
|
" delete": " delete",
|
||||||
"Confirm": "Confirm",
|
"this folder?": "this folder?",
|
||||||
"Cancel": "Cancel",
|
"Confirm": "Confirm",
|
||||||
"Markdown Note": "Markdown Note",
|
"Cancel": "Cancel",
|
||||||
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.",
|
"Markdown Note": "Markdown Note",
|
||||||
"Snippet Note": "Snippet Note",
|
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.",
|
||||||
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.",
|
"Snippet Note": "Snippet Note",
|
||||||
"Tab to switch format": "Tab to switch format",
|
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.",
|
||||||
"Updated": "Updated",
|
"Tab to switch format": "Tab to switch format",
|
||||||
"Created": "Created",
|
"Updated": "Updated",
|
||||||
"Alphabetically": "Alphabetically",
|
"Created": "Created",
|
||||||
"Default View": "Default View",
|
"Alphabetically": "Alphabetically",
|
||||||
"Compressed View": "Compressed View",
|
"Default View": "Default View",
|
||||||
"Search": "Search",
|
"Compressed View": "Compressed View",
|
||||||
"Blog Type": "Blog Type",
|
"Search": "Search",
|
||||||
"Blog Address": "Blog Address",
|
"Blog Type": "Blog Type",
|
||||||
"Save": "Save",
|
"Blog Address": "Blog Address",
|
||||||
"Auth": "Auth",
|
"Save": "Save",
|
||||||
"Authentication Method": "Authentication Method",
|
"Auth": "Auth",
|
||||||
"JWT": "JWT",
|
"Authentication Method": "Authentication Method",
|
||||||
"USER": "USER",
|
"JWT": "JWT",
|
||||||
"Token": "Token",
|
"USER": "USER",
|
||||||
"Storage": "Storage",
|
"Token": "Token",
|
||||||
"Hotkeys": "Hotkeys",
|
"Storage": "Storage",
|
||||||
"Show/Hide Boostnote": "Show/Hide Boostnote",
|
"Hotkeys": "Hotkeys",
|
||||||
"Restore": "Restore",
|
"Show/Hide Boostnote": "Show/Hide Boostnote",
|
||||||
"Permanent Delete": "Permanent Delete",
|
"Restore": "Restore",
|
||||||
"Confirm note deletion": "Confirm note deletion",
|
"Permanent Delete": "Permanent Delete",
|
||||||
"This will permanently remove this note.": "This will permanently remove this note.",
|
"Confirm note deletion": "Confirm note deletion",
|
||||||
"Successfully applied!": "Successfully applied!",
|
"This will permanently remove this note.": "This will permanently remove this note.",
|
||||||
"Albanian": "Albanian",
|
"Successfully applied!": "Successfully applied!",
|
||||||
"Chinese (zh-CN)": "Chinese (zh-CN)",
|
"Albanian": "Albanian",
|
||||||
"Chinese (zh-TW)": "Chinese (zh-TW)",
|
"Chinese (zh-CN)": "Chinese (zh-CN)",
|
||||||
"Danish": "Danish",
|
"Chinese (zh-TW)": "Chinese (zh-TW)",
|
||||||
"Japanese": "Japanese",
|
"Czech": "Czech",
|
||||||
"Korean": "Korean",
|
"Danish": "Danish",
|
||||||
"Norwegian": "Norwegian",
|
"Japanese": "Japanese",
|
||||||
"Polish": "Polish",
|
"Korean": "Korean",
|
||||||
"Portuguese": "Portuguese",
|
"Norwegian": "Norwegian",
|
||||||
"Spanish": "Spanish",
|
"Polish": "Polish",
|
||||||
"Unsaved Changes!": "Unsaved Changes!",
|
"Portuguese": "Portuguese",
|
||||||
"Russian": "Russian",
|
"Spanish": "Spanish",
|
||||||
"Command(⌘)": "Command(⌘)",
|
"Unsaved Changes!": "Unsaved Changes!",
|
||||||
"Editor Rulers": "Editor Rulers",
|
"Russian": "Russian",
|
||||||
"Enable": "Enable",
|
"Command(⌘)": "Command(⌘)",
|
||||||
"Disable": "Disable",
|
"Editor Rulers": "Editor Rulers",
|
||||||
"Sanitization": "Sanitization",
|
"Enable": "Enable",
|
||||||
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
|
"Disable": "Disable",
|
||||||
"Allow styles": "Allow styles",
|
"Sanitization": "Sanitization",
|
||||||
"Allow dangerous html tags": "Allow dangerous html tags",
|
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
|
||||||
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.",
|
"Allow styles": "Allow styles",
|
||||||
"⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠",
|
"Allow dangerous html tags": "Allow dangerous html tags",
|
||||||
"Spellcheck disabled": "Spellcheck disabled",
|
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.",
|
||||||
"Show menu bar": "Show menu bar",
|
"⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠",
|
||||||
"Auto Detect": "Auto Detect"
|
"Spellcheck disabled": "Spellcheck disabled",
|
||||||
|
"Show menu bar": "Show menu bar",
|
||||||
|
"Auto Detect": "Auto Detect",
|
||||||
|
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
|
||||||
|
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
|
||||||
}
|
}
|
||||||
|
|||||||
432
locales/de.json
432
locales/de.json
@@ -1,216 +1,220 @@
|
|||||||
{
|
{
|
||||||
"Notes": "Notizen",
|
"Notes": "Notizen",
|
||||||
"Tags": "Tags",
|
"Tags": "Tags",
|
||||||
"Preferences": "Einstellungen",
|
"Preferences": "Einstellungen",
|
||||||
"Make a note": "Notiz erstellen",
|
"Make a note": "Notiz erstellen",
|
||||||
"Ctrl": "Strg",
|
"Ctrl": "Strg",
|
||||||
"Ctrl(^)": "Strg",
|
"Ctrl(^)": "Strg",
|
||||||
"to create a new note": "um eine neue Notiz zu erstellen",
|
"to create a new note": "um eine neue Notiz zu erstellen",
|
||||||
"Toggle Mode": "Modus umschalten",
|
"Toggle Mode": "Modus umschalten",
|
||||||
"Trash": "Papierkorb",
|
"Trash": "Papierkorb",
|
||||||
"MODIFICATION DATE": "ÄNDERUNGSDATUM",
|
"Ok": "Ok",
|
||||||
"Words": "Wörter",
|
"MODIFICATION DATE": "ÄNDERUNGSDATUM",
|
||||||
"Letters": "Buchstaben",
|
"Words": "Wörter",
|
||||||
"STORAGE": "SPEICHERORT",
|
"Letters": "Buchstaben",
|
||||||
"FOLDER": "ORDNER",
|
"STORAGE": "SPEICHERORT",
|
||||||
"CREATION DATE": "ERSTELLUNGSDATUM",
|
"FOLDER": "ORDNER",
|
||||||
"NOTE LINK": "NOTIZ LINK",
|
"CREATION DATE": "ERSTELLUNGSDATUM",
|
||||||
".md": ".md",
|
"NOTE LINK": "NOTIZ LINK",
|
||||||
".txt": ".txt",
|
".md": ".md",
|
||||||
".html": ".html",
|
".txt": ".txt",
|
||||||
".pdf": ".pdf",
|
".html": ".html",
|
||||||
"Print": "Drucken",
|
".pdf": ".pdf",
|
||||||
"Your preferences for Boostnote": "Boostnote Einstellungen",
|
"Print": "Drucken",
|
||||||
"Storage Locations": "Speicherverwaltung",
|
"Your preferences for Boostnote": "Boostnote Einstellungen",
|
||||||
"Add Storage Location": "Speicherort hinzufügen",
|
"Storage Locations": "Speicherverwaltung",
|
||||||
"Add Folder": "Ordner hinzufügen",
|
"Add Storage Location": "Speicherort hinzufügen",
|
||||||
"Open Storage folder": "Speicherort öffnen",
|
"Add Folder": "Ordner hinzufügen",
|
||||||
"Unlink": "Verknüpfung aufheben",
|
"Open Storage folder": "Speicherort öffnen",
|
||||||
"Edit": "Bearbeiten",
|
"Unlink": "Verknüpfung aufheben",
|
||||||
"Delete": "Löschen",
|
"Edit": "Bearbeiten",
|
||||||
"Interface": "Darstellung",
|
"Delete": "Löschen",
|
||||||
"Interface Theme": "Stil",
|
"Interface": "Darstellung",
|
||||||
"Default": "Standard",
|
"Interface Theme": "Stil",
|
||||||
"White": "Hell",
|
"Default": "Standard",
|
||||||
"Solarized Dark": "Solarized Dark",
|
"White": "Hell",
|
||||||
"Dark": "Dunkel",
|
"Solarized Dark": "Solarized Dark",
|
||||||
"Show a confirmation dialog when deleting notes": "Bestätigungsdialog beim Löschen von Notizen anzeigen",
|
"Dark": "Dunkel",
|
||||||
"Editor Theme": "Editor Theme",
|
"Show a confirmation dialog when deleting notes": "Bestätigungsdialog beim Löschen von Notizen anzeigen",
|
||||||
"Editor Font Size": "Editor Schriftgröße",
|
"Editor Theme": "Editor Theme",
|
||||||
"Editor Font Family": "Editor Schriftart",
|
"Editor Font Size": "Editor Schriftgröße",
|
||||||
"Editor Indent Style": "Editor Einrückestil",
|
"Editor Font Family": "Editor Schriftart",
|
||||||
"Spaces": "Leerzeichen",
|
"Editor Indent Style": "Editor Einrückestil",
|
||||||
"Tabs": "Tabs",
|
"Spaces": "Leerzeichen",
|
||||||
"Switch to Preview": "Zur Vorschau wechseln",
|
"Tabs": "Tabs",
|
||||||
"When Editor Blurred": "Wenn Editor nicht fokusiert",
|
"Switch to Preview": "Zur Vorschau wechseln",
|
||||||
"When Editor Blurred, Edit On Double Click": "Mit Doppelklick bearbeiten, wenn Editor in Vorschaumodus",
|
"When Editor Blurred": "Wenn Editor nicht fokusiert",
|
||||||
"On Right Click": "Mit Rechtsklick",
|
"When Editor Blurred, Edit On Double Click": "Mit Doppelklick bearbeiten, wenn Editor in Vorschaumodus",
|
||||||
"Editor Keymap": "Editor Tastenbelegung",
|
"On Right Click": "Mit Rechtsklick",
|
||||||
"default": "Standard",
|
"Editor Keymap": "Editor Tastenbelegung",
|
||||||
"vim": "vim",
|
"default": "Standard",
|
||||||
"emacs": "emacs",
|
"vim": "vim",
|
||||||
"⚠️ Please restart boostnote after you change the keymap": "⚠️ Boostnote nach Änderung der Tastenbelegung neu starten",
|
"emacs": "emacs",
|
||||||
"Show line numbers in the editor": "Zeilennummern im Editor anzeigen",
|
"⚠️ Please restart boostnote after you change the keymap": "⚠️ Boostnote nach Änderung der Tastenbelegung neu starten",
|
||||||
"Allow editor to scroll past the last line": "Editor das Scrollen über das Ende hinaus erlauben",
|
"Show line numbers in the editor": "Zeilennummern im Editor anzeigen",
|
||||||
"Bring in web page title when pasting URL on editor": "Titel der Website beim Einfügen in den Editor anzeigen",
|
"Allow editor to scroll past the last line": "Editor das Scrollen über das Ende hinaus erlauben",
|
||||||
"Preview": "Vorschau",
|
"Bring in web page title when pasting URL on editor": "Titel der Website beim Einfügen in den Editor anzeigen",
|
||||||
"Preview Font Size": "Vorschau Schriftgröße",
|
"Preview": "Vorschau",
|
||||||
"Preview Font Family": "Vorschau Schriftart",
|
"Preview Font Size": "Vorschau Schriftgröße",
|
||||||
"Code Block Theme": "Code-Block Theme",
|
"Preview Font Family": "Vorschau Schriftart",
|
||||||
"Allow preview to scroll past the last line": "Vorschau das Scrollen über das Ende hinaus erlauben",
|
"Code Block Theme": "Code-Block Theme",
|
||||||
"Show line numbers for preview code blocks": "Zeilennummern in Vorschau-Code-Blöcken anzeigen",
|
"Allow preview to scroll past the last line": "Vorschau das Scrollen über das Ende hinaus erlauben",
|
||||||
"LaTeX Inline Open Delimiter": "LaTeX Inline Beginn Kennzeichen",
|
"Show line numbers for preview code blocks": "Zeilennummern in Vorschau-Code-Blöcken anzeigen",
|
||||||
"LaTeX Inline Close Delimiter": "LaTeX Inline Ende Kennzeichen",
|
"LaTeX Inline Open Delimiter": "LaTeX Inline Beginn Kennzeichen",
|
||||||
"LaTeX Block Open Delimiter": "LaTeX Block Beginn Kennzeichen",
|
"LaTeX Inline Close Delimiter": "LaTeX Inline Ende Kennzeichen",
|
||||||
"LaTeX Block Close Delimiter": "LaTeX Block Ende Kennzeichen",
|
"LaTeX Block Open Delimiter": "LaTeX Block Beginn Kennzeichen",
|
||||||
"PlantUML Server": "PlantUML Server",
|
"LaTeX Block Close Delimiter": "LaTeX Block Ende Kennzeichen",
|
||||||
"Community": "Community",
|
"PlantUML Server": "PlantUML Server",
|
||||||
"Subscribe to Newsletter": "Newsletter abonnieren",
|
"Community": "Community",
|
||||||
"GitHub": "GitHub",
|
"Subscribe to Newsletter": "Newsletter abonnieren",
|
||||||
"Blog": "Blog",
|
"GitHub": "GitHub",
|
||||||
"Facebook Group": "Facebook Gruppe",
|
"Blog": "Blog",
|
||||||
"Twitter": "Twitter",
|
"Facebook Group": "Facebook Gruppe",
|
||||||
"About": "Über",
|
"Twitter": "Twitter",
|
||||||
"Boostnote": "Boostnote",
|
"About": "Über",
|
||||||
"An open source note-taking app made for programmers just like you.": "Eine OpenSource-Notizapp für Programmierer wie du und ich.",
|
"Boostnote": "Boostnote",
|
||||||
"Website": "Website",
|
"An open source note-taking app made for programmers just like you.": "Eine OpenSource-Notizapp für Programmierer wie du und ich.",
|
||||||
"Development": "Entwicklung",
|
"Website": "Website",
|
||||||
" : Development configurations for Boostnote.": " : Entwicklungseinstellungen für Boostnote.",
|
"Development": "Entwicklung",
|
||||||
"Copyright (C) 2017 - 2019 BoostIO": "Copyright (C) 2017 - 2019 BoostIO",
|
" : Development configurations for Boostnote.": " : Entwicklungseinstellungen für Boostnote.",
|
||||||
"License: GPL v3": "License: GPL v3",
|
"Copyright (C) 2017 - 2019 BoostIO": "Copyright (C) 2017 - 2019 BoostIO",
|
||||||
"Analytics": "Analytics",
|
"License: GPL v3": "License: GPL v3",
|
||||||
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote sammelt anonyme Daten, um die App zu verbessern. Persönliche Informationen, wie z.B. der Inhalt deiner Notizen, werden dabei nicht erfasst.",
|
"Analytics": "Analytics",
|
||||||
"You can see how it works on ": "Wie das funktioniert, kannst du dir hier ansehen ",
|
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote sammelt anonyme Daten, um die App zu verbessern. Persönliche Informationen, wie z.B. der Inhalt deiner Notizen, werden dabei nicht erfasst.",
|
||||||
"You can choose to enable or disable this option.": "Du kannst wählen, ob du diese Option aktivieren oder daektivieren möchtest.",
|
"You can see how it works on ": "Wie das funktioniert, kannst du dir hier ansehen ",
|
||||||
"Enable analytics to help improve Boostnote": "Datenerhebung zur Verbesserung von Boostnote aktivieren",
|
"You can choose to enable or disable this option.": "Du kannst wählen, ob du diese Option aktivieren oder daektivieren möchtest.",
|
||||||
"Crowdfunding": "Crowdfunding",
|
"Enable analytics to help improve Boostnote": "Datenerhebung zur Verbesserung von Boostnote aktivieren",
|
||||||
"Dear Boostnote users,": "Hallo,",
|
"Crowdfunding": "Crowdfunding",
|
||||||
"Thank you for using Boostnote!": "Danke, dass du Boostnote verwendest.",
|
"Dear Boostnote users,": "Hallo,",
|
||||||
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote wird in über 200 verschiedenen Ländern von einer großartigen Community von Entwicklern verwendet.",
|
"Thank you for using Boostnote!": "Danke, dass du Boostnote verwendest.",
|
||||||
"To support our growing userbase, and satisfy community expectations,": "Um die Erwartungen der Community weiterhin erfüllen zu können und die Verbreitung von Boostnote weiter voranzutreiben,",
|
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote wird in über 200 verschiedenen Ländern von einer großartigen Community von Entwicklern verwendet.",
|
||||||
"we would like to invest more time and resources in this project.": "würden wir gern mehr Zeit und Resourcen in dieses Projekt investieren.",
|
"To support our growing userbase, and satisfy community expectations,": "Um die Erwartungen der Community weiterhin erfüllen zu können und die Verbreitung von Boostnote weiter voranzutreiben,",
|
||||||
"If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "Wenn dir dieses Projekt gefällt und du sein Potential erkennst, kannst du uns gern mit OpenCollective unterstützen!",
|
"we would like to invest more time and resources in this project.": "würden wir gern mehr Zeit und Resourcen in dieses Projekt investieren.",
|
||||||
"Thanks,": "Vielen Dank,",
|
"If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "Wenn dir dieses Projekt gefällt und du sein Potential erkennst, kannst du uns gern mit OpenCollective unterstützen!",
|
||||||
"The Boostnote Team": "Dein Boostnote Team",
|
"Thanks,": "Vielen Dank,",
|
||||||
"Support via OpenCollective": "Unterstützen mit OpenCollective",
|
"The Boostnote Team": "Dein Boostnote Team",
|
||||||
"Language": "Sprache",
|
"Support via OpenCollective": "Unterstützen mit OpenCollective",
|
||||||
"English": "Englisch",
|
"Language": "Sprache",
|
||||||
"German": "Deutsch",
|
"English": "Englisch",
|
||||||
"French": "Französisch",
|
"German": "Deutsch",
|
||||||
"Show \"Saved to Clipboard\" notification when copying": "\"Auf Clipboard gespeichert\" Benachrichtigungen beim Kopieren anzeigen",
|
"French": "Französisch",
|
||||||
"All Notes": "Alle Notizen",
|
"Show \"Saved to Clipboard\" notification when copying": "\"Auf Clipboard gespeichert\" Benachrichtigungen beim Kopieren anzeigen",
|
||||||
"Starred": "Markiert",
|
"All Notes": "Alle Notizen",
|
||||||
"Are you sure to ": "Sind sie sicher ",
|
"Starred": "Markiert",
|
||||||
" delete": " zu löschen",
|
"Are you sure to ": "Sind sie sicher ",
|
||||||
"this folder?": "diesen Ordner?",
|
" delete": " zu löschen",
|
||||||
"Confirm": "Bestätigen",
|
"this folder?": "diesen Ordner?",
|
||||||
"Cancel": "Abbrechen",
|
"Confirm": "Bestätigen",
|
||||||
"Markdown Note": "Markdown Notiz",
|
"Cancel": "Abbrechen",
|
||||||
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "Mit diesem Format kannst du einzelne Textdokumente erstellen. Dabei stehen dir Checklisten, Code- & Latex-Blöcke zur Verfügung.",
|
"Markdown Note": "Markdown Notiz",
|
||||||
"Snippet Note": "Codeschnipsel",
|
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "Mit diesem Format kannst du einzelne Textdokumente erstellen. Dabei stehen dir Checklisten, Code- & Latex-Blöcke zur Verfügung.",
|
||||||
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "Mit diesem Format kannst du mehrere Codeschnipsel erstellen und sie in einer Notiz zusammenfassen.",
|
"Snippet Note": "Codeschnipsel",
|
||||||
"Tab to switch format": "Tab drücken, um das Format zu wechseln",
|
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "Mit diesem Format kannst du mehrere Codeschnipsel erstellen und sie in einer Notiz zusammenfassen.",
|
||||||
"Updated": "Bearbeitet",
|
"Tab to switch format": "Tab drücken, um das Format zu wechseln",
|
||||||
"Created": "Erstellt",
|
"Updated": "Bearbeitet",
|
||||||
"Alphabetically": "Alphabetisch",
|
"Created": "Erstellt",
|
||||||
"Default View": "Standardansicht",
|
"Alphabetically": "Alphabetisch",
|
||||||
"Compressed View": "Kompaktansicht",
|
"Default View": "Standardansicht",
|
||||||
"Search": "Suchen",
|
"Compressed View": "Kompaktansicht",
|
||||||
"Blog Type": "Blog-Typ",
|
"Search": "Suchen",
|
||||||
"Blog Address": "Blog Adresse",
|
"Blog Type": "Blog-Typ",
|
||||||
"Save": "Speichern",
|
"Blog Address": "Blog Adresse",
|
||||||
"Auth": "Authentifizierung",
|
"Save": "Speichern",
|
||||||
"Authentication Method": "Authentifizierungsmethode",
|
"Auth": "Authentifizierung",
|
||||||
"JWT": "JWT",
|
"Authentication Method": "Authentifizierungsmethode",
|
||||||
"USER": "BENUTZER",
|
"JWT": "JWT",
|
||||||
"Token": "Token",
|
"USER": "BENUTZER",
|
||||||
"Storage": "Speicher",
|
"Token": "Token",
|
||||||
"Hotkeys": "Tastenkürzel",
|
"Storage": "Speicher",
|
||||||
"Show/Hide Boostnote": "Boostnote anzeigen/verstecken",
|
"Hotkeys": "Tastenkürzel",
|
||||||
"Restore": "Wiederherstellen",
|
"Show/Hide Boostnote": "Boostnote anzeigen/verstecken",
|
||||||
"Permanent Delete": "Dauerhaft löschen",
|
"Restore": "Wiederherstellen",
|
||||||
"Confirm note deletion": "Löschen bestätigen",
|
"Permanent Delete": "Dauerhaft löschen",
|
||||||
"This will permanently remove this note.": "Diese Notiz wird dauerhaft gelöscht.",
|
"Confirm note deletion": "Löschen bestätigen",
|
||||||
"Unsaved Changes!": "Speichern notwendig!",
|
"This will permanently remove this note.": "Diese Notiz wird dauerhaft gelöscht.",
|
||||||
"Albanian": "Albanisch",
|
"Unsaved Changes!": "Speichern notwendig!",
|
||||||
"Danish": "Dänisch",
|
"Albanian": "Albanisch",
|
||||||
"Japanese": "Japanisch",
|
"Czech": "Tschechisch",
|
||||||
"Korean": "Koreanisch",
|
"Danish": "Dänisch",
|
||||||
"Norwegian": "Norwegisch",
|
"Japanese": "Japanisch",
|
||||||
"Polish": "Polnisch",
|
"Korean": "Koreanisch",
|
||||||
"Portuguese": "Portugiesisch",
|
"Norwegian": "Norwegisch",
|
||||||
"Spanish": "Spanisch",
|
"Polish": "Polnisch",
|
||||||
"Chinese (zh-CN)": "Chinesisch (China)",
|
"Portuguese": "Portugiesisch",
|
||||||
"Chinese (zh-TW)": "Chinesisch (Taiwan)",
|
"Spanish": "Spanisch",
|
||||||
"Successfully applied!": "Erfolgreich gespeichert!",
|
"Chinese (zh-CN)": "Chinesisch (China)",
|
||||||
"UserName": "Benutzername",
|
"Chinese (zh-TW)": "Chinesisch (Taiwan)",
|
||||||
"Password": "Passwort",
|
"Successfully applied!": "Erfolgreich gespeichert!",
|
||||||
"Russian": "Russisch",
|
"UserName": "Benutzername",
|
||||||
"Thai": "Thai (ภาษาไทย)",
|
"Password": "Passwort",
|
||||||
"Command(⌘)": "Befehlstaste(⌘)",
|
"Russian": "Russisch",
|
||||||
"Editor Rulers": "Editor Trennline",
|
"Thai": "Thai (ภาษาไทย)",
|
||||||
"Enable": "Aktiviert",
|
"Command(⌘)": "Befehlstaste(⌘)",
|
||||||
"Disable": "Deaktiviert",
|
"Editor Rulers": "Editor Trennline",
|
||||||
"Sanitization": "Sanitization",
|
"Enable": "Aktiviert",
|
||||||
"Only allow secure html tags (recommended)": "Erlaube nur sichere HTML Tags (empfohlen)",
|
"Disable": "Deaktiviert",
|
||||||
"Allow styles": "Erlaube Styles",
|
"Sanitization": "Sanitization",
|
||||||
"Allow dangerous html tags": "Erlaube gefähliche HTML Tags",
|
"Only allow secure html tags (recommended)": "Erlaube nur sichere HTML Tags (empfohlen)",
|
||||||
"Select filter mode": "Wähle Filter Modus",
|
"Allow styles": "Erlaube Styles",
|
||||||
"Add tag...": "Tag hinzufügen...",
|
"Allow dangerous html tags": "Erlaube gefähliche HTML Tags",
|
||||||
"Star": "Markieren",
|
"Select filter mode": "Wähle Filter Modus",
|
||||||
"Fullscreen": "Vollbild",
|
"Add tag...": "Tag hinzufügen...",
|
||||||
"Info": "Info",
|
"Star": "Markieren",
|
||||||
"Remove pin": "Pin entfernen",
|
"Fullscreen": "Vollbild",
|
||||||
"Pin to Top": "Notiz anpinnen",
|
"Info": "Info",
|
||||||
"Delete Note": "Notiz löschen",
|
"Remove pin": "Pin entfernen",
|
||||||
"Clone Note": "Notiz duplizieren",
|
"Pin to Top": "Notiz anpinnen",
|
||||||
"Restore Note": "Notiz wiederherstellen",
|
"Delete Note": "Notiz löschen",
|
||||||
"Copy Note Link": "Link zur Notiz kopieren",
|
"Clone Note": "Notiz duplizieren",
|
||||||
"Publish Blog": "Auf Blog veröffentlichen",
|
"Restore Note": "Notiz wiederherstellen",
|
||||||
"Update Blog": "Blog aktualisieren",
|
"Copy Note Link": "Link zur Notiz kopieren",
|
||||||
"Open Blog": "Blog öffnen",
|
"Publish Blog": "Auf Blog veröffentlichen",
|
||||||
"Empty Trash": "Papierkorb leeren",
|
"Update Blog": "Blog aktualisieren",
|
||||||
"Rename Folder": "Ordner umbenennen",
|
"Open Blog": "Blog öffnen",
|
||||||
"Export Folder": "Ordner exportieren",
|
"Empty Trash": "Papierkorb leeren",
|
||||||
"Export as txt": "Exportieren als txt",
|
"Rename Folder": "Ordner umbenennen",
|
||||||
"Export as md": "Exportieren als md",
|
"Export Folder": "Ordner exportieren",
|
||||||
"Delete Folder": "Ordner löschen",
|
"Export as txt": "Exportieren als txt",
|
||||||
"Select directory": "Ordner auswählen",
|
"Export as md": "Exportieren als md",
|
||||||
"Select a folder to export the files to": "Wähle einen Ordner zum Export der Dateien",
|
"Delete Folder": "Ordner löschen",
|
||||||
"Description...": "Beschreibung...",
|
"Select directory": "Ordner auswählen",
|
||||||
"Publish Failed": "Veröffentlichung fehlgeschlagen",
|
"Select a folder to export the files to": "Wähle einen Ordner zum Export der Dateien",
|
||||||
"Check and update your blog setting and try again.": "Prüfe und aktualisiere deine Blog Einstellungen und versuche es noch einmal.",
|
"Description...": "Beschreibung...",
|
||||||
"Delete a snippet": "Codeschnipsel löschen",
|
"Publish Failed": "Veröffentlichung fehlgeschlagen",
|
||||||
"This work cannot be undone.": "Diese Aktion kann nicht rückgängig gemacht werden.",
|
"Check and update your blog setting and try again.": "Prüfe und aktualisiere deine Blog Einstellungen und versuche es noch einmal.",
|
||||||
"Help": "Hilfe",
|
"Delete a snippet": "Codeschnipsel löschen",
|
||||||
"Hungarian": "Ungarisch",
|
"This work cannot be undone.": "Diese Aktion kann nicht rückgängig gemacht werden.",
|
||||||
"Hide Help": "Hilfe verstecken",
|
"Help": "Hilfe",
|
||||||
"wordpress": "Wordpress",
|
"Hungarian": "Ungarisch",
|
||||||
"Add Storage": "Speicher hinzufügen",
|
"Hide Help": "Hilfe verstecken",
|
||||||
"Name": "Name",
|
"wordpress": "Wordpress",
|
||||||
"Type": "Typ",
|
"Add Storage": "Speicher hinzufügen",
|
||||||
"File System": "Dateisystem",
|
"Name": "Name",
|
||||||
"Setting up 3rd-party cloud storage integration:": "Integration von Cloudspeicher externer Anbieter einrichten:",
|
"Type": "Typ",
|
||||||
"Cloud-Syncing-and-Backup": "Cloud-Syncing-and-Backup",
|
"File System": "Dateisystem",
|
||||||
"Location": "Ort",
|
"Setting up 3rd-party cloud storage integration:": "Integration von Cloudspeicher externer Anbieter einrichten:",
|
||||||
"Add": "Hinzufügen",
|
"Cloud-Syncing-and-Backup": "Cloud-Syncing-and-Backup",
|
||||||
"Available Keys": "Verfügbare Tasten",
|
"Location": "Ort",
|
||||||
"Select Directory": "Ordner auswählen",
|
"Add": "Hinzufügen",
|
||||||
"copy": "Kopie",
|
"Available Keys": "Verfügbare Tasten",
|
||||||
"Create new folder": "Ordner erstellen",
|
"Select Directory": "Ordner auswählen",
|
||||||
"Folder name": "Ordnername",
|
"copy": "Kopie",
|
||||||
"Create": "Erstellen",
|
"Create new folder": "Ordner erstellen",
|
||||||
"Untitled": "Neuer Ordner",
|
"Folder name": "Ordnername",
|
||||||
"Unlink Storage": "Speicherverknüpfung aufheben",
|
"Create": "Erstellen",
|
||||||
"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.",
|
"Untitled": "Neuer Ordner",
|
||||||
"Empty note": "Leere Notiz",
|
"Unlink Storage": "Speicherverknüpfung aufheben",
|
||||||
"Unnamed": "Unbenannt",
|
"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.",
|
||||||
"Rename": "Umbenennen",
|
"Empty note": "Leere Notiz",
|
||||||
"Folder Name": "Ordnername",
|
"Unnamed": "Unbenannt",
|
||||||
"No tags": "Keine Tags",
|
"Rename": "Umbenennen",
|
||||||
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.",
|
"Folder Name": "Ordnername",
|
||||||
"⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠",
|
"No tags": "Keine Tags",
|
||||||
"Spellcheck disabled": "Spellcheck disabled",
|
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.",
|
||||||
"Show menu bar": "Show menu bar",
|
"⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠",
|
||||||
"Auto Detect": "Auto Detect"
|
"Spellcheck disabled": "Spellcheck disabled",
|
||||||
|
"Show menu bar": "Show menu bar",
|
||||||
|
"Auto Detect": "Auto Detect",
|
||||||
|
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
|
||||||
|
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
|
||||||
}
|
}
|
||||||
|
|||||||
383
locales/en.json
383
locales/en.json
@@ -1,191 +1,196 @@
|
|||||||
{
|
{
|
||||||
"Notes": "Notes",
|
"Notes": "Notes",
|
||||||
"Tags": "Tags",
|
"Tags": "Tags",
|
||||||
"Preferences": "Preferences",
|
"Preferences": "Preferences",
|
||||||
"Make a note": "Make a note",
|
"Make a note": "Make a note",
|
||||||
"Ctrl": "Ctrl",
|
"Ctrl": "Ctrl",
|
||||||
"Ctrl(^)": "Ctrl(^)",
|
"Ctrl(^)": "Ctrl(^)",
|
||||||
"to create a new note": "to create a new note",
|
"to create a new note": "to create a new note",
|
||||||
"Toggle Mode": "Toggle Mode",
|
"Toggle Mode": "Toggle Mode",
|
||||||
"Add tag...": "Add tag...",
|
"Add tag...": "Add tag...",
|
||||||
"Trash": "Trash",
|
"Trash": "Trash",
|
||||||
"MODIFICATION DATE": "MODIFICATION DATE",
|
"Ok": "Ok",
|
||||||
"Words": "Words",
|
"MODIFICATION DATE": "MODIFICATION DATE",
|
||||||
"Letters": "Letters",
|
"Words": "Words",
|
||||||
"STORAGE": "STORAGE",
|
"Letters": "Letters",
|
||||||
"FOLDER": "FOLDER",
|
"STORAGE": "STORAGE",
|
||||||
"CREATION DATE": "CREATION DATE",
|
"FOLDER": "FOLDER",
|
||||||
"NOTE LINK": "NOTE LINK",
|
"CREATION DATE": "CREATION DATE",
|
||||||
".md": ".md",
|
"NOTE LINK": "NOTE LINK",
|
||||||
".txt": ".txt",
|
".md": ".md",
|
||||||
".html": ".html",
|
".txt": ".txt",
|
||||||
".pdf": ".pdf",
|
".html": ".html",
|
||||||
"Print": "Print",
|
".pdf": ".pdf",
|
||||||
"Your preferences for Boostnote": "Your preferences for Boostnote",
|
"Print": "Print",
|
||||||
"Help": "Help",
|
"Your preferences for Boostnote": "Your preferences for Boostnote",
|
||||||
"Hide Help": "Hide Help",
|
"Help": "Help",
|
||||||
"Storage Locations": "Storage Locations",
|
"Hide Help": "Hide Help",
|
||||||
"Add Storage Location": "Add Storage Location",
|
"Storage Locations": "Storage Locations",
|
||||||
"Add Folder": "Add Folder",
|
"Add Storage Location": "Add Storage Location",
|
||||||
"Select Folder": "Select Folder",
|
"Add Folder": "Add Folder",
|
||||||
"Open Storage folder": "Open Storage folder",
|
"Select Folder": "Select Folder",
|
||||||
"Unlink": "Unlink",
|
"Open Storage folder": "Open Storage folder",
|
||||||
"Edit": "Edit",
|
"Unlink": "Unlink",
|
||||||
"Delete": "Delete",
|
"Edit": "Edit",
|
||||||
"Interface": "Interface",
|
"Delete": "Delete",
|
||||||
"Interface Theme": "Interface Theme",
|
"Interface": "Interface",
|
||||||
"Default": "Default",
|
"Interface Theme": "Interface Theme",
|
||||||
"White": "White",
|
"Default": "Default",
|
||||||
"Solarized Dark": "Solarized Dark",
|
"White": "White",
|
||||||
"Dark": "Dark",
|
"Solarized Dark": "Solarized Dark",
|
||||||
"Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes",
|
"Dark": "Dark",
|
||||||
"Disable Direct Write (It will be applied after restarting)": "Disable Direct Write (It will be applied after restarting)",
|
"Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes",
|
||||||
"Show only related tags": "Show only related tags",
|
"Disable Direct Write (It will be applied after restarting)": "Disable Direct Write (It will be applied after restarting)",
|
||||||
"Editor Theme": "Editor Theme",
|
"Show only related tags": "Show only related tags",
|
||||||
"Editor Font Size": "Editor Font Size",
|
"Editor Theme": "Editor Theme",
|
||||||
"Editor Font Family": "Editor Font Family",
|
"Editor Font Size": "Editor Font Size",
|
||||||
"Editor Indent Style": "Editor Indent Style",
|
"Editor Font Family": "Editor Font Family",
|
||||||
"Spaces": "Spaces",
|
"Editor Indent Style": "Editor Indent Style",
|
||||||
"Tabs": "Tabs",
|
"Spaces": "Spaces",
|
||||||
"Switch to Preview": "Switch to Preview",
|
"Tabs": "Tabs",
|
||||||
"When Editor Blurred": "When Editor Blurred",
|
"Switch to Preview": "Switch to Preview",
|
||||||
"When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click",
|
"When Editor Blurred": "When Editor Blurred",
|
||||||
"On Right Click": "On Right Click",
|
"When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click",
|
||||||
"Editor Keymap": "Editor Keymap",
|
"On Right Click": "On Right Click",
|
||||||
"default": "default",
|
"Editor Keymap": "Editor Keymap",
|
||||||
"vim": "vim",
|
"default": "default",
|
||||||
"emacs": "emacs",
|
"vim": "vim",
|
||||||
"⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap",
|
"emacs": "emacs",
|
||||||
"Show line numbers in the editor": "Show line numbers in the editor",
|
"⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap",
|
||||||
"Allow editor to scroll past the last line": "Allow editor to scroll past the last line",
|
"Show line numbers in the editor": "Show line numbers in the editor",
|
||||||
"Enable smart quotes": "Enable smart quotes",
|
"Allow editor to scroll past the last line": "Allow editor to scroll past the last line",
|
||||||
"Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor",
|
"Enable smart quotes": "Enable smart quotes",
|
||||||
"Preview": "Preview",
|
"Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor",
|
||||||
"Preview Font Size": "Preview Font Size",
|
"Preview": "Preview",
|
||||||
"Preview Font Family": "Preview Font Family",
|
"Preview Font Size": "Preview Font Size",
|
||||||
"Code Block Theme": "Code Block Theme",
|
"Preview Font Family": "Preview Font Family",
|
||||||
"Allow preview to scroll past the last line": "Allow preview to scroll past the last line",
|
"Code Block Theme": "Code Block Theme",
|
||||||
"Show line numbers for preview code blocks": "Show line numbers for preview code blocks",
|
"Allow preview to scroll past the last line": "Allow preview to scroll past the last line",
|
||||||
"LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter",
|
"Show line numbers for preview code blocks": "Show line numbers for preview code blocks",
|
||||||
"LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter",
|
"LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter",
|
||||||
"LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter",
|
"LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter",
|
||||||
"LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter",
|
"LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter",
|
||||||
"PlantUML Server": "PlantUML Server",
|
"LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter",
|
||||||
"Community": "Community",
|
"PlantUML Server": "PlantUML Server",
|
||||||
"Subscribe to Newsletter": "Subscribe to Newsletter",
|
"Community": "Community",
|
||||||
"GitHub": "GitHub",
|
"Subscribe to Newsletter": "Subscribe to Newsletter",
|
||||||
"Blog": "Blog",
|
"GitHub": "GitHub",
|
||||||
"Facebook Group": "Facebook Group",
|
"Blog": "Blog",
|
||||||
"Twitter": "Twitter",
|
"Facebook Group": "Facebook Group",
|
||||||
"About": "About",
|
"Twitter": "Twitter",
|
||||||
"Boostnote": "Boostnote",
|
"About": "About",
|
||||||
"An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.",
|
"Boostnote": "Boostnote",
|
||||||
"Website": "Website",
|
"An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.",
|
||||||
"Development": "Development",
|
"Website": "Website",
|
||||||
" : Development configurations for Boostnote.": " : Development configurations for Boostnote.",
|
"Development": "Development",
|
||||||
"Copyright (C) 2017 - 2019 BoostIO": "Copyright (C) 2017 - 2019 BoostIO",
|
" : Development configurations for Boostnote.": " : Development configurations for Boostnote.",
|
||||||
"License: GPL v3": "License: GPL v3",
|
"Copyright (C) 2017 - 2019 BoostIO": "Copyright (C) 2017 - 2019 BoostIO",
|
||||||
"Analytics": "Analytics",
|
"License: GPL v3": "License: GPL v3",
|
||||||
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.",
|
"Analytics": "Analytics",
|
||||||
"You can see how it works on ": "You can see how it works on ",
|
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.",
|
||||||
"You can choose to enable or disable this option.": "You can choose to enable or disable this option.",
|
"You can see how it works on ": "You can see how it works on ",
|
||||||
"Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote",
|
"You can choose to enable or disable this option.": "You can choose to enable or disable this option.",
|
||||||
"Crowdfunding": "Crowdfunding",
|
"Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote",
|
||||||
"Dear Boostnote users,": "Dear Boostnote users,",
|
"Crowdfunding": "Crowdfunding",
|
||||||
"Thank you for using Boostnote!": "Thank you for using Boostnote!",
|
"Dear Boostnote users,": "Dear Boostnote users,",
|
||||||
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.",
|
"Thank you for using Boostnote!": "Thank you for using Boostnote!",
|
||||||
"To support our growing userbase, and satisfy community expectations,": "To support our growing userbase, and satisfy community expectations,",
|
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.",
|
||||||
"we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.",
|
"To support our growing userbase, and satisfy community expectations,": "To support our growing userbase, and satisfy community expectations,",
|
||||||
"If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!",
|
"we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.",
|
||||||
"Thanks,": "Thanks,",
|
"If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!",
|
||||||
"The Boostnote Team": "The Boostnote Team",
|
"Thanks,": "Thanks,",
|
||||||
"Support via OpenCollective": "Support via OpenCollective",
|
"The Boostnote Team": "The Boostnote Team",
|
||||||
"Language": "Language",
|
"Support via OpenCollective": "Support via OpenCollective",
|
||||||
"Default New Note": "Default New Note",
|
"Language": "Language",
|
||||||
"English": "English",
|
"Default New Note": "Default New Note",
|
||||||
"German": "German",
|
"English": "English",
|
||||||
"French": "French",
|
"German": "German",
|
||||||
"Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying",
|
"French": "French",
|
||||||
"All Notes": "All Notes",
|
"Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying",
|
||||||
"Starred": "Starred",
|
"All Notes": "All Notes",
|
||||||
"Are you sure to ": "Are you sure to ",
|
"Starred": "Starred",
|
||||||
" delete": " delete",
|
"Are you sure to ": "Are you sure to ",
|
||||||
"this folder?": "this folder?",
|
" delete": " delete",
|
||||||
"Confirm": "Confirm",
|
"this folder?": "this folder?",
|
||||||
"Cancel": "Cancel",
|
"Confirm": "Confirm",
|
||||||
"Markdown Note": "Markdown Note",
|
"Cancel": "Cancel",
|
||||||
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.",
|
"Markdown Note": "Markdown Note",
|
||||||
"Snippet Note": "Snippet Note",
|
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.",
|
||||||
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.",
|
"Snippet Note": "Snippet Note",
|
||||||
"Tab to switch format": "Tab to switch format",
|
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.",
|
||||||
"Updated": "Updated",
|
"Tab to switch format": "Tab to switch format",
|
||||||
"Created": "Created",
|
"Updated": "Updated",
|
||||||
"Alphabetically": "Alphabetically",
|
"Created": "Created",
|
||||||
"Counter": "Counter",
|
"Alphabetically": "Alphabetically",
|
||||||
"Default View": "Default View",
|
"Counter": "Counter",
|
||||||
"Compressed View": "Compressed View",
|
"Default View": "Default View",
|
||||||
"Search": "Search",
|
"Compressed View": "Compressed View",
|
||||||
"Blog Type": "Blog Type",
|
"Search": "Search",
|
||||||
"Blog Address": "Blog Address",
|
"Blog Type": "Blog Type",
|
||||||
"Save": "Save",
|
"Blog Address": "Blog Address",
|
||||||
"Auth": "Auth",
|
"Save": "Save",
|
||||||
"Authentication Method": "Authentication Method",
|
"Auth": "Auth",
|
||||||
"JWT": "JWT",
|
"Authentication Method": "Authentication Method",
|
||||||
"USER": "USER",
|
"JWT": "JWT",
|
||||||
"Token": "Token",
|
"USER": "USER",
|
||||||
"Storage": "Storage",
|
"Token": "Token",
|
||||||
"Hotkeys": "Hotkeys",
|
"Storage": "Storage",
|
||||||
"Show/Hide Boostnote": "Show/Hide Boostnote",
|
"Hotkeys": "Hotkeys",
|
||||||
"Toggle Editor Mode": "Toggle Editor Mode",
|
"Show/Hide Boostnote": "Show/Hide Boostnote",
|
||||||
"Delete Note": "Delete Note",
|
"Toggle Editor Mode": "Toggle Editor Mode",
|
||||||
"Restore": "Restore",
|
"Delete Note": "Delete Note",
|
||||||
"Permanent Delete": "Permanent Delete",
|
"Restore": "Restore",
|
||||||
"Confirm note deletion": "Confirm note deletion",
|
"Permanent Delete": "Permanent Delete",
|
||||||
"This will permanently remove this note.": "This will permanently remove this note.",
|
"Confirm note deletion": "Confirm note deletion",
|
||||||
"Successfully applied!": "Successfully applied!",
|
"This will permanently remove this note.": "This will permanently remove this note.",
|
||||||
"Albanian": "Albanian",
|
"Successfully applied!": "Successfully applied!",
|
||||||
"Chinese (zh-CN)": "Chinese (zh-CN)",
|
"Albanian": "Albanian",
|
||||||
"Chinese (zh-TW)": "Chinese (zh-TW)",
|
"Chinese (zh-CN)": "Chinese (zh-CN)",
|
||||||
"Danish": "Danish",
|
"Chinese (zh-TW)": "Chinese (zh-TW)",
|
||||||
"Japanese": "Japanese",
|
"Czech": "Czech",
|
||||||
"Korean": "Korean",
|
"Danish": "Danish",
|
||||||
"Norwegian": "Norwegian",
|
"Japanese": "Japanese",
|
||||||
"Polish": "Polish",
|
"Korean": "Korean",
|
||||||
"Portuguese": "Portuguese",
|
"Norwegian": "Norwegian",
|
||||||
"Spanish": "Spanish",
|
"Polish": "Polish",
|
||||||
"Unsaved Changes!": "Unsaved Changes!",
|
"Portuguese": "Portuguese",
|
||||||
"UserName": "UserName",
|
"Spanish": "Spanish",
|
||||||
"Password": "Password",
|
"Unsaved Changes!": "Unsaved Changes!",
|
||||||
"Russian": "Russian",
|
"UserName": "UserName",
|
||||||
"Hungarian": "Hungarian",
|
"Password": "Password",
|
||||||
"Thai": "Thai (ภาษาไทย)",
|
"Russian": "Russian",
|
||||||
"Command(⌘)": "Command(⌘)",
|
"Hungarian": "Hungarian",
|
||||||
"Add Storage": "Add Storage",
|
"Thai": "Thai (ภาษาไทย)",
|
||||||
"Name": "Name",
|
"Command(⌘)": "Command(⌘)",
|
||||||
"Type": "Type",
|
"Add Storage": "Add Storage",
|
||||||
"File System": "File System",
|
"Name": "Name",
|
||||||
"Setting up 3rd-party cloud storage integration:": "Setting up 3rd-party cloud storage integration:",
|
"Type": "Type",
|
||||||
"Cloud-Syncing-and-Backup": "Cloud-Syncing-and-Backup",
|
"File System": "File System",
|
||||||
"Location": "Location",
|
"Setting up 3rd-party cloud storage integration:": "Setting up 3rd-party cloud storage integration:",
|
||||||
"Add": "Add",
|
"Cloud-Syncing-and-Backup": "Cloud-Syncing-and-Backup",
|
||||||
"Unlink Storage": "Unlink Storage",
|
"Location": "Location",
|
||||||
"Unlinking removes this linked storage from Boostnote. No data is removed, please manually delete the folder from your hard drive if needed.": "Unlinking removes this linked storage from Boostnote. No data is removed, please manually delete the folder from your hard drive if needed.",
|
"Add": "Add",
|
||||||
"Editor Rulers": "Editor Rulers",
|
"Unlink Storage": "Unlink Storage",
|
||||||
"Enable": "Enable",
|
"Unlinking removes this linked storage from Boostnote. No data is removed, please manually delete the folder from your hard drive if needed.": "Unlinking removes this linked storage from Boostnote. No data is removed, please manually delete the folder from your hard drive if needed.",
|
||||||
"Disable": "Disable",
|
"Editor Rulers": "Editor Rulers",
|
||||||
"Sanitization": "Sanitization",
|
"Enable": "Enable",
|
||||||
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
|
"Disable": "Disable",
|
||||||
"Render newlines in Markdown paragraphs as <br>": "Render newlines in Markdown paragraphs as <br>",
|
"Sanitization": "Sanitization",
|
||||||
"Allow styles": "Allow styles",
|
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
|
||||||
"Allow dangerous html tags": "Allow dangerous html tags",
|
"Render newlines in Markdown paragraphs as <br>": "Render newlines in Markdown paragraphs as <br>",
|
||||||
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.",
|
"Allow styles": "Allow styles",
|
||||||
"⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠",
|
"Allow dangerous html tags": "Allow dangerous html tags",
|
||||||
"Spellcheck disabled": "Spellcheck disabled",
|
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.",
|
||||||
"Save tags of a note in alphabetical order": "Save tags of a note in alphabetical order",
|
"⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠",
|
||||||
"Enable live count of notes": "Enable live count of notes",
|
"Spellcheck disabled": "Spellcheck disabled",
|
||||||
"Enable smart table editor": "Enable smart table editor",
|
"Save tags of a note in alphabetical order": "Save tags of a note in alphabetical order",
|
||||||
"Snippet Default Language": "Snippet Default Language",
|
"Enable live count of notes": "Enable live count of notes",
|
||||||
"New notes are tagged with the filtering tags": "New notes are tagged with the filtering tags",
|
"Enable smart table editor": "Enable smart table editor",
|
||||||
"Show menu bar": "Show menu bar",
|
"Snippet Default Language": "Snippet Default Language",
|
||||||
"Auto Detect": "Auto Detect"
|
"New notes are tagged with the filtering tags": "New notes are tagged with the filtering tags",
|
||||||
|
"Show menu bar": "Show menu bar",
|
||||||
|
"Auto Detect": "Auto Detect",
|
||||||
|
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
|
||||||
|
"Wrap line in Snippet Note": "Wrap line in Snippet Note",
|
||||||
|
"Enable Auto Update": "Enable Auto Update"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,162 +1,166 @@
|
|||||||
{
|
{
|
||||||
"Notes": "Notas",
|
"Notes": "Notas",
|
||||||
"Tags": "Etiquetas",
|
"Tags": "Etiquetas",
|
||||||
"Preferences": "Preferencias",
|
"Preferences": "Preferencias",
|
||||||
"Make a note": "Crear nota",
|
"Make a note": "Crear nota",
|
||||||
"Ctrl": "Ctrl",
|
"Ctrl": "Ctrl",
|
||||||
"Ctrl(^)": "Ctrl",
|
"Ctrl(^)": "Ctrl",
|
||||||
"to create a new note": "para crear una nueva nota",
|
"to create a new note": "para crear una nueva nota",
|
||||||
"Toggle Mode": "Alternar modo",
|
"Toggle Mode": "Alternar modo",
|
||||||
"Trash": "Basura",
|
"Trash": "Basura",
|
||||||
"MODIFICATION DATE": "FECHA DE MODIFICACIÓN",
|
"Ok": "Ok",
|
||||||
"Words": "Palabras",
|
"MODIFICATION DATE": "FECHA DE MODIFICACIÓN",
|
||||||
"Letters": "Letras",
|
"Words": "Palabras",
|
||||||
"STORAGE": "ALMACENAMIENTO",
|
"Letters": "Letras",
|
||||||
"FOLDER": "CARPETA",
|
"STORAGE": "ALMACENAMIENTO",
|
||||||
"CREATION DATE": "FECHA DE CREACIÓN",
|
"FOLDER": "CARPETA",
|
||||||
"NOTE LINK": "ENLACE DE LA NOTA",
|
"CREATION DATE": "FECHA DE CREACIÓN",
|
||||||
".md": ".md",
|
"NOTE LINK": "ENLACE DE LA NOTA",
|
||||||
".txt": ".txt",
|
".md": ".md",
|
||||||
".html": ".html",
|
".txt": ".txt",
|
||||||
".pdf": ".pdf",
|
".html": ".html",
|
||||||
"Print": "Imprimir",
|
".pdf": ".pdf",
|
||||||
"Your preferences for Boostnote": "Tus preferencias para Boostnote",
|
"Print": "Imprimir",
|
||||||
"Storage Locations": "Almacenamientos",
|
"Your preferences for Boostnote": "Tus preferencias para Boostnote",
|
||||||
"Add Storage Location": "Añadir ubicación de almacenamiento",
|
"Storage Locations": "Almacenamientos",
|
||||||
"Add Folder": "Añadir carpeta",
|
"Add Storage Location": "Añadir ubicación de almacenamiento",
|
||||||
"Open Storage folder": "Abrir carpeta de almacenamiento",
|
"Add Folder": "Añadir carpeta",
|
||||||
"Unlink": "Desvincular",
|
"Open Storage folder": "Abrir carpeta de almacenamiento",
|
||||||
"Edit": "Editar",
|
"Unlink": "Desvincular",
|
||||||
"Delete": "Eliminar",
|
"Edit": "Editar",
|
||||||
"Interface": "Interfaz",
|
"Delete": "Eliminar",
|
||||||
"Interface Theme": "Tema de la interfaz",
|
"Interface": "Interfaz",
|
||||||
"Default": "Por defecto",
|
"Interface Theme": "Tema de la interfaz",
|
||||||
"White": "Blanco",
|
"Default": "Por defecto",
|
||||||
"Solarized Dark": "Solarizado oscuro",
|
"White": "Blanco",
|
||||||
"Dark": "Oscuro",
|
"Solarized Dark": "Solarizado oscuro",
|
||||||
"Show a confirmation dialog when deleting notes": "Requerir confirmación al eliminar nota",
|
"Dark": "Oscuro",
|
||||||
"Editor Theme": "Tema del editor",
|
"Show a confirmation dialog when deleting notes": "Requerir confirmación al eliminar nota",
|
||||||
"Editor Font Size": "Tamaño de fuente del editor",
|
"Editor Theme": "Tema del editor",
|
||||||
"Editor Font Family": "Fuente del editor",
|
"Editor Font Size": "Tamaño de fuente del editor",
|
||||||
"Editor Indent Style": "Estilo de indentado del editor",
|
"Editor Font Family": "Fuente del editor",
|
||||||
"Spaces": "Espacios",
|
"Editor Indent Style": "Estilo de indentado del editor",
|
||||||
"Tabs": "Tabulaciones",
|
"Spaces": "Espacios",
|
||||||
"Switch to Preview": "Cambiar a previsualización",
|
"Tabs": "Tabulaciones",
|
||||||
"When Editor Blurred": "Cuando el editor pierde el foco",
|
"Switch to Preview": "Cambiar a previsualización",
|
||||||
"When Editor Blurred, Edit On Double Click": "Cuando el editor pierde el foco, editar con doble clic",
|
"When Editor Blurred": "Cuando el editor pierde el foco",
|
||||||
"On Right Click": "Al hacer clic derecho",
|
"When Editor Blurred, Edit On Double Click": "Cuando el editor pierde el foco, editar con doble clic",
|
||||||
"Editor Keymap": "Mapeo de teclas del editor",
|
"On Right Click": "Al hacer clic derecho",
|
||||||
"default": "por defecto",
|
"Editor Keymap": "Mapeo de teclas del editor",
|
||||||
"vim": "vim",
|
"default": "por defecto",
|
||||||
"emacs": "emacs",
|
"vim": "vim",
|
||||||
"⚠️ Please restart boostnote after you change the keymap": "⚠️ Por favor reinicie boostnote después de cambiar el mapeo de teclas",
|
"emacs": "emacs",
|
||||||
"Show line numbers in the editor": "Mostrar números de línea en el editor",
|
"⚠️ Please restart boostnote after you change the keymap": "⚠️ Por favor reinicie boostnote después de cambiar el mapeo de teclas",
|
||||||
"Allow editor to scroll past the last line": "Permitir al editor desplazarse más allá de la última línea",
|
"Show line numbers in the editor": "Mostrar números de línea en el editor",
|
||||||
"Bring in web page title when pasting URL on editor": "Al pegar una URL en el editor, insertar el título de la web",
|
"Allow editor to scroll past the last line": "Permitir al editor desplazarse más allá de la última línea",
|
||||||
"Preview": "Previsualizar",
|
"Bring in web page title when pasting URL on editor": "Al pegar una URL en el editor, insertar el título de la web",
|
||||||
"Preview Font Size": "Previsualizar tamaño de la fuente",
|
"Preview": "Previsualizar",
|
||||||
"Preview Font Family": "Previsualizar fuente",
|
"Preview Font Size": "Previsualizar tamaño de la fuente",
|
||||||
"Code Block Theme": "Tema de los bloques de código",
|
"Preview Font Family": "Previsualizar fuente",
|
||||||
"Allow preview to scroll past the last line": "Permitir a la previsualización desplazarse más allá de la última línea",
|
"Code Block Theme": "Tema de los bloques de código",
|
||||||
"Show line numbers for preview code blocks": "Mostrar números de línea al previsualizar bloques de código",
|
"Allow preview to scroll past the last line": "Permitir a la previsualización desplazarse más allá de la última línea",
|
||||||
"LaTeX Inline Open Delimiter": "Delimitador de apertura de LaTeX en línea",
|
"Show line numbers for preview code blocks": "Mostrar números de línea al previsualizar bloques de código",
|
||||||
"LaTeX Inline Close Delimiter": "Delimitador de cierre de LaTeX en línea",
|
"LaTeX Inline Open Delimiter": "Delimitador de apertura de LaTeX en línea",
|
||||||
"LaTeX Block Open Delimiter": "Delimitador de apertura de bloque LaTeX",
|
"LaTeX Inline Close Delimiter": "Delimitador de cierre de LaTeX en línea",
|
||||||
"LaTeX Block Close Delimiter": "Delimitador de cierre de bloque LaTeX",
|
"LaTeX Block Open Delimiter": "Delimitador de apertura de bloque LaTeX",
|
||||||
"PlantUML Server": "PlantUML Server",
|
"LaTeX Block Close Delimiter": "Delimitador de cierre de bloque LaTeX",
|
||||||
"Community": "Comunidad",
|
"PlantUML Server": "PlantUML Server",
|
||||||
"Subscribe to Newsletter": "Suscribirse al boletín",
|
"Community": "Comunidad",
|
||||||
"GitHub": "GitHub",
|
"Subscribe to Newsletter": "Suscribirse al boletín",
|
||||||
"Blog": "Blog",
|
"GitHub": "GitHub",
|
||||||
"Facebook Group": "Grupo de Facebook",
|
"Blog": "Blog",
|
||||||
"Twitter": "Twitter",
|
"Facebook Group": "Grupo de Facebook",
|
||||||
"About": "Sobre",
|
"Twitter": "Twitter",
|
||||||
"Boostnote": "Boostnote",
|
"About": "Sobre",
|
||||||
"An open source note-taking app made for programmers just like you.": "Una aplicación de código abierto para tomar notas hecho para programadores como tú.",
|
"Boostnote": "Boostnote",
|
||||||
"Website": "Página web",
|
"An open source note-taking app made for programmers just like you.": "Una aplicación de código abierto para tomar notas hecho para programadores como tú.",
|
||||||
"Development": "Desarrollo",
|
"Website": "Página web",
|
||||||
" : Development configurations for Boostnote.": " : Configuraciones de desarrollo para Boostnote.",
|
"Development": "Desarrollo",
|
||||||
"Copyright (C) 2017 - 2019 BoostIO": "Copyright (C) 2017 - 2019 BoostIO",
|
" : Development configurations for Boostnote.": " : Configuraciones de desarrollo para Boostnote.",
|
||||||
"License: GPL v3": "Licencia: GPL v3",
|
"Copyright (C) 2017 - 2019 BoostIO": "Copyright (C) 2017 - 2019 BoostIO",
|
||||||
"Analytics": "Analítica",
|
"License: GPL v3": "Licencia: GPL v3",
|
||||||
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote recopila datos anónimos con el único propósito de mejorar la aplicación, y de ninguna manera recopila información personal como el contenido de sus notas.",
|
"Analytics": "Analítica",
|
||||||
"You can see how it works on ": "Puedes ver cómo funciona en ",
|
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote recopila datos anónimos con el único propósito de mejorar la aplicación, y de ninguna manera recopila información personal como el contenido de sus notas.",
|
||||||
"You can choose to enable or disable this option.": "Puedes elegir activar o desactivar esta opción.",
|
"You can see how it works on ": "Puedes ver cómo funciona en ",
|
||||||
"Enable analytics to help improve Boostnote": "Activar recopilación de datos para ayudar a mejorar Boostnote",
|
"You can choose to enable or disable this option.": "Puedes elegir activar o desactivar esta opción.",
|
||||||
"Crowdfunding": "Crowdfunding",
|
"Enable analytics to help improve Boostnote": "Activar recopilación de datos para ayudar a mejorar Boostnote",
|
||||||
"Dear Boostnote users,": "Hola a todos,",
|
"Crowdfunding": "Crowdfunding",
|
||||||
"Thank you for using Boostnote!": "¡Gracias por usar Boostnote!",
|
"Dear Boostnote users,": "Hola a todos,",
|
||||||
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote es utilizado en alrededor de 200 países y regiones diferentes por una increíble comunidad de desarrolladores.",
|
"Thank you for using Boostnote!": "¡Gracias por usar Boostnote!",
|
||||||
"To support our growing userbase, and satisfy community expectations,": "Para continuar apoyando este crecimiento y satisfacer las expectativas de la comunidad,",
|
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote es utilizado en alrededor de 200 países y regiones diferentes por una increíble comunidad de desarrolladores.",
|
||||||
"we would like to invest more time and resources in this project.": "nos gustaría invertir más tiempo y recursos en este proyecto.",
|
"To support our growing userbase, and satisfy community expectations,": "Para continuar apoyando este crecimiento y satisfacer las expectativas de la comunidad,",
|
||||||
"If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "Si te gusta este proyecto y ves su potencial, ¡puedes ayudar apoyándonos en OpenCollective!",
|
"we would like to invest more time and resources in this project.": "nos gustaría invertir más tiempo y recursos en este proyecto.",
|
||||||
"Thanks,": "Gracias,",
|
"If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "Si te gusta este proyecto y ves su potencial, ¡puedes ayudar apoyándonos en OpenCollective!",
|
||||||
"The Boostnote Team": "Equipo de Boostnote",
|
"Thanks,": "Gracias,",
|
||||||
"Support via OpenCollective": "Contribuir vía OpenCollective",
|
"The Boostnote Team": "Equipo de Boostnote",
|
||||||
"Language": "Idioma",
|
"Support via OpenCollective": "Contribuir vía OpenCollective",
|
||||||
"English": "Inglés",
|
"Language": "Idioma",
|
||||||
"German": "Alemán",
|
"English": "Inglés",
|
||||||
"French": "Francés",
|
"German": "Alemán",
|
||||||
"Show \"Saved to Clipboard\" notification when copying": "Mostrar la notificaión \"Guardado en Portapapeles\" al copiar",
|
"French": "Francés",
|
||||||
"All Notes": "Todas las notas",
|
"Show \"Saved to Clipboard\" notification when copying": "Mostrar la notificaión \"Guardado en Portapapeles\" al copiar",
|
||||||
"Starred": "Destacado",
|
"All Notes": "Todas las notas",
|
||||||
"Are you sure to ": "¿Estás seguro de ",
|
"Starred": "Destacado",
|
||||||
" delete": " eliminar",
|
"Are you sure to ": "¿Estás seguro de ",
|
||||||
"this folder?": "esta carpeta?",
|
" delete": " eliminar",
|
||||||
"Confirm": "Confirmar",
|
"this folder?": "esta carpeta?",
|
||||||
"Cancel": "Cancelar",
|
"Confirm": "Confirmar",
|
||||||
"Markdown Note": "Nota Markdown",
|
"Cancel": "Cancelar",
|
||||||
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "Formato para crear documentos de texto. Permite utilizar listas, bloques de código y LaTeX.",
|
"Markdown Note": "Nota Markdown",
|
||||||
"Snippet Note": "Nota Snippet",
|
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "Formato para crear documentos de texto. Permite utilizar listas, bloques de código y LaTeX.",
|
||||||
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "Formato para fragmentos de código. Múltiples fragmentos se pueden agrupar en una sola nota.",
|
"Snippet Note": "Nota Snippet",
|
||||||
"Tab to switch format": "Tabulador para cambiar formato",
|
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "Formato para fragmentos de código. Múltiples fragmentos se pueden agrupar en una sola nota.",
|
||||||
"Updated": "Actualizado",
|
"Tab to switch format": "Tabulador para cambiar formato",
|
||||||
"Created": "Creado",
|
"Updated": "Actualizado",
|
||||||
"Alphabetically": "Alfabéticamente",
|
"Created": "Creado",
|
||||||
"Default View": "Vista por defecto",
|
"Alphabetically": "Alfabéticamente",
|
||||||
"Compressed View": "Vista comprimida",
|
"Default View": "Vista por defecto",
|
||||||
"Search": "Buscar",
|
"Compressed View": "Vista comprimida",
|
||||||
"Blog Type": "Tipo de blog",
|
"Search": "Buscar",
|
||||||
"Blog Address": "Dirección del blog",
|
"Blog Type": "Tipo de blog",
|
||||||
"Save": "Guardar",
|
"Blog Address": "Dirección del blog",
|
||||||
"Auth": "Autentificación",
|
"Save": "Guardar",
|
||||||
"Authentication Method": "Método de autentificación",
|
"Auth": "Autentificación",
|
||||||
"JWT": "JWT",
|
"Authentication Method": "Método de autentificación",
|
||||||
"USER": "USUARIO",
|
"JWT": "JWT",
|
||||||
"Token": "Token",
|
"USER": "USUARIO",
|
||||||
"Storage": "Almacenamiento",
|
"Token": "Token",
|
||||||
"Hotkeys": "Atajos de teclado",
|
"Storage": "Almacenamiento",
|
||||||
"Show/Hide Boostnote": "Mostrar/Ocultar Boostnote",
|
"Hotkeys": "Atajos de teclado",
|
||||||
"Restore": "Restaurar",
|
"Show/Hide Boostnote": "Mostrar/Ocultar Boostnote",
|
||||||
"Permanent Delete": "Eliminar permanentemente",
|
"Restore": "Restaurar",
|
||||||
"Confirm note deletion": "Confirmar eliminación de nota",
|
"Permanent Delete": "Eliminar permanentemente",
|
||||||
"This will permanently remove this note.": "Esto eliminará la nota permanentemente.",
|
"Confirm note deletion": "Confirmar eliminación de nota",
|
||||||
"Successfully applied!": "¡Aplicado con éxito!",
|
"This will permanently remove this note.": "Esto eliminará la nota permanentemente.",
|
||||||
"Albanian": "Albanés",
|
"Successfully applied!": "¡Aplicado con éxito!",
|
||||||
"Chinese (zh-CN)": "Chino - China",
|
"Albanian": "Albanés",
|
||||||
"Chinese (zh-TW)": "Chino - Taiwán",
|
"Chinese (zh-CN)": "Chino - China",
|
||||||
"Danish": "Danés",
|
"Chinese (zh-TW)": "Chino - Taiwán",
|
||||||
"Japanese": "Japonés",
|
"Czech": "Checo",
|
||||||
"Korean": "Coreano",
|
"Danish": "Danés",
|
||||||
"Norwegian": "Noruego",
|
"Japanese": "Japonés",
|
||||||
"Polish": "Polaco",
|
"Korean": "Coreano",
|
||||||
"Portuguese": "Portugués",
|
"Norwegian": "Noruego",
|
||||||
"Spanish": "Español",
|
"Polish": "Polaco",
|
||||||
"Unsaved Changes!": "¡Tienes que guardar!",
|
"Portuguese": "Portugués",
|
||||||
"Russian": "Ruso",
|
"Spanish": "Español",
|
||||||
"Thai": "Thai (ภาษาไทย)",
|
"Unsaved Changes!": "¡Tienes que guardar!",
|
||||||
"Command(⌘)": "Comando(⌘)",
|
"Russian": "Ruso",
|
||||||
"Editor Rulers": "Reglas del editor",
|
"Thai": "Thai (ภาษาไทย)",
|
||||||
"Enable": "Activar",
|
"Command(⌘)": "Comando(⌘)",
|
||||||
"Disable": "Desactivar",
|
"Editor Rulers": "Reglas del editor",
|
||||||
"Sanitization": "Saneamiento",
|
"Enable": "Activar",
|
||||||
"Only allow secure html tags (recommended)": "Solo permitir etiquetas html seguras (recomendado)",
|
"Disable": "Desactivar",
|
||||||
"Allow styles": "Permitir estilos",
|
"Sanitization": "Saneamiento",
|
||||||
"Allow dangerous html tags": "Permitir etiquetas html peligrosas",
|
"Only allow secure html tags (recommended)": "Solo permitir etiquetas html seguras (recomendado)",
|
||||||
"⚠ You have pasted a link referring an attachment that could not be found in the location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ Ha pegado un enlace a un archivo adjunto que no se puede encontrar en el almacenamiento de esta nota. Pegar enlaces a archivos adjuntos solo está soportado si el origen y el destino son el mismo almacenamiento. ¡Por favor, mejor arrastre el archivo! ⚠",
|
"Allow styles": "Permitir estilos",
|
||||||
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Convertir flechas textuales a símbolos bonitos. ⚠ Esto interferirá cuando use comentarios HTML en Markdown.",
|
"Allow dangerous html tags": "Permitir etiquetas html peligrosas",
|
||||||
"Spellcheck disabled": "Deshabilitar corrector ortográfico",
|
"⚠ You have pasted a link referring an attachment that could not be found in the location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ Ha pegado un enlace a un archivo adjunto que no se puede encontrar en el almacenamiento de esta nota. Pegar enlaces a archivos adjuntos solo está soportado si el origen y el destino son el mismo almacenamiento. ¡Por favor, mejor arrastre el archivo! ⚠",
|
||||||
"Show menu bar": "Mostrar barra del menú",
|
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Convertir flechas textuales a símbolos bonitos. ⚠ Esto interferirá cuando use comentarios HTML en Markdown.",
|
||||||
"Auto Detect": "Detección automática",
|
"Spellcheck disabled": "Deshabilitar corrector ortográfico",
|
||||||
"Snippet Default Language": "Lenguaje por defecto de los fragmentos de código"
|
"Show menu bar": "Mostrar barra del menú",
|
||||||
|
"Auto Detect": "Detección automática",
|
||||||
|
"Snippet Default Language": "Lenguaje por defecto de los fragmentos de código",
|
||||||
|
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
|
||||||
|
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
|
||||||
}
|
}
|
||||||
|
|||||||
327
locales/fa.json
327
locales/fa.json
@@ -1,164 +1,167 @@
|
|||||||
{
|
{
|
||||||
"Notes": "یادداشت ها",
|
"Notes": "یادداشت ها",
|
||||||
"Tags": "تگ ها",
|
"Tags": "تگ ها",
|
||||||
"Preferences": "تنظیمات",
|
"Preferences": "تنظیمات",
|
||||||
"Make a note": "یک یادداشت بنویس",
|
"Make a note": "یک یادداشت بنویس",
|
||||||
"Ctrl": "Ctrl",
|
"Ctrl": "Ctrl",
|
||||||
"Ctrl(^)": "Ctrl",
|
"Ctrl(^)": "Ctrl",
|
||||||
"to create a new note": "برای ساخت یک یادداشت",
|
"to create a new note": "برای ساخت یک یادداشت",
|
||||||
"Toggle Mode": "تغییر حالت نمایش",
|
"Toggle Mode": "تغییر حالت نمایش",
|
||||||
"Trash": "سطل آشغال",
|
"Trash": "سطل آشغال",
|
||||||
"MODIFICATION DATE": "تاریخ تغییر",
|
"MODIFICATION DATE": "تاریخ تغییر",
|
||||||
"Words": "کلمات",
|
"Words": "کلمات",
|
||||||
"Letters": "حروف",
|
"Letters": "حروف",
|
||||||
"STORAGE": "ذخیره سازی",
|
"STORAGE": "ذخیره سازی",
|
||||||
"FOLDER": "پوشه",
|
"FOLDER": "پوشه",
|
||||||
"CREATION DATE": "تاریخ ایجاد",
|
"CREATION DATE": "تاریخ ایجاد",
|
||||||
"NOTE LINK": "لینک یادداشت",
|
"NOTE LINK": "لینک یادداشت",
|
||||||
".md": ".md",
|
".md": ".md",
|
||||||
".txt": ".txt",
|
".txt": ".txt",
|
||||||
".html": ".html",
|
".html": ".html",
|
||||||
".pdf": ".pdf",
|
".pdf": ".pdf",
|
||||||
"Print": "پرینت",
|
"Print": "پرینت",
|
||||||
"Your preferences for Boostnote": "تنظیمات شما برای boostnote",
|
"Your preferences for Boostnote": "تنظیمات شما برای boostnote",
|
||||||
"Storage Locations": "ذخیره سازی",
|
"Storage Locations": "ذخیره سازی",
|
||||||
"Add Storage Location": "افزودن محل ذخیره سازی",
|
"Add Storage Location": "افزودن محل ذخیره سازی",
|
||||||
"Add Folder": "ساخت پوشه",
|
"Add Folder": "ساخت پوشه",
|
||||||
"Open Storage folder": "بازکردن پوشه ذخیره سازی",
|
"Open Storage folder": "بازکردن پوشه ذخیره سازی",
|
||||||
"Unlink": "حذف لینک",
|
"Unlink": "حذف لینک",
|
||||||
"Edit": "ویرایش",
|
"Edit": "ویرایش",
|
||||||
"Delete": "حذف",
|
"Delete": "حذف",
|
||||||
"Interface": "رابط کاربری",
|
"Interface": "رابط کاربری",
|
||||||
"Interface Theme": "تم رابط کاربری",
|
"Interface Theme": "تم رابط کاربری",
|
||||||
"Default": "پیش فرض",
|
"Default": "پیش فرض",
|
||||||
"White": "روشن",
|
"White": "روشن",
|
||||||
"Solarized Dark": "سولارایز",
|
"Solarized Dark": "سولارایز",
|
||||||
"Dark": "تاریک",
|
"Dark": "تاریک",
|
||||||
"Show a confirmation dialog when deleting notes": "هنگام حذف یادداشت ها یک پیام تایید نمایش بده.",
|
"Show a confirmation dialog when deleting notes": "هنگام حذف یادداشت ها یک پیام تایید نمایش بده.",
|
||||||
"Editor Theme": "تم ویرایشگر",
|
"Editor Theme": "تم ویرایشگر",
|
||||||
"Editor Font Size": "اندازه فونت ویرایشگر",
|
"Editor Font Size": "اندازه فونت ویرایشگر",
|
||||||
"Editor Font Family": "فونت ویرایشگر",
|
"Editor Font Family": "فونت ویرایشگر",
|
||||||
"Editor Indent Style": "حالت فاصله گذاری ویرایشگر",
|
"Editor Indent Style": "حالت فاصله گذاری ویرایشگر",
|
||||||
"Spaces": "Spaces",
|
"Spaces": "Spaces",
|
||||||
"Tabs": "Tabs",
|
"Tabs": "Tabs",
|
||||||
"Switch to Preview": "دیدن پیش نمایش",
|
"Switch to Preview": "دیدن پیش نمایش",
|
||||||
"When Editor Blurred": "وقتی ویرایشگر از حالت ویرایش خارج شد ",
|
"When Editor Blurred": "وقتی ویرایشگر از حالت ویرایش خارج شد ",
|
||||||
"When Editor Blurred, Edit On Double Click": "وقتی ویرایشگر از حالت ویرایش خارج شد و با دبل کلیک ویرایش کنید.",
|
"When Editor Blurred, Edit On Double Click": "وقتی ویرایشگر از حالت ویرایش خارج شد و با دبل کلیک ویرایش کنید.",
|
||||||
"On Right Click": "راست کلیک",
|
"On Right Click": "راست کلیک",
|
||||||
"Editor Keymap": "ویرایشگر Keymap",
|
"Editor Keymap": "ویرایشگر Keymap",
|
||||||
"default": "پیش فرض",
|
"default": "پیش فرض",
|
||||||
"vim": "vim",
|
"vim": "vim",
|
||||||
"emacs": "emacs",
|
"emacs": "emacs",
|
||||||
"⚠️ Please restart boostnote after you change the keymap": "⚠️ برنامه را دوباره راه اندازی کنید keymap لطفا بعد از تغییر",
|
"⚠️ Please restart boostnote after you change the keymap": "⚠️ برنامه را دوباره راه اندازی کنید keymap لطفا بعد از تغییر",
|
||||||
"Show line numbers in the editor": "شماره خطوط در ویرایشگر را نمایش بده.",
|
"Show line numbers in the editor": "شماره خطوط در ویرایشگر را نمایش بده.",
|
||||||
"Allow editor to scroll past the last line": "اجازه بده ویرایشگر بعد از آخرین خط اسکرول کند.",
|
"Allow editor to scroll past the last line": "اجازه بده ویرایشگر بعد از آخرین خط اسکرول کند.",
|
||||||
"Bring in web page title when pasting URL on editor": "هنگامی که آدرس اینترنتی در ویرایشگر اضافه شد عنوان آنرا نمایش بده",
|
"Bring in web page title when pasting URL on editor": "هنگامی که آدرس اینترنتی در ویرایشگر اضافه شد عنوان آنرا نمایش بده",
|
||||||
"Preview": "پیش نمایش",
|
"Preview": "پیش نمایش",
|
||||||
"Preview Font Size": "اندازه فونتِ پیش نمایش",
|
"Preview Font Size": "اندازه فونتِ پیش نمایش",
|
||||||
"Preview Font Family": " فونتِ پیش نمایش",
|
"Preview Font Family": " فونتِ پیش نمایش",
|
||||||
"Code Block Theme": "تم بخش کد",
|
"Code Block Theme": "تم بخش کد",
|
||||||
"Allow preview to scroll past the last line": "اجازه بده پیش نمایش بعد از آخرین خط اسکرول کند.",
|
"Allow preview to scroll past the last line": "اجازه بده پیش نمایش بعد از آخرین خط اسکرول کند.",
|
||||||
"Show line numbers for preview code blocks": "شماره خطوط در پیش نمایش را نمایش بده.",
|
"Show line numbers for preview code blocks": "شماره خطوط در پیش نمایش را نمایش بده.",
|
||||||
"LaTeX Inline Open Delimiter": "جداکننده آغازین لاتکس خطی",
|
"LaTeX Inline Open Delimiter": "جداکننده آغازین لاتکس خطی",
|
||||||
"LaTeX Inline Close Delimiter": "جداکننده پایانی لاتکس خطی",
|
"LaTeX Inline Close Delimiter": "جداکننده پایانی لاتکس خطی",
|
||||||
"LaTeX Block Open Delimiter": "جداکننده آغازین بلوک لاتکس ",
|
"LaTeX Block Open Delimiter": "جداکننده آغازین بلوک لاتکس ",
|
||||||
"LaTeX Block Close Delimiter": "جداکننده آغازین بلوک لاتکس ",
|
"LaTeX Block Close Delimiter": "جداکننده آغازین بلوک لاتکس ",
|
||||||
"PlantUML Server": "PlantUML Server",
|
"PlantUML Server": "PlantUML Server",
|
||||||
"Community": "کامینیتی",
|
"Community": "کامینیتی",
|
||||||
"Subscribe to Newsletter": "اشتراک در خبرنامه",
|
"Subscribe to Newsletter": "اشتراک در خبرنامه",
|
||||||
"GitHub": "گیت هاب",
|
"GitHub": "گیت هاب",
|
||||||
"Blog": "بلاگ",
|
"Blog": "بلاگ",
|
||||||
"Facebook Group": "گروه فیسبوک",
|
"Facebook Group": "گروه فیسبوک",
|
||||||
"Twitter": "توییتر",
|
"Twitter": "توییتر",
|
||||||
"About": "درباره",
|
"About": "درباره",
|
||||||
"Boostnote": "Boostnote",
|
"Boostnote": "Boostnote",
|
||||||
"An open source note-taking app made for programmers just like you.": "یک دفترچه یادداشت متن باز ساخته شده برای برنامه نویسانی مثل تو.",
|
"An open source note-taking app made for programmers just like you.": "یک دفترچه یادداشت متن باز ساخته شده برای برنامه نویسانی مثل تو.",
|
||||||
"Website": "وبسایت",
|
"Website": "وبسایت",
|
||||||
"Development": "توسعه",
|
"Development": "توسعه",
|
||||||
" : Development configurations for Boostnote.": " : پیکربندی توسعه برای Boostnote.",
|
" : Development configurations for Boostnote.": " : پیکربندی توسعه برای Boostnote.",
|
||||||
"Copyright (C) 2017 - 2019 BoostIO": "Copyright (C) 2017 - 2019 BoostIO",
|
"Copyright (C) 2017 - 2019 BoostIO": "Copyright (C) 2017 - 2019 BoostIO",
|
||||||
"License: GPL v3": "لایسنس: GPL v3",
|
"License: GPL v3": "لایسنس: GPL v3",
|
||||||
"Analytics": "تجزیه و تحلیل",
|
"Analytics": "تجزیه و تحلیل",
|
||||||
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Bosstnote اطلاعات ناشناس را برای بهبود عملکرد برنامه جمع آوری میکند.اطلاعات شخصی شما مثل محتوای یادداشت ها هرگز برای هیچ هدفی جمع آوری نمیشوند",
|
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Bosstnote اطلاعات ناشناس را برای بهبود عملکرد برنامه جمع آوری میکند.اطلاعات شخصی شما مثل محتوای یادداشت ها هرگز برای هیچ هدفی جمع آوری نمیشوند",
|
||||||
"You can see how it works on ": "میتوانید ببینید چگونه کار میکند. ",
|
"You can see how it works on ": "میتوانید ببینید چگونه کار میکند. ",
|
||||||
"You can choose to enable or disable this option.": "میتوانید این گزینه را فعال یا غیرفعال کنید.",
|
"You can choose to enable or disable this option.": "میتوانید این گزینه را فعال یا غیرفعال کنید.",
|
||||||
"Enable analytics to help improve Boostnote":".تجزیه تحلیل داده ها را برای کمک به بهبود برنامه فعال کن",
|
"Enable analytics to help improve Boostnote": ".تجزیه تحلیل داده ها را برای کمک به بهبود برنامه فعال کن",
|
||||||
"Crowdfunding": "جمع سپاری (سرمایه گذاری جمعی )",
|
"Crowdfunding": "جمع سپاری (سرمایه گذاری جمعی )",
|
||||||
"Dear Boostnote users,": "عزیزان,",
|
"Dear Boostnote users,": "عزیزان,",
|
||||||
"Thank you for using Boostnote!": "از شما بخاطر استفاده از boostnote ممنونیم!",
|
"Thank you for using Boostnote!": "از شما بخاطر استفاده از boostnote ممنونیم!",
|
||||||
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "در ۲۰۰ کشور مختلف دنیا مورد توسط جمعی از برنامه نویسان بی نظیر مورد استفاده قرار میگیرد. Boostnote",
|
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "در ۲۰۰ کشور مختلف دنیا مورد توسط جمعی از برنامه نویسان بی نظیر مورد استفاده قرار میگیرد. Boostnote",
|
||||||
"To support our growing userbase, and satisfy community expectations,": "برای حمایت از این رشد ، و برآورده شدن انتظارات کامینیتی,",
|
"To support our growing userbase, and satisfy community expectations,": "برای حمایت از این رشد ، و برآورده شدن انتظارات کامینیتی,",
|
||||||
"we would like to invest more time and resources in this project.": "ما می خواهیم زمان و منابع بیشتری را در این پروژه سرمایه گذاری کنیم.",
|
"we would like to invest more time and resources in this project.": "ما می خواهیم زمان و منابع بیشتری را در این پروژه سرمایه گذاری کنیم.",
|
||||||
"If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "اگر این پروژه را دوست دارید و پتانسیلی در آن میبینید، میتوانید مارا در اوپن کالکتیو حمایت کنید.",
|
"If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "اگر این پروژه را دوست دارید و پتانسیلی در آن میبینید، میتوانید مارا در اوپن کالکتیو حمایت کنید.",
|
||||||
"Thanks,": "با تشکر,",
|
"Thanks,": "با تشکر,",
|
||||||
"The Boostnote Team": "Boostnote نگهدارندگان",
|
"The Boostnote Team": "Boostnote نگهدارندگان",
|
||||||
"Support via OpenCollective": "حمایت کنید OpenCollective از طریق",
|
"Support via OpenCollective": "حمایت کنید OpenCollective از طریق",
|
||||||
"Language": "زبان",
|
"Language": "زبان",
|
||||||
"English": "انگلیسی",
|
"English": "انگلیسی",
|
||||||
"German": "آلمانی",
|
"German": "آلمانی",
|
||||||
"French": "فرانسوی",
|
"French": "فرانسوی",
|
||||||
"Show \"Saved to Clipboard\" notification when copying": "نمایش \"ذخیره در کلیپبورد\" اطلاع رسانی هنگام کپی کردن",
|
"Show \"Saved to Clipboard\" notification when copying": "نمایش \"ذخیره در کلیپبورد\" اطلاع رسانی هنگام کپی کردن",
|
||||||
"All Notes": "همه یادداشت ها",
|
"All Notes": "همه یادداشت ها",
|
||||||
"Starred": "ستاره دار",
|
"Starred": "ستاره دار",
|
||||||
"Are you sure to ": " مطمئن هستید که",
|
"Are you sure to ": " مطمئن هستید که",
|
||||||
" delete": "حذف ",
|
" delete": "حذف ",
|
||||||
"this folder?": "این پوشه ؟",
|
"this folder?": "این پوشه ؟",
|
||||||
"Confirm": "تایید",
|
"Confirm": "تایید",
|
||||||
"Cancel": "انصراف",
|
"Cancel": "انصراف",
|
||||||
"Markdown Note": "Markdown یادداشتِ",
|
"Markdown Note": "Markdown یادداشتِ",
|
||||||
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "این قالب برای ساخت سند های متنی است. چک لیست ها و تکه کد ها و بلاک های لاتکس قابل استفاده اند.",
|
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "این قالب برای ساخت سند های متنی است. چک لیست ها و تکه کد ها و بلاک های لاتکس قابل استفاده اند.",
|
||||||
"Snippet Note": "Snippet یادداشتِ",
|
"Snippet Note": "Snippet یادداشتِ",
|
||||||
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "این قالب برای ساخت تکه کد هاست. چند تکه کد میتوانند تبدیل به یک یادداشت شوند.",
|
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "این قالب برای ساخت تکه کد هاست. چند تکه کد میتوانند تبدیل به یک یادداشت شوند.",
|
||||||
"Tab to switch format": "را بزنید Tab برای تغییر فرمت",
|
"Tab to switch format": "را بزنید Tab برای تغییر فرمت",
|
||||||
"Updated": "بروزرسانی شد",
|
"Updated": "بروزرسانی شد",
|
||||||
"Created": "ایجاد شد",
|
"Created": "ایجاد شد",
|
||||||
"Alphabetically": "بر اساس حروف الفبا",
|
"Alphabetically": "بر اساس حروف الفبا",
|
||||||
"Counter": "شمارشگر",
|
"Counter": "شمارشگر",
|
||||||
"Default View": "نمایش پیشفرض",
|
"Default View": "نمایش پیشفرض",
|
||||||
"Compressed View": "نمایش فشرده",
|
"Compressed View": "نمایش فشرده",
|
||||||
"Search": "جستجو",
|
"Search": "جستجو",
|
||||||
"Blog Type": "نوع وبلاگ",
|
"Blog Type": "نوع وبلاگ",
|
||||||
"Blog Address": "آدرس وبلاگ",
|
"Blog Address": "آدرس وبلاگ",
|
||||||
"Save": "ذخیره",
|
"Save": "ذخیره",
|
||||||
"Auth": "هویت",
|
"Auth": "هویت",
|
||||||
"Authentication Method": "متد احراز هویت",
|
"Authentication Method": "متد احراز هویت",
|
||||||
"JWT": "JWT",
|
"JWT": "JWT",
|
||||||
"USER": "کاربر",
|
"USER": "کاربر",
|
||||||
"Token": "توکن",
|
"Token": "توکن",
|
||||||
"Storage": "ذخیره سازی",
|
"Storage": "ذخیره سازی",
|
||||||
"Hotkeys": "کلید های میانبر",
|
"Hotkeys": "کلید های میانبر",
|
||||||
"Show/Hide Boostnote": "Boostnote نمایش/پنهان کردن",
|
"Show/Hide Boostnote": "Boostnote نمایش/پنهان کردن",
|
||||||
"Restore": "بازگرداندن به حالت اول",
|
"Restore": "بازگرداندن به حالت اول",
|
||||||
"Permanent Delete": "حذف بدون بازگشت",
|
"Permanent Delete": "حذف بدون بازگشت",
|
||||||
"Confirm note deletion": ".حذف یادداشت را تایید کنید",
|
"Confirm note deletion": ".حذف یادداشت را تایید کنید",
|
||||||
"This will permanently remove this note.": ".این کار یادداشت را بطور دائمی حذف خواهد کرد",
|
"This will permanently remove this note.": ".این کار یادداشت را بطور دائمی حذف خواهد کرد",
|
||||||
"Successfully applied!": "!با موفقیت اجرا شد",
|
"Successfully applied!": "!با موفقیت اجرا شد",
|
||||||
"Albanian": "آلبانی",
|
"Albanian": "آلبانی",
|
||||||
"Chinese (zh-CN)": "چینی (zh-CN)",
|
"Chinese (zh-CN)": "چینی (zh-CN)",
|
||||||
"Chinese (zh-TW)": "چینی (zh-TW)",
|
"Chinese (zh-TW)": "چینی (zh-TW)",
|
||||||
"Danish": "دانمارکی",
|
"Czech": "Czech",
|
||||||
"Japanese": "ژاپنی",
|
"Danish": "دانمارکی",
|
||||||
"Korean": "کره ای",
|
"Japanese": "ژاپنی",
|
||||||
"Norwegian": "نروژی",
|
"Korean": "کره ای",
|
||||||
"Polish": "لهستانی",
|
"Norwegian": "نروژی",
|
||||||
"Portuguese": "پرتغالی",
|
"Polish": "لهستانی",
|
||||||
"Spanish": "اسپانیایی",
|
"Portuguese": "پرتغالی",
|
||||||
"Unsaved Changes!": "!باید ذخیره کنید",
|
"Spanish": "اسپانیایی",
|
||||||
"UserName": "نام کاربری",
|
"Unsaved Changes!": "!باید ذخیره کنید",
|
||||||
"Password": "رمز عبور",
|
"UserName": "نام کاربری",
|
||||||
"Russian": "روسی",
|
"Password": "رمز عبور",
|
||||||
"Thai": "Thai (ภาษาไทย)",
|
"Russian": "روسی",
|
||||||
"Command(⌘)": "Command(⌘)",
|
"Thai": "Thai (ภาษาไทย)",
|
||||||
"Editor Rulers": "Editor Rulers",
|
"Command(⌘)": "Command(⌘)",
|
||||||
"Enable": "فعال",
|
"Editor Rulers": "Editor Rulers",
|
||||||
"Disable": "غیرفعال",
|
"Enable": "فعال",
|
||||||
"Sanitization": "پاکسازی کردن",
|
"Disable": "غیرفعال",
|
||||||
"Only allow secure html tags (recommended)": "(فقط تگ های امن اچ تی ام ال مجاز اند.(پیشنهاد میشود",
|
"Sanitization": "پاکسازی کردن",
|
||||||
"Allow styles": "حالت های مجاز",
|
"Only allow secure html tags (recommended)": "(فقط تگ های امن اچ تی ام ال مجاز اند.(پیشنهاد میشود",
|
||||||
"Allow dangerous html tags": "تگ های خطرناک اچ تی ام ال مجاز اند",
|
"Allow styles": "حالت های مجاز",
|
||||||
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.",
|
"Allow dangerous html tags": "تگ های خطرناک اچ تی ام ال مجاز اند",
|
||||||
"⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠",
|
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.",
|
||||||
"Spellcheck disabled": "Spellcheck disabled",
|
"⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠",
|
||||||
"Show menu bar": "Show menu bar",
|
"Spellcheck disabled": "Spellcheck disabled",
|
||||||
"Auto Detect": "Auto Detect"
|
"Show menu bar": "Show menu bar",
|
||||||
|
"Auto Detect": "Auto Detect",
|
||||||
|
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
|
||||||
|
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
|
||||||
}
|
}
|
||||||
|
|||||||
352
locales/fr.json
352
locales/fr.json
@@ -1,176 +1,180 @@
|
|||||||
{
|
{
|
||||||
"Notes": "Notes",
|
"Notes": "Notes",
|
||||||
"Tags": "Tags",
|
"Tags": "Tags",
|
||||||
"Preferences": "Préférences",
|
"Preferences": "Préférences",
|
||||||
"Make a note": "Créer une note",
|
"Make a note": "Créer une note",
|
||||||
"Ctrl": "Ctrl",
|
"Ctrl": "Ctrl",
|
||||||
"Ctrl(^)": "Ctrl",
|
"Ctrl(^)": "Ctrl",
|
||||||
"to create a new note": "pour créer une nouvelle note",
|
"to create a new note": "pour créer une nouvelle note",
|
||||||
"Toggle Mode": "Toggle Mode",
|
"Toggle Mode": "Toggle Mode",
|
||||||
"Trash": "Poubelle",
|
"Trash": "Poubelle",
|
||||||
"MODIFICATION DATE": "DATE DE MODIFICATION",
|
"Ok": "Ok",
|
||||||
"Words": "Mots",
|
"MODIFICATION DATE": "DATE DE MODIFICATION",
|
||||||
"Letters": "Lettres",
|
"Words": "Mots",
|
||||||
"STORAGE": "STOCKAGE",
|
"Letters": "Lettres",
|
||||||
"FOLDER": "DOSSIER",
|
"STORAGE": "STOCKAGE",
|
||||||
"CREATION DATE": "DATE DE CREATION",
|
"FOLDER": "DOSSIER",
|
||||||
"NOTE LINK": "LIEN DE LA NOTE",
|
"CREATION DATE": "DATE DE CREATION",
|
||||||
".md": ".md",
|
"NOTE LINK": "LIEN DE LA NOTE",
|
||||||
".txt": ".txt",
|
".md": ".md",
|
||||||
".html": ".html",
|
".txt": ".txt",
|
||||||
".pdf": ".pdf",
|
".html": ".html",
|
||||||
"Print": "Imprimer",
|
".pdf": ".pdf",
|
||||||
"Your preferences for Boostnote": "Vos préférences pour Boostnote",
|
"Print": "Imprimer",
|
||||||
"Storage Locations": "Stockages",
|
"Your preferences for Boostnote": "Vos préférences pour Boostnote",
|
||||||
"Add Storage Location": "Ajouter un espace de stockage",
|
"Storage Locations": "Stockages",
|
||||||
"Add Folder": "Ajouter un dossier",
|
"Add Storage Location": "Ajouter un espace de stockage",
|
||||||
"Open Storage folder": "Ouvrir un dossier de stockage",
|
"Add Folder": "Ajouter un dossier",
|
||||||
"Unlink": "Délier",
|
"Open Storage folder": "Ouvrir un dossier de stockage",
|
||||||
"Edit": "Editer",
|
"Unlink": "Délier",
|
||||||
"Delete": "Supprimer",
|
"Edit": "Editer",
|
||||||
"Interface": "Interface",
|
"Delete": "Supprimer",
|
||||||
"Interface Theme": "Thème d'interface",
|
"Interface": "Interface",
|
||||||
"Default": "Effacer",
|
"Interface Theme": "Thème d'interface",
|
||||||
"White": "Blanc",
|
"Default": "Effacer",
|
||||||
"Solarized Dark": "Foncé solarisé",
|
"White": "Blanc",
|
||||||
"Dark": "Foncé",
|
"Solarized Dark": "Foncé solarisé",
|
||||||
"Show a confirmation dialog when deleting notes": "Montrer une alerte de confirmation lors de la suppression de notes",
|
"Dark": "Foncé",
|
||||||
"Editor Theme": "Theme d'éditeur",
|
"Show a confirmation dialog when deleting notes": "Montrer une alerte de confirmation lors de la suppression de notes",
|
||||||
"Editor Font Size": "Taille de police de l'éditeur",
|
"Editor Theme": "Theme d'éditeur",
|
||||||
"Editor Font Family": "Police de l'éditeur",
|
"Editor Font Size": "Taille de police de l'éditeur",
|
||||||
"Editor Indent Style": "Style d'indentation de l'éditeur",
|
"Editor Font Family": "Police de l'éditeur",
|
||||||
"Spaces": "Espaces",
|
"Editor Indent Style": "Style d'indentation de l'éditeur",
|
||||||
"Tabs": "Tabulations",
|
"Spaces": "Espaces",
|
||||||
"Show only related tags": "Afficher uniquement les tags associés",
|
"Tabs": "Tabulations",
|
||||||
"Switch to Preview": "Switcher vers l'aperçu",
|
"Show only related tags": "Afficher uniquement les tags associés",
|
||||||
"When Editor Blurred": "Quand l'éditeur n'est pas sélectionné",
|
"Switch to Preview": "Switcher vers l'aperçu",
|
||||||
"When Editor Blurred, Edit On Double Click": "Quand l'éditeur n'est pas sélectionné, éditer avec un double clic",
|
"When Editor Blurred": "Quand l'éditeur n'est pas sélectionné",
|
||||||
"On Right Click": "Avec un clic droit",
|
"When Editor Blurred, Edit On Double Click": "Quand l'éditeur n'est pas sélectionné, éditer avec un double clic",
|
||||||
"Editor Keymap": "Keymap de l'éditeur",
|
"On Right Click": "Avec un clic droit",
|
||||||
"default": "Par défaut",
|
"Editor Keymap": "Keymap de l'éditeur",
|
||||||
"vim": "vim",
|
"default": "Par défaut",
|
||||||
"emacs": "emacs",
|
"vim": "vim",
|
||||||
"⚠️ Please restart boostnote after you change the keymap": "⚠️ Redémarrez Boostnote après avoir changé la keymap",
|
"emacs": "emacs",
|
||||||
"Show line numbers in the editor": "Montrer les numéros de lignes dans l'éditeur",
|
"⚠️ Please restart boostnote after you change the keymap": "⚠️ Redémarrez Boostnote après avoir changé la keymap",
|
||||||
"Allow editor to scroll past the last line": "Contrôle si l'éditeur défile au-delà de la dernière ligne",
|
"Show line numbers in the editor": "Montrer les numéros de lignes dans l'éditeur",
|
||||||
"Bring in web page title when pasting URL on editor": "Mettre le titre de la page lors d'un collé d'une URL dans l'éditeur",
|
"Allow editor to scroll past the last line": "Contrôle si l'éditeur défile au-delà de la dernière ligne",
|
||||||
"Preview": "Aperçu",
|
"Bring in web page title when pasting URL on editor": "Mettre le titre de la page lors d'un collé d'une URL dans l'éditeur",
|
||||||
"Preview Font Size": "Taille de police de l'aperçu",
|
"Preview": "Aperçu",
|
||||||
"Preview Font Family": "Police de l'aperçu",
|
"Preview Font Size": "Taille de police de l'aperçu",
|
||||||
"Code Block Theme": "Thème des blocs de code",
|
"Preview Font Family": "Police de l'aperçu",
|
||||||
"Show line numbers for preview code blocks": "Montrer les numéros de lignes dans les blocs de code dans l'aperçu",
|
"Code Block Theme": "Thème des blocs de code",
|
||||||
"Enable smart quotes": "Activer les citations intelligentes",
|
"Show line numbers for preview code blocks": "Montrer les numéros de lignes dans les blocs de code dans l'aperçu",
|
||||||
"LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter",
|
"Enable smart quotes": "Activer les citations intelligentes",
|
||||||
"LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter",
|
"LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter",
|
||||||
"LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter",
|
"LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter",
|
||||||
"LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter",
|
"LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter",
|
||||||
"PlantUML Server": "PlantUML Server",
|
"LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter",
|
||||||
"Community": "Communauté",
|
"PlantUML Server": "PlantUML Server",
|
||||||
"Subscribe to Newsletter": "Souscrire à la newsletter",
|
"Community": "Communauté",
|
||||||
"GitHub": "GitHub",
|
"Subscribe to Newsletter": "Souscrire à la newsletter",
|
||||||
"Blog": "Blog",
|
"GitHub": "GitHub",
|
||||||
"Facebook Group": "Groupe Facebook",
|
"Blog": "Blog",
|
||||||
"Twitter": "Twitter",
|
"Facebook Group": "Groupe Facebook",
|
||||||
"About": "A propos",
|
"Twitter": "Twitter",
|
||||||
"Boostnote": "Boostnote",
|
"About": "A propos",
|
||||||
"An open source note-taking app made for programmers just like you.": "Une appli de prise de notes open-source faite pour les développeurs comme vous.",
|
"Boostnote": "Boostnote",
|
||||||
"Website": "Site web",
|
"An open source note-taking app made for programmers just like you.": "Une appli de prise de notes open-source faite pour les développeurs comme vous.",
|
||||||
"Development": "Développement",
|
"Website": "Site web",
|
||||||
" : Development configurations for Boostnote.": " : Configurations de développement pour Boostnote.",
|
"Development": "Développement",
|
||||||
"Copyright (C) 2017 - 2019 BoostIO": "Copyright (C) 2017 - 2019 BoostIO",
|
" : Development configurations for Boostnote.": " : Configurations de développement pour Boostnote.",
|
||||||
"License: GPL v3": "License: GPL v3",
|
"Copyright (C) 2017 - 2019 BoostIO": "Copyright (C) 2017 - 2019 BoostIO",
|
||||||
"Analytics": "Analytics",
|
"License: GPL v3": "License: GPL v3",
|
||||||
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collecte des données anonymisées dans le seul but d'améliorer l'application, et ne collecte aucune donnée personnelle telle que le contenu de vos notes.",
|
"Analytics": "Analytics",
|
||||||
"You can see how it works on ": "Vous pouvez voir comment ça marche sur",
|
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collecte des données anonymisées dans le seul but d'améliorer l'application, et ne collecte aucune donnée personnelle telle que le contenu de vos notes.",
|
||||||
"You can choose to enable or disable this option.": "Vous pouvez choisir d'activer/désactiver cette option.",
|
"You can see how it works on ": "Vous pouvez voir comment ça marche sur",
|
||||||
"Enable analytics to help improve Boostnote": "Activer la collecte de données anonymisées pour améliorer Boostnote",
|
"You can choose to enable or disable this option.": "Vous pouvez choisir d'activer/désactiver cette option.",
|
||||||
"Crowdfunding": "Crowdfunding",
|
"Enable analytics to help improve Boostnote": "Activer la collecte de données anonymisées pour améliorer Boostnote",
|
||||||
"Dear Boostnote users,": "Cher utilisateur,",
|
"Crowdfunding": "Crowdfunding",
|
||||||
"Thank you for using Boostnote!": "Merci d'utiliser Boostnote !",
|
"Dear Boostnote users,": "Cher utilisateur,",
|
||||||
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote est utilisé dans plus de 200 pays et régions par une impressionnante communauté de développeurs.",
|
"Thank you for using Boostnote!": "Merci d'utiliser Boostnote !",
|
||||||
"To support our growing userbase, and satisfy community expectations,": "Afin de continuer à grandir, et de satisfaire les attentes de la communauté,",
|
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote est utilisé dans plus de 200 pays et régions par une impressionnante communauté de développeurs.",
|
||||||
"we would like to invest more time and resources in this project.": "nous aimerions investir d'avantage de temps et de ressources dans ce proje.",
|
"To support our growing userbase, and satisfy community expectations,": "Afin de continuer à grandir, et de satisfaire les attentes de la communauté,",
|
||||||
"If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "Si vous aimez ce projet et que vous en voyez tout le potentiel, vous pouvez aider par un support sur OpenCollective !",
|
"we would like to invest more time and resources in this project.": "nous aimerions investir d'avantage de temps et de ressources dans ce proje.",
|
||||||
"Thanks,": "Merci,",
|
"If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "Si vous aimez ce projet et que vous en voyez tout le potentiel, vous pouvez aider par un support sur OpenCollective !",
|
||||||
"The Boostnote Team": "Les mainteneurs de Boostnote",
|
"Thanks,": "Merci,",
|
||||||
"Support via OpenCollective": "Support via OpenCollective",
|
"The Boostnote Team": "Les mainteneurs de Boostnote",
|
||||||
"Language": "Langues",
|
"Support via OpenCollective": "Support via OpenCollective",
|
||||||
"Default New Note": "Nouvelle note par défaut",
|
"Language": "Langues",
|
||||||
"English": "Anglais",
|
"Default New Note": "Nouvelle note par défaut",
|
||||||
"German": "Allemand",
|
"English": "Anglais",
|
||||||
"French": "Français",
|
"German": "Allemand",
|
||||||
"Show \"Saved to Clipboard\" notification when copying": "Montrer la notification \"Sauvegardé dans le presse-papiers\" lors de la copie",
|
"French": "Français",
|
||||||
"All Notes": "Toutes les notes",
|
"Show \"Saved to Clipboard\" notification when copying": "Montrer la notification \"Sauvegardé dans le presse-papiers\" lors de la copie",
|
||||||
"Starred": "Favoris",
|
"All Notes": "Toutes les notes",
|
||||||
"Are you sure to ": "Etes-vous sûr de ",
|
"Starred": "Favoris",
|
||||||
" delete": " supprimer",
|
"Are you sure to ": "Etes-vous sûr de ",
|
||||||
"this folder?": "ce dossier ?",
|
" delete": " supprimer",
|
||||||
"Confirm": "Confimer",
|
"this folder?": "ce dossier ?",
|
||||||
"Cancel": "Annuler",
|
"Confirm": "Confimer",
|
||||||
"Markdown Note": "Note Markdown",
|
"Cancel": "Annuler",
|
||||||
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "Ce format est pour créer des documents texte. Checklists, blocks de code et blocks Latex sont disponibles.",
|
"Markdown Note": "Note Markdown",
|
||||||
"Snippet Note": "Note Snippet",
|
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "Ce format est pour créer des documents texte. Checklists, blocks de code et blocks Latex sont disponibles.",
|
||||||
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "Ce format est pour créer des snippets de code. Plusieurs snippets peuvent être groupés en une seule note.",
|
"Snippet Note": "Note Snippet",
|
||||||
"Tab to switch format": "Tab pour changer de format",
|
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "Ce format est pour créer des snippets de code. Plusieurs snippets peuvent être groupés en une seule note.",
|
||||||
"Updated": "Mis à jour",
|
"Tab to switch format": "Tab pour changer de format",
|
||||||
"Created": "Créé",
|
"Updated": "Mis à jour",
|
||||||
"Alphabetically": "De manière alphabétique",
|
"Created": "Créé",
|
||||||
"Default View": "Vue par défaut",
|
"Alphabetically": "De manière alphabétique",
|
||||||
"Compressed View": "Vue compressée",
|
"Default View": "Vue par défaut",
|
||||||
"Search": "Chercher",
|
"Compressed View": "Vue compressée",
|
||||||
"Blog Type": "Type du blog",
|
"Search": "Chercher",
|
||||||
"Blog Address": "Adresse du blog",
|
"Blog Type": "Type du blog",
|
||||||
"Save": "Sauvegarder",
|
"Blog Address": "Adresse du blog",
|
||||||
"Auth": "Auth",
|
"Save": "Sauvegarder",
|
||||||
"Authentication Method": "Méthode d'Authentification",
|
"Auth": "Auth",
|
||||||
"JWT": "JWT",
|
"Authentication Method": "Méthode d'Authentification",
|
||||||
"USER": "USER",
|
"JWT": "JWT",
|
||||||
"Token": "Token",
|
"USER": "USER",
|
||||||
"Storage": "Stockage",
|
"Token": "Token",
|
||||||
"Hotkeys": "Raccourcis",
|
"Storage": "Stockage",
|
||||||
"Show/Hide Boostnote": "Montrer/Cacher Boostnote",
|
"Hotkeys": "Raccourcis",
|
||||||
"Restore": "Restaurer",
|
"Show/Hide Boostnote": "Montrer/Cacher Boostnote",
|
||||||
"Permanent Delete": "Supprimer définivitement",
|
"Restore": "Restaurer",
|
||||||
"Confirm note deletion": "Confirmer la suppression de la note",
|
"Permanent Delete": "Supprimer définivitement",
|
||||||
"This will permanently remove this note.": "Cela va supprimer cette note définitivement.",
|
"Confirm note deletion": "Confirmer la suppression de la note",
|
||||||
"Successfully applied!": " Succès !",
|
"This will permanently remove this note.": "Cela va supprimer cette note définitivement.",
|
||||||
"Albanian": "Albanais",
|
"Successfully applied!": " Succès !",
|
||||||
"Chinese (zh-CN)": "Chinois (zh-CN)",
|
"Albanian": "Albanais",
|
||||||
"Chinese (zh-TW)": "Chinois (zh-TW)",
|
"Chinese (zh-CN)": "Chinois (zh-CN)",
|
||||||
"Toggle Editor Mode": "Basculer en mode éditeur",
|
"Chinese (zh-TW)": "Chinois (zh-TW)",
|
||||||
"Danish": "Danois",
|
"Czech": "Tchèque",
|
||||||
"Japanese": "Japonais",
|
"Toggle Editor Mode": "Basculer en mode éditeur",
|
||||||
"Korean": "Coréen",
|
"Danish": "Danois",
|
||||||
"Norwegian": "Norvégien",
|
"Japanese": "Japonais",
|
||||||
"Polish": "Polonais",
|
"Korean": "Coréen",
|
||||||
"Portuguese": "Portugais",
|
"Norwegian": "Norvégien",
|
||||||
"Spanish": "Espagnol",
|
"Polish": "Polonais",
|
||||||
"Unsaved Changes!": "Il faut sauvegarder !",
|
"Portuguese": "Portugais",
|
||||||
"Russian": "Russe",
|
"Spanish": "Espagnol",
|
||||||
"Thai": "Thai (ภาษาไทย)",
|
"Unsaved Changes!": "Il faut sauvegarder !",
|
||||||
"Command(⌘)": "Command(⌘)",
|
"Russian": "Russe",
|
||||||
"Editor Rulers": "Règles dans l'éditeur",
|
"Thai": "Thai (ภาษาไทย)",
|
||||||
"Enable": "Activer",
|
"Command(⌘)": "Command(⌘)",
|
||||||
"Disable": "Désactiver",
|
"Editor Rulers": "Règles dans l'éditeur",
|
||||||
"Allow preview to scroll past the last line": "Permettre de scroller après la dernière ligne dans l'aperçu",
|
"Enable": "Activer",
|
||||||
"Sanitization": "Sanitization",
|
"Disable": "Désactiver",
|
||||||
"Only allow secure html tags (recommended)": "N'accepter que les tags html sécurisés (recommandé)",
|
"Allow preview to scroll past the last line": "Permettre de scroller après la dernière ligne dans l'aperçu",
|
||||||
"Allow styles": "Accepter les styles",
|
"Sanitization": "Sanitization",
|
||||||
"Allow dangerous html tags": "Accepter les tags html dangereux",
|
"Only allow secure html tags (recommended)": "N'accepter que les tags html sécurisés (recommandé)",
|
||||||
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Convertir des flèches textuelles en jolis signes. ⚠ Cela va interferérer avec les éventuels commentaires HTML dans votre Markdown.",
|
"Allow styles": "Accepter les styles",
|
||||||
"⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ Vous avez collé un lien qui référence une pièce-jointe qui n'a pas pu être récupéré dans le dossier de stockage de la note. Coller des liens qui font référence à des pièces-jointes ne fonctionne que si la source et la destination et la même. Veuillez plutôt utiliser du Drag & Drop ! ⚠",
|
"Allow dangerous html tags": "Accepter les tags html dangereux",
|
||||||
"Save tags of a note in alphabetical order": "Sauvegarder les tags d'une note en ordre alphabétique",
|
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Convertir des flèches textuelles en jolis signes. ⚠ Cela va interferérer avec les éventuels commentaires HTML dans votre Markdown.",
|
||||||
"Show tags of a note in alphabetical order": "Afficher les tags d'une note par ordre alphabétique",
|
"⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ Vous avez collé un lien qui référence une pièce-jointe qui n'a pas pu être récupéré dans le dossier de stockage de la note. Coller des liens qui font référence à des pièces-jointes ne fonctionne que si la source et la destination et la même. Veuillez plutôt utiliser du Drag & Drop ! ⚠",
|
||||||
"Enable live count of notes": "Activer le comptage live des notes",
|
"Save tags of a note in alphabetical order": "Sauvegarder les tags d'une note en ordre alphabétique",
|
||||||
"Enable smart table editor": "Activer l'intelligent éditeur de tableaux",
|
"Show tags of a note in alphabetical order": "Afficher les tags d'une note par ordre alphabétique",
|
||||||
"Snippet Default Language": "Langage par défaut d'un snippet",
|
"Enable live count of notes": "Activer le comptage live des notes",
|
||||||
"Spellcheck disabled": "Spellcheck disabled",
|
"Enable smart table editor": "Activer l'intelligent éditeur de tableaux",
|
||||||
"Show menu bar": "Show menu bar",
|
"Snippet Default Language": "Langage par défaut d'un snippet",
|
||||||
"Auto Detect": "Auto Detect",
|
"Spellcheck disabled": "Spellcheck disabled",
|
||||||
"New Snippet": "Nouveau snippet",
|
"Show menu bar": "Show menu bar",
|
||||||
"Custom CSS": "CSS personnalisé",
|
"Auto Detect": "Auto Detect",
|
||||||
"Snippet name": "Nom du snippet",
|
"New Snippet": "Nouveau snippet",
|
||||||
"Snippet prefix": "Préfixe du snippet",
|
"Custom CSS": "CSS personnalisé",
|
||||||
"Delete Note": "Supprimer la note",
|
"Snippet name": "Nom du snippet",
|
||||||
"New notes are tagged with the filtering tags": "Les nouvelles notes sont taggées avec les tags de filtrage"
|
"Snippet prefix": "Préfixe du snippet",
|
||||||
|
"Delete Note": "Supprimer la note",
|
||||||
|
"New notes are tagged with the filtering tags": "Les nouvelles notes sont taggées avec les tags de filtrage",
|
||||||
|
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
|
||||||
|
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
|
||||||
}
|
}
|
||||||
|
|||||||
367
locales/hu.json
367
locales/hu.json
@@ -1,184 +1,187 @@
|
|||||||
{
|
{
|
||||||
"Notes": "Jegyzetek",
|
"Notes": "Jegyzetek",
|
||||||
"Tags": "Címkék",
|
"Tags": "Címkék",
|
||||||
"Preferences": "Beállítások",
|
"Preferences": "Beállítások",
|
||||||
"Make a note": "Új jegyzet",
|
"Make a note": "Új jegyzet",
|
||||||
"Ctrl": "Ctrl",
|
"Ctrl": "Ctrl",
|
||||||
"Ctrl(^)": "Ctrl",
|
"Ctrl(^)": "Ctrl",
|
||||||
"to create a new note": "hogy létrehozz egy jegyzetet",
|
"to create a new note": "hogy létrehozz egy jegyzetet",
|
||||||
"Toggle Mode": "Mód Váltás",
|
"Toggle Mode": "Mód Váltás",
|
||||||
"Add tag...": "Tag hozzáadása...",
|
"Add tag...": "Tag hozzáadása...",
|
||||||
"Trash": "Lomtár",
|
"Trash": "Lomtár",
|
||||||
"MODIFICATION DATE": "MÓDOSÍTÁS DÁTUMA",
|
"MODIFICATION DATE": "MÓDOSÍTÁS DÁTUMA",
|
||||||
"Words": "Szó",
|
"Words": "Szó",
|
||||||
"Letters": "Betű",
|
"Letters": "Betű",
|
||||||
"STORAGE": "TÁROLÓ",
|
"STORAGE": "TÁROLÓ",
|
||||||
"FOLDER": "KÖNYVTÁR",
|
"FOLDER": "KÖNYVTÁR",
|
||||||
"CREATION DATE": "LÉTREHOZÁS DÁTUMA",
|
"CREATION DATE": "LÉTREHOZÁS DÁTUMA",
|
||||||
"NOTE LINK": "JEGYZET LINKJE",
|
"NOTE LINK": "JEGYZET LINKJE",
|
||||||
".md": ".md",
|
".md": ".md",
|
||||||
".txt": ".txt",
|
".txt": ".txt",
|
||||||
".html": ".html",
|
".html": ".html",
|
||||||
".pdf": ".pdf",
|
".pdf": ".pdf",
|
||||||
"Print": "Nyomtatás",
|
"Print": "Nyomtatás",
|
||||||
"Your preferences for Boostnote": "Boostnote beállításaid",
|
"Your preferences for Boostnote": "Boostnote beállításaid",
|
||||||
"Help": "Súgó",
|
"Help": "Súgó",
|
||||||
"Hide Help": "Súgó Elrejtése",
|
"Hide Help": "Súgó Elrejtése",
|
||||||
"Storage Locations": "Tárolók",
|
"Storage Locations": "Tárolók",
|
||||||
"Add Storage Location": "Tároló Hozzáadása",
|
"Add Storage Location": "Tároló Hozzáadása",
|
||||||
"Add Folder": "Könyvtár Hozzáadása",
|
"Add Folder": "Könyvtár Hozzáadása",
|
||||||
"Open Storage folder": "Tároló Megnyitása",
|
"Open Storage folder": "Tároló Megnyitása",
|
||||||
"Unlink": "Tároló Leválasztása",
|
"Unlink": "Tároló Leválasztása",
|
||||||
"Edit": "Szerkesztés",
|
"Edit": "Szerkesztés",
|
||||||
"Delete": "Törlés",
|
"Delete": "Törlés",
|
||||||
"Interface": "Felület",
|
"Interface": "Felület",
|
||||||
"Interface Theme": "Felület Témája",
|
"Interface Theme": "Felület Témája",
|
||||||
"Default": "Alapértelmezett",
|
"Default": "Alapértelmezett",
|
||||||
"White": "Világos",
|
"White": "Világos",
|
||||||
"Solarized Dark": "Solarized Dark",
|
"Solarized Dark": "Solarized Dark",
|
||||||
"Dark": "Sötét",
|
"Dark": "Sötét",
|
||||||
"Show a confirmation dialog when deleting notes": "Kérjen megerősítést a jegyzetek törlése előtt",
|
"Show a confirmation dialog when deleting notes": "Kérjen megerősítést a jegyzetek törlése előtt",
|
||||||
"Disable Direct Write (It will be applied after restarting)": "Jegyzet Azonnali Mentésének Tiltása (Újraindítás igényel)",
|
"Disable Direct Write (It will be applied after restarting)": "Jegyzet Azonnali Mentésének Tiltása (Újraindítás igényel)",
|
||||||
"Show only related tags": "Csak a kapcsolódó tag-ek megjelenítése",
|
"Show only related tags": "Csak a kapcsolódó tag-ek megjelenítése",
|
||||||
"Editor Theme": "Szerkesztő Témája",
|
"Editor Theme": "Szerkesztő Témája",
|
||||||
"Editor Font Size": "Szerkesztő Betűmérete",
|
"Editor Font Size": "Szerkesztő Betűmérete",
|
||||||
"Editor Font Family": "Szerkesztő Betűtípusa",
|
"Editor Font Family": "Szerkesztő Betűtípusa",
|
||||||
"Editor Indent Style": "Szerkesztő Behúzása",
|
"Editor Indent Style": "Szerkesztő Behúzása",
|
||||||
"Spaces": "Szóközök",
|
"Spaces": "Szóközök",
|
||||||
"Tabs": "Tabulátor karakterek",
|
"Tabs": "Tabulátor karakterek",
|
||||||
"Switch to Preview": "Váltás Megtekintésre",
|
"Switch to Preview": "Váltás Megtekintésre",
|
||||||
"When Editor Blurred": "Szerkesztő Elhagyásakor",
|
"When Editor Blurred": "Szerkesztő Elhagyásakor",
|
||||||
"When Editor Blurred, Edit On Double Click": "Szerkesztő Elhagyásakor, Szerkesztő Megnyitása Dupla Kattintással",
|
"When Editor Blurred, Edit On Double Click": "Szerkesztő Elhagyásakor, Szerkesztő Megnyitása Dupla Kattintással",
|
||||||
"On Right Click": "Jobb Egérgombbal",
|
"On Right Click": "Jobb Egérgombbal",
|
||||||
"Editor Keymap": "Szerkesztő Billentyűzetkiosztása",
|
"Editor Keymap": "Szerkesztő Billentyűzetkiosztása",
|
||||||
"default": "alapértelmezett",
|
"default": "alapértelmezett",
|
||||||
"vim": "vim",
|
"vim": "vim",
|
||||||
"emacs": "emacs",
|
"emacs": "emacs",
|
||||||
"⚠️ Please restart boostnote after you change the keymap": "⚠️ Kérlek, indítsd újra a programot a kiosztás megváltoztatása után",
|
"⚠️ Please restart boostnote after you change the keymap": "⚠️ Kérlek, indítsd újra a programot a kiosztás megváltoztatása után",
|
||||||
"Show line numbers in the editor": "Mutatassa a sorszámokat a szerkesztőben",
|
"Show line numbers in the editor": "Mutatassa a sorszámokat a szerkesztőben",
|
||||||
"Allow editor to scroll past the last line": "A szerkesztőben az utolsó sor alá is lehessen görgetni",
|
"Allow editor to scroll past the last line": "A szerkesztőben az utolsó sor alá is lehessen görgetni",
|
||||||
"Enable smart quotes": "Idézőjelek párjának automatikus beírása",
|
"Enable smart quotes": "Idézőjelek párjának automatikus beírása",
|
||||||
"Bring in web page title when pasting URL on editor": "Weboldal főcímének lekérdezése URL cím beillesztésekor",
|
"Bring in web page title when pasting URL on editor": "Weboldal főcímének lekérdezése URL cím beillesztésekor",
|
||||||
"Preview": "Megtekintés",
|
"Preview": "Megtekintés",
|
||||||
"Preview Font Size": "Megtekintés Betűmérete",
|
"Preview Font Size": "Megtekintés Betűmérete",
|
||||||
"Preview Font Family": "Megtekintés Betűtípusa",
|
"Preview Font Family": "Megtekintés Betűtípusa",
|
||||||
"Code Block Theme": "Kódblokk Témája",
|
"Code Block Theme": "Kódblokk Témája",
|
||||||
"Allow preview to scroll past the last line": "Megtekintésben az utolsó sor alá is lehessen görgetni",
|
"Allow preview to scroll past the last line": "Megtekintésben az utolsó sor alá is lehessen görgetni",
|
||||||
"Show line numbers for preview code blocks": "Mutatassa a sorszámokat a megtekintett kódblokkokban",
|
"Show line numbers for preview code blocks": "Mutatassa a sorszámokat a megtekintett kódblokkokban",
|
||||||
"LaTeX Inline Open Delimiter": "LaTeX Inline Nyitó Határolója",
|
"LaTeX Inline Open Delimiter": "LaTeX Inline Nyitó Határolója",
|
||||||
"LaTeX Inline Close Delimiter": "LaTeX Inline Záró Határolója",
|
"LaTeX Inline Close Delimiter": "LaTeX Inline Záró Határolója",
|
||||||
"LaTeX Block Open Delimiter": "LaTeX Blokk Nyitó Határolója",
|
"LaTeX Block Open Delimiter": "LaTeX Blokk Nyitó Határolója",
|
||||||
"LaTeX Block Close Delimiter": "LaTeX Blokk Záró Határolója",
|
"LaTeX Block Close Delimiter": "LaTeX Blokk Záró Határolója",
|
||||||
"PlantUML Server": "PlantUML Server",
|
"PlantUML Server": "PlantUML Server",
|
||||||
"Community": "Közösség",
|
"Community": "Közösség",
|
||||||
"Subscribe to Newsletter": "Feliratkozás a Hírlevélre",
|
"Subscribe to Newsletter": "Feliratkozás a Hírlevélre",
|
||||||
"GitHub": "GitHub",
|
"GitHub": "GitHub",
|
||||||
"Blog": "Blog",
|
"Blog": "Blog",
|
||||||
"Facebook Group": "Facebook Csoport",
|
"Facebook Group": "Facebook Csoport",
|
||||||
"Twitter": "Twitter",
|
"Twitter": "Twitter",
|
||||||
"About": "Névjegy",
|
"About": "Névjegy",
|
||||||
"Boostnote": "Boostnote",
|
"Boostnote": "Boostnote",
|
||||||
"An open source note-taking app made for programmers just like you.": "Nyílt forráskódú jegyzetkészítő program a hozzád hasonló programozóknak.",
|
"An open source note-taking app made for programmers just like you.": "Nyílt forráskódú jegyzetkészítő program a hozzád hasonló programozóknak.",
|
||||||
"Website": "Weboldal",
|
"Website": "Weboldal",
|
||||||
"Development": "Fejlesztés",
|
"Development": "Fejlesztés",
|
||||||
" : Development configurations for Boostnote.": " : Információk a Boostnote fejlesztéséről.",
|
" : Development configurations for Boostnote.": " : Információk a Boostnote fejlesztéséről.",
|
||||||
"Copyright (C) 2017 - 2019 BoostIO": "Szerzői jog (C) 2017 - 2019 BoostIO",
|
"Copyright (C) 2017 - 2019 BoostIO": "Szerzői jog (C) 2017 - 2019 BoostIO",
|
||||||
"License: GPL v3": "Licensz: GPL v3",
|
"License: GPL v3": "Licensz: GPL v3",
|
||||||
"Analytics": "Adatok elemzése",
|
"Analytics": "Adatok elemzése",
|
||||||
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "A Boostnote névtelen adatokat gyűjt össze az alkalmazás tökéletesítése céljából, és szigorúan nem gyűjt semmilyen személyes adatot, például a jegyzetek tartalmát.",
|
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "A Boostnote névtelen adatokat gyűjt össze az alkalmazás tökéletesítése céljából, és szigorúan nem gyűjt semmilyen személyes adatot, például a jegyzetek tartalmát.",
|
||||||
"You can see how it works on ": "A működéséről további információkat itt találsz: ",
|
"You can see how it works on ": "A működéséről további információkat itt találsz: ",
|
||||||
"You can choose to enable or disable this option.": "Kiválaszthatod, hogy engedélyezed, vagy tiltod ezt az opciót.",
|
"You can choose to enable or disable this option.": "Kiválaszthatod, hogy engedélyezed, vagy tiltod ezt az opciót.",
|
||||||
"Enable analytics to help improve Boostnote": "Adatok elemzésének engedélyezése a Boostnote tökéletesítésének céljából",
|
"Enable analytics to help improve Boostnote": "Adatok elemzésének engedélyezése a Boostnote tökéletesítésének céljából",
|
||||||
"Crowdfunding": "Közösségi finanszírozás",
|
"Crowdfunding": "Közösségi finanszírozás",
|
||||||
"Dear Boostnote users,": "Kedves felhasználók!",
|
"Dear Boostnote users,": "Kedves felhasználók!",
|
||||||
"Thank you for using Boostnote!": "Köszönjük, hogy a Boostnote-ot használjátok!",
|
"Thank you for using Boostnote!": "Köszönjük, hogy a Boostnote-ot használjátok!",
|
||||||
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "A Boostnote-ot több, mint 200 ország és régió fantasztikus fejlesztői használják.",
|
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "A Boostnote-ot több, mint 200 ország és régió fantasztikus fejlesztői használják.",
|
||||||
"To support our growing userbase, and satisfy community expectations,": "Hogy folytathassuk ezt a fejlődést és kielégíthessük a felhasználói elvárásokat,",
|
"To support our growing userbase, and satisfy community expectations,": "Hogy folytathassuk ezt a fejlődést és kielégíthessük a felhasználói elvárásokat,",
|
||||||
"we would like to invest more time and resources in this project.": "több időt és erőforrást szeretnénk a projektbe fektetni.",
|
"we would like to invest more time and resources in this project.": "több időt és erőforrást szeretnénk a projektbe fektetni.",
|
||||||
"If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "Ha tetszik a projekt és hasznosnak találod, te is segíthetsz ebben az OpenCollective-en keresztül küldött támogatásoddal.",
|
"If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "Ha tetszik a projekt és hasznosnak találod, te is segíthetsz ebben az OpenCollective-en keresztül küldött támogatásoddal.",
|
||||||
"Thanks,": "Köszönjük!",
|
"Thanks,": "Köszönjük!",
|
||||||
"The Boostnote Team": "A Boostnote csapata",
|
"The Boostnote Team": "A Boostnote csapata",
|
||||||
"Support via OpenCollective": "Támogatás Küldése",
|
"Support via OpenCollective": "Támogatás Küldése",
|
||||||
"Language": "Nyelv",
|
"Language": "Nyelv",
|
||||||
"English": "English",
|
"English": "English",
|
||||||
"German": "German",
|
"German": "German",
|
||||||
"French": "French",
|
"French": "French",
|
||||||
"Show \"Saved to Clipboard\" notification when copying": "Mutassa a \"Vágólapra Másolva\" üzenetet másoláskor",
|
"Show \"Saved to Clipboard\" notification when copying": "Mutassa a \"Vágólapra Másolva\" üzenetet másoláskor",
|
||||||
"All Notes": "Minden Jegyzet",
|
"All Notes": "Minden Jegyzet",
|
||||||
"Starred": "Kiemelt",
|
"Starred": "Kiemelt",
|
||||||
"Are you sure to ": "Biztos, hogy ",
|
"Are you sure to ": "Biztos, hogy ",
|
||||||
" delete": " törölni",
|
" delete": " törölni",
|
||||||
"this folder?": "szeretnéd a könyvtárat?",
|
"this folder?": "szeretnéd a könyvtárat?",
|
||||||
"Confirm": "Igen",
|
"Confirm": "Igen",
|
||||||
"Cancel": "Mégse",
|
"Cancel": "Mégse",
|
||||||
"Markdown Note": "Markdown Jegyzet",
|
"Markdown Note": "Markdown Jegyzet",
|
||||||
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "Ez a formátum szöveges dokumentumok készítésére használható. Jelölőnégyzeteket, kódblokkokat és Latex blokkokat is tartalmazhat.",
|
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "Ez a formátum szöveges dokumentumok készítésére használható. Jelölőnégyzeteket, kódblokkokat és Latex blokkokat is tartalmazhat.",
|
||||||
"Snippet Note": "Kód Jegyzet",
|
"Snippet Note": "Kód Jegyzet",
|
||||||
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "Ez a formátum kódrészletek készítésére használható. Több kódrészlet tárolására is alkalmas (pl. HTML + CSS).",
|
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "Ez a formátum kódrészletek készítésére használható. Több kódrészlet tárolására is alkalmas (pl. HTML + CSS).",
|
||||||
"Tab to switch format": "Formátum váltásához nyomd le a Tabulátor billentyűt!",
|
"Tab to switch format": "Formátum váltásához nyomd le a Tabulátor billentyűt!",
|
||||||
"Updated": "Módosítás",
|
"Updated": "Módosítás",
|
||||||
"Created": "Létrehozás",
|
"Created": "Létrehozás",
|
||||||
"Alphabetically": "Ábécé sorrendben",
|
"Alphabetically": "Ábécé sorrendben",
|
||||||
"Counter": "Számláló",
|
"Counter": "Számláló",
|
||||||
"Default View": "Alapértelmezett Nézet",
|
"Default View": "Alapértelmezett Nézet",
|
||||||
"Compressed View": "Tömörített Nézet",
|
"Compressed View": "Tömörített Nézet",
|
||||||
"Search": "Keresés",
|
"Search": "Keresés",
|
||||||
"Blog Type": "Blog Típusa",
|
"Blog Type": "Blog Típusa",
|
||||||
"Blog Address": "Blog Címe",
|
"Blog Address": "Blog Címe",
|
||||||
"Save": "Mentés",
|
"Save": "Mentés",
|
||||||
"Auth": "Hitelesítés",
|
"Auth": "Hitelesítés",
|
||||||
"Authentication Method": "Hitelesítési Módszer",
|
"Authentication Method": "Hitelesítési Módszer",
|
||||||
"JWT": "JWT",
|
"JWT": "JWT",
|
||||||
"USER": "USER",
|
"USER": "USER",
|
||||||
"Token": "Token",
|
"Token": "Token",
|
||||||
"Storage": "Tároló",
|
"Storage": "Tároló",
|
||||||
"Hotkeys": "Gyorsbillentyűk",
|
"Hotkeys": "Gyorsbillentyűk",
|
||||||
"Show/Hide Boostnote": "Boostnote Megjelenítése/Elrejtése",
|
"Show/Hide Boostnote": "Boostnote Megjelenítése/Elrejtése",
|
||||||
"Toggle Editor Mode": "Szerkesztő mód váltása",
|
"Toggle Editor Mode": "Szerkesztő mód váltása",
|
||||||
"Restore": "Visszaállítás",
|
"Restore": "Visszaállítás",
|
||||||
"Permanent Delete": "Végleges Törlés",
|
"Permanent Delete": "Végleges Törlés",
|
||||||
"Confirm note deletion": "Törlés megerősítése",
|
"Confirm note deletion": "Törlés megerősítése",
|
||||||
"This will permanently remove this note.": "A jegyzet véglegesen törölve lesz.",
|
"This will permanently remove this note.": "A jegyzet véglegesen törölve lesz.",
|
||||||
"Successfully applied!": "Sikeresen alkalmazva.",
|
"Successfully applied!": "Sikeresen alkalmazva.",
|
||||||
"Albanian": "Albanian",
|
"Albanian": "Albanian",
|
||||||
"Chinese (zh-CN)": "Chinese (zh-CN)",
|
"Chinese (zh-CN)": "Chinese (zh-CN)",
|
||||||
"Chinese (zh-TW)": "Chinese (zh-TW)",
|
"Chinese (zh-TW)": "Chinese (zh-TW)",
|
||||||
"Danish": "Danish",
|
"Czech": "Czech",
|
||||||
"Japanese": "Japanese",
|
"Danish": "Danish",
|
||||||
"Korean": "Korean",
|
"Japanese": "Japanese",
|
||||||
"Norwegian": "Norwegian",
|
"Korean": "Korean",
|
||||||
"Polish": "Polish",
|
"Norwegian": "Norwegian",
|
||||||
"Portuguese": "Portuguese",
|
"Polish": "Polish",
|
||||||
"Spanish": "Spanish",
|
"Portuguese": "Portuguese",
|
||||||
"Unsaved Changes!": "Mentened kell!",
|
"Spanish": "Spanish",
|
||||||
"UserName": "FelhasznaloNev",
|
"Unsaved Changes!": "Mentened kell!",
|
||||||
"Password": "Jelszo",
|
"UserName": "FelhasznaloNev",
|
||||||
"Russian": "Russian",
|
"Password": "Jelszo",
|
||||||
"Hungarian": "Hungarian",
|
"Russian": "Russian",
|
||||||
"Thai": "Thai (ภาษาไทย)",
|
"Hungarian": "Hungarian",
|
||||||
"Command(⌘)": "Command(⌘)",
|
"Thai": "Thai (ภาษาไทย)",
|
||||||
"Add Storage": "Tároló hozzáadása",
|
"Command(⌘)": "Command(⌘)",
|
||||||
"Name": "Név",
|
"Add Storage": "Tároló hozzáadása",
|
||||||
"Type": "Típus",
|
"Name": "Név",
|
||||||
"File System": "Fájlrendszer",
|
"Type": "Típus",
|
||||||
"Setting up 3rd-party cloud storage integration:": "Harmadik féltől származó felhőtárolási integráció beállítása:",
|
"File System": "Fájlrendszer",
|
||||||
"Cloud-Syncing-and-Backup": "Cloud-Syncing-and-Backup",
|
"Setting up 3rd-party cloud storage integration:": "Harmadik féltől származó felhőtárolási integráció beállítása:",
|
||||||
"Location": "Hely",
|
"Cloud-Syncing-and-Backup": "Cloud-Syncing-and-Backup",
|
||||||
"Add": "Hozzáadás",
|
"Location": "Hely",
|
||||||
"Select Folder": "Könyvtár Kiválasztása",
|
"Add": "Hozzáadás",
|
||||||
"Unlink Storage": "Tároló Leválasztása",
|
"Select Folder": "Könyvtár Kiválasztása",
|
||||||
"Unlinking removes this linked storage from Boostnote. No data is removed, please manually delete the folder from your hard drive if needed.": "A leválasztás eltávolítja ezt a tárolót a Boostnote-ból. Az adatok nem lesznek törölve, kérlek manuálisan töröld a könyvtárat a merevlemezről, ha szükséges.",
|
"Unlink Storage": "Tároló Leválasztása",
|
||||||
"Editor Rulers": "Szerkesztő Margók",
|
"Unlinking removes this linked storage from Boostnote. No data is removed, please manually delete the folder from your hard drive if needed.": "A leválasztás eltávolítja ezt a tárolót a Boostnote-ból. Az adatok nem lesznek törölve, kérlek manuálisan töröld a könyvtárat a merevlemezről, ha szükséges.",
|
||||||
"Enable": "Engedélyezés",
|
"Editor Rulers": "Szerkesztő Margók",
|
||||||
"Disable": "Tiltás",
|
"Enable": "Engedélyezés",
|
||||||
"Sanitization": "Tisztítás",
|
"Disable": "Tiltás",
|
||||||
"Only allow secure html tags (recommended)": "Csak a biztonságos html tag-ek engedélyezése (ajánlott)",
|
"Sanitization": "Tisztítás",
|
||||||
"Render newlines in Markdown paragraphs as <br>": "Az újsor karaktert <br> soremelésként jelenítse meg a Markdown jegyzetekben",
|
"Only allow secure html tags (recommended)": "Csak a biztonságos html tag-ek engedélyezése (ajánlott)",
|
||||||
"Allow styles": "Stílusok engedélyezése",
|
"Render newlines in Markdown paragraphs as <br>": "Az újsor karaktert <br> soremelésként jelenítse meg a Markdown jegyzetekben",
|
||||||
"Allow dangerous html tags": "Veszélyes html tag-ek engedélyezése",
|
"Allow styles": "Stílusok engedélyezése",
|
||||||
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.",
|
"Allow dangerous html tags": "Veszélyes html tag-ek engedélyezése",
|
||||||
"⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠",
|
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.",
|
||||||
"Spellcheck disabled": "Spellcheck disabled",
|
"⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠",
|
||||||
"Show menu bar": "Show menu bar",
|
"Spellcheck disabled": "Spellcheck disabled",
|
||||||
"Auto Detect": "Auto Detect"
|
"Show menu bar": "Show menu bar",
|
||||||
|
"Auto Detect": "Auto Detect",
|
||||||
|
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
|
||||||
|
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user