1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-13 01:36:22 +00:00

Merge branch 'master' into spellchecker

This commit is contained in:
ehhc
2018-11-02 10:41:30 +01:00
committed by GitHub
113 changed files with 4066 additions and 765 deletions

View File

@@ -1,15 +1,25 @@
# Current behavior # Current behavior
<!-- <!--
Please paste some **screenshots** with the **developer tool** open (console tab) when you report a bug. Let us know what is currently happening.
If your issue is regarding boostnote mobile, move to https://github.com/BoostIO/boostnote-mobile. Please include some **screenshots** with the **developer tools** open (console tab) when you report a bug.
If your issue is regarding Boostnote mobile, please open an issue in the Boostnote Mobile repo 👉 https://github.com/BoostIO/boostnote-mobile.
--> -->
# Expected behavior # Expected behavior
<!--
Let us know what you think should happen!
-->
# Steps to reproduce # Steps to reproduce
<!--
Please be thorough, issues we can reproduce are easier to fix!
-->
1. 1.
2. 2.
3. 3.

View File

@@ -5,7 +5,7 @@ import CodeMirror from 'codemirror'
import 'codemirror-mode-elixir' import 'codemirror-mode-elixir'
import attachmentManagement from 'browser/main/lib/dataApi/attachmentManagement' import attachmentManagement from 'browser/main/lib/dataApi/attachmentManagement'
import convertModeName from 'browser/lib/convertModeName' import convertModeName from 'browser/lib/convertModeName'
import { options, TableEditor } from '@susisu/mte-kernel' import { options, TableEditor, Alignment } from '@susisu/mte-kernel'
import TextEditorInterface from 'browser/lib/TextEditorInterface' import TextEditorInterface from 'browser/lib/TextEditorInterface'
import eventEmitter from 'browser/main/lib/eventEmitter' import eventEmitter from 'browser/main/lib/eventEmitter'
import iconv from 'iconv-lite' import iconv from 'iconv-lite'
@@ -17,6 +17,8 @@ const { ipcRenderer, remote } = 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')
import TurndownService from 'turndown'
import { gfm } from 'turndown-plugin-gfm'
CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js' CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js'
@@ -60,15 +62,16 @@ 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.formatTable = () => this.handleFormatTable() this.formatTable = () => this.handleFormatTable()
this.contextMenuHandler = function (editor, event) { this.contextMenuHandler = function (editor, event) {
const menu = buildEditorContextMenu(editor, event) const menu = buildEditorContextMenu(editor, event)
if (menu != null) { if (menu != null) {
setTimeout(() => menu.popup(remote.getCurrentWindow()), 30) setTimeout(() => menu.popup(remote.getCurrentWindow()), 30)
} }
} }
this.editorActivityHandler = () => this.handleEditorActivity()
} }
handleSearch (msg) { handleSearch (msg) {
@@ -109,9 +112,32 @@ export default class CodeEditor extends React.Component {
this.tableEditor.formatAll(options({textWidthOptions: {}})) this.tableEditor.formatAll(options({textWidthOptions: {}}))
} }
handleEditorActivity () {
if (!this.textEditorInterface.transaction) {
this.updateTableEditorState()
}
}
updateTableEditorState () {
const active = this.tableEditor.cursorIsInTable(this.tableEditorOptions)
if (active) {
if (this.extraKeysMode !== 'editor') {
this.extraKeysMode = 'editor'
this.editor.setOption('extraKeys', this.editorKeyMap)
}
} else {
if (this.extraKeysMode !== 'default') {
this.extraKeysMode = 'default'
this.editor.setOption('extraKeys', this.defaultKeyMap)
this.tableEditor.resetSmartCursor()
}
}
}
componentDidMount () { componentDidMount () {
const { rulers, enableRulers } = this.props const { rulers, enableRulers } = this.props
const expandSnippet = this.expandSnippet.bind(this) const expandSnippet = this.expandSnippet.bind(this)
eventEmitter.on('line:jump', this.scrollToLineHandeler)
const defaultSnippet = [ const defaultSnippet = [
{ {
@@ -129,6 +155,59 @@ export default class CodeEditor extends React.Component {
) )
} }
this.defaultKeyMap = CodeMirror.normalizeKeyMap({
Tab: function (cm) {
const cursor = cm.getCursor()
const line = cm.getLine(cursor.line)
const cursorPosition = cursor.ch
const charBeforeCursor = line.substr(cursorPosition - 1, 1)
if (cm.somethingSelected()) cm.indentSelection('add')
else {
const tabs = cm.getOption('indentWithTabs')
if (line.trimLeft().match(/^(-|\*|\+) (\[( |x)] )?$/)) {
cm.execCommand('goLineStart')
if (tabs) {
cm.execCommand('insertTab')
} else {
cm.execCommand('insertSoftTab')
}
cm.execCommand('goLineEnd')
} else if (
!charBeforeCursor.match(/\t|\s|\r|\n/) &&
cursor.ch > 1
) {
// text expansion on tab key if the char before is alphabet
const snippets = JSON.parse(
fs.readFileSync(consts.SNIPPET_FILE, 'utf8')
)
if (expandSnippet(line, cursor, cm, snippets) === false) {
if (tabs) {
cm.execCommand('insertTab')
} else {
cm.execCommand('insertSoftTab')
}
}
} else {
if (tabs) {
cm.execCommand('insertTab')
} else {
cm.execCommand('insertSoftTab')
}
}
}
},
'Cmd-T': function (cm) {
// Do nothing
},
Enter: 'boostNewLineAndIndentContinueMarkdownList',
'Ctrl-C': cm => {
if (cm.getOption('keyMap').substr(0, 3) === 'vim') {
document.execCommand('copy')
}
return CodeMirror.Pass
}
})
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),
@@ -151,58 +230,7 @@ export default class CodeEditor extends React.Component {
explode: '[]{}``$$', explode: '[]{}``$$',
override: true override: true
}, },
extraKeys: { extraKeys: this.defaultKeyMap
Tab: function (cm) {
const cursor = cm.getCursor()
const line = cm.getLine(cursor.line)
const cursorPosition = cursor.ch
const charBeforeCursor = line.substr(cursorPosition - 1, 1)
if (cm.somethingSelected()) cm.indentSelection('add')
else {
const tabs = cm.getOption('indentWithTabs')
if (line.trimLeft().match(/^(-|\*|\+) (\[( |x)] )?$/)) {
cm.execCommand('goLineStart')
if (tabs) {
cm.execCommand('insertTab')
} else {
cm.execCommand('insertSoftTab')
}
cm.execCommand('goLineEnd')
} else if (
!charBeforeCursor.match(/\t|\s|\r|\n/) &&
cursor.ch > 1
) {
// text expansion on tab key if the char before is alphabet
const snippets = JSON.parse(
fs.readFileSync(consts.SNIPPET_FILE, 'utf8')
)
if (expandSnippet(line, cursor, cm, snippets) === false) {
if (tabs) {
cm.execCommand('insertTab')
} else {
cm.execCommand('insertSoftTab')
}
}
} else {
if (tabs) {
cm.execCommand('insertTab')
} else {
cm.execCommand('insertSoftTab')
}
}
}
},
'Cmd-T': function (cm) {
// Do nothing
},
Enter: 'boostNewLineAndIndentContinueMarkdownList',
'Ctrl-C': cm => {
if (cm.getOption('keyMap').substr(0, 3) === 'vim') {
document.execCommand('copy')
}
return CodeMirror.Pass
}
}
}) })
this.setMode(this.props.mode) this.setMode(this.props.mode)
@@ -226,11 +254,66 @@ export default class CodeEditor extends React.Component {
CodeMirror.Vim.defineEx('qw', 'qw', this.quitEditor) CodeMirror.Vim.defineEx('qw', 'qw', this.quitEditor)
CodeMirror.Vim.map('ZZ', ':q', 'normal') CodeMirror.Vim.map('ZZ', ':q', 'normal')
this.tableEditor = new TableEditor(new TextEditorInterface(this.editor)) this.textEditorInterface = new TextEditorInterface(this.editor)
this.tableEditor = new TableEditor(this.textEditorInterface)
if (this.props.spellCheck) { if (this.props.spellCheck) {
this.editor.addPanel(this.createSpellCheckPanel(), {position: 'bottom'}) this.editor.addPanel(this.createSpellCheckPanel(), {position: 'bottom'})
} }
eventEmitter.on('code:format-table', this.formatTable) eventEmitter.on('code:format-table', this.formatTable)
this.tableEditorOptions = options({
smartCursor: true
})
this.editorKeyMap = CodeMirror.normalizeKeyMap({
'Tab': () => { this.tableEditor.nextCell(this.tableEditorOptions) },
'Shift-Tab': () => { this.tableEditor.previousCell(this.tableEditorOptions) },
'Enter': () => { this.tableEditor.nextRow(this.tableEditorOptions) },
'Ctrl-Enter': () => { this.tableEditor.escape(this.tableEditorOptions) },
'Cmd-Enter': () => { this.tableEditor.escape(this.tableEditorOptions) },
'Shift-Ctrl-Left': () => { this.tableEditor.alignColumn(Alignment.LEFT, this.tableEditorOptions) },
'Shift-Cmd-Left': () => { this.tableEditor.alignColumn(Alignment.LEFT, this.tableEditorOptions) },
'Shift-Ctrl-Right': () => { this.tableEditor.alignColumn(Alignment.RIGHT, this.tableEditorOptions) },
'Shift-Cmd-Right': () => { this.tableEditor.alignColumn(Alignment.RIGHT, this.tableEditorOptions) },
'Shift-Ctrl-Up': () => { this.tableEditor.alignColumn(Alignment.CENTER, this.tableEditorOptions) },
'Shift-Cmd-Up': () => { this.tableEditor.alignColumn(Alignment.CENTER, this.tableEditorOptions) },
'Shift-Ctrl-Down': () => { this.tableEditor.alignColumn(Alignment.NONE, this.tableEditorOptions) },
'Shift-Cmd-Down': () => { this.tableEditor.alignColumn(Alignment.NONE, this.tableEditorOptions) },
'Ctrl-Left': () => { this.tableEditor.moveFocus(0, -1, this.tableEditorOptions) },
'Cmd-Left': () => { this.tableEditor.moveFocus(0, -1, this.tableEditorOptions) },
'Ctrl-Right': () => { this.tableEditor.moveFocus(0, 1, this.tableEditorOptions) },
'Cmd-Right': () => { this.tableEditor.moveFocus(0, 1, this.tableEditorOptions) },
'Ctrl-Up': () => { this.tableEditor.moveFocus(-1, 0, this.tableEditorOptions) },
'Cmd-Up': () => { this.tableEditor.moveFocus(-1, 0, this.tableEditorOptions) },
'Ctrl-Down': () => { this.tableEditor.moveFocus(1, 0, this.tableEditorOptions) },
'Cmd-Down': () => { this.tableEditor.moveFocus(1, 0, this.tableEditorOptions) },
'Ctrl-K Ctrl-I': () => { this.tableEditor.insertRow(this.tableEditorOptions) },
'Cmd-K Cmd-I': () => { this.tableEditor.insertRow(this.tableEditorOptions) },
'Ctrl-L Ctrl-I': () => { this.tableEditor.deleteRow(this.tableEditorOptions) },
'Cmd-L Cmd-I': () => { this.tableEditor.deleteRow(this.tableEditorOptions) },
'Ctrl-K Ctrl-J': () => { this.tableEditor.insertColumn(this.tableEditorOptions) },
'Cmd-K Cmd-J': () => { this.tableEditor.insertColumn(this.tableEditorOptions) },
'Ctrl-L Ctrl-J': () => { this.tableEditor.deleteColumn(this.tableEditorOptions) },
'Cmd-L Cmd-J': () => { this.tableEditor.deleteColumn(this.tableEditorOptions) },
'Alt-Shift-Ctrl-Left': () => { this.tableEditor.moveColumn(-1, this.tableEditorOptions) },
'Alt-Shift-Cmd-Left': () => { this.tableEditor.moveColumn(-1, this.tableEditorOptions) },
'Alt-Shift-Ctrl-Right': () => { this.tableEditor.moveColumn(1, this.tableEditorOptions) },
'Alt-Shift-Cmd-Right': () => { this.tableEditor.moveColumn(1, this.tableEditorOptions) },
'Alt-Shift-Ctrl-Up': () => { this.tableEditor.moveRow(-1, this.tableEditorOptions) },
'Alt-Shift-Cmd-Up': () => { this.tableEditor.moveRow(-1, this.tableEditorOptions) },
'Alt-Shift-Ctrl-Down': () => { this.tableEditor.moveRow(1, this.tableEditorOptions) },
'Alt-Shift-Cmd-Down': () => { this.tableEditor.moveRow(1, this.tableEditorOptions) }
})
if (this.props.enableTableEditor) {
this.editor.on('cursorActivity', this.editorActivityHandler)
this.editor.on('changes', this.editorActivityHandler)
}
this.setState({
clientWidth: this.refs.root.clientWidth
})
} }
expandSnippet (line, cursor, cm, snippets) { expandSnippet (line, cursor, cm, snippets) {
@@ -369,6 +452,27 @@ export default class CodeEditor extends React.Component {
this.editor.setOption('scrollPastEnd', this.props.scrollPastEnd) this.editor.setOption('scrollPastEnd', this.props.scrollPastEnd)
} }
if (prevProps.enableTableEditor !== this.props.enableTableEditor) {
if (this.props.enableTableEditor) {
this.editor.on('cursorActivity', this.editorActivityHandler)
this.editor.on('changes', this.editorActivityHandler)
} else {
this.editor.off('cursorActivity', this.editorActivityHandler)
this.editor.off('changes', this.editorActivityHandler)
}
this.extraKeysMode = 'default'
this.editor.setOption('extraKeys', this.defaultKeyMap)
}
if (this.state.clientWidth !== this.refs.root.clientWidth) {
this.setState({
clientWidth: this.refs.root.clientWidth
})
needRefresh = true
}
if (needRefresh) { if (needRefresh) {
this.editor.refresh() this.editor.refresh()
} }
@@ -392,7 +496,13 @@ export default class CodeEditor extends React.Component {
moveCursorTo (row, col) {} moveCursorTo (row, col) {}
scrollToLine (num) {} scrollToLine (event, num) {
const cursor = {
line: num,
ch: 1
}
this.editor.setCursor(cursor)
}
focus () { focus () {
this.editor.focus() this.editor.focus()
@@ -455,7 +565,11 @@ export default class CodeEditor extends React.Component {
) )
return prevChar === '](' && nextChar === ')' return prevChar === '](' && nextChar === ')'
} }
if (dataTransferItem.type.match('image')) {
const pastedHtml = clipboardData.getData('text/html')
if (pastedHtml !== '') {
this.handlePasteHtml(e, editor, pastedHtml)
} else if (dataTransferItem.type.match('image')) {
attachmentManagement.handlePastImageEvent( attachmentManagement.handlePastImageEvent(
this, this,
storageKey, storageKey,
@@ -525,6 +639,12 @@ export default class CodeEditor extends React.Component {
}) })
} }
handlePasteHtml (e, editor, pastedHtml) {
e.preventDefault()
const markdown = this.turndownService.turndown(pastedHtml)
editor.replaceSelection(markdown)
}
mapNormalResponse (response, pastedTxt) { mapNormalResponse (response, pastedTxt) {
return this.decodeResponse(response).then(body => { return this.decodeResponse(response).then(body => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@@ -533,7 +653,10 @@ export default class CodeEditor extends React.Component {
body, body,
'text/html' 'text/html'
) )
const linkWithTitle = `[${parsedBody.title}](${pastedTxt})` const escapePipe = (str) => {
return str.replace('|', '\\|')
}
const linkWithTitle = `[${escapePipe(parsedBody.title)}](${pastedTxt})`
resolve(linkWithTitle) resolve(linkWithTitle)
} catch (e) { } catch (e) {
reject(e) reject(e)

View File

@@ -64,6 +64,10 @@ class MarkdownEditor extends React.Component {
}) })
} }
setValue (value) {
this.refs.code.setValue(value)
}
handleChange (e) { handleChange (e) {
this.value = this.refs.code.value this.value = this.refs.code.value
this.props.onChange(e) this.props.onChange(e)
@@ -250,7 +254,7 @@ class MarkdownEditor extends React.Component {
: 'codeEditor--hide' : 'codeEditor--hide'
} }
ref='code' ref='code'
mode='GitHub Flavored Markdown' mode='Boost Flavored Markdown'
value={value} value={value}
theme={config.editor.theme} theme={config.editor.theme}
keyMap={config.editor.keyMap} keyMap={config.editor.keyMap}
@@ -265,6 +269,7 @@ class MarkdownEditor extends React.Component {
storageKey={storageKey} storageKey={storageKey}
noteKey={noteKey} noteKey={noteKey}
fetchUrlTitle={config.editor.fetchUrlTitle} fetchUrlTitle={config.editor.fetchUrlTitle}
enableTableEditor={config.editor.enableTableEditor}
onChange={(e) => this.handleChange(e)} onChange={(e) => this.handleChange(e)}
onBlur={(e) => this.handleBlur(e)} onBlur={(e) => this.handleBlur(e)}
spellCheck spellCheck
@@ -300,6 +305,7 @@ class MarkdownEditor extends React.Component {
noteKey={noteKey} noteKey={noteKey}
customCSS={config.preview.customCSS} customCSS={config.preview.customCSS}
allowCustomCSS={config.preview.allowCustomCSS} allowCustomCSS={config.preview.allowCustomCSS}
lineThroughCheckbox={config.preview.lineThroughCheckbox}
/> />
</div> </div>
) )

View File

@@ -16,7 +16,6 @@
.preview .preview
display block display block
absolute top bottom left right absolute top bottom left right
z-index 100
background-color white background-color white
height 100% height 100%
width 100% width 100%

View File

@@ -17,8 +17,11 @@ import copy from 'copy-to-clipboard'
import mdurl from 'mdurl' import mdurl from 'mdurl'
import exportNote from 'browser/main/lib/dataApi/exportNote' import exportNote from 'browser/main/lib/dataApi/exportNote'
import { escapeHtmlCharacters } from 'browser/lib/utils' import { escapeHtmlCharacters } from 'browser/lib/utils'
import context from 'browser/lib/context'
import i18n from 'browser/lib/i18n'
import fs from 'fs'
const { remote } = require('electron') const { remote, shell } = require('electron')
const attachmentManagement = require('../main/lib/dataApi/attachmentManagement') const attachmentManagement = require('../main/lib/dataApi/attachmentManagement')
const { app } = remote const { app } = remote
@@ -27,6 +30,8 @@ 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()
@@ -75,7 +80,6 @@ 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');
} }
${allowCustomCSS ? customCSS : ''}
${markdownStyle} ${markdownStyle}
body { body {
@@ -83,6 +87,11 @@ body {
font-size: ${fontSize}px; font-size: ${fontSize}px;
${scrollPastEnd && 'padding-bottom: 90vh;'} ${scrollPastEnd && 'padding-bottom: 90vh;'}
} }
@media print {
body {
padding-bottom: initial;
}
}
code { code {
font-family: '${codeBlockFontFamily.join("','")}'; font-family: '${codeBlockFontFamily.join("','")}';
background-color: rgba(0,0,0,0.04); background-color: rgba(0,0,0,0.04);
@@ -139,6 +148,8 @@ body p {
display: none display: none
} }
} }
${allowCustomCSS ? customCSS : ''}
` `
} }
@@ -161,7 +172,6 @@ const scrollBarDarkStyle = `
} }
` `
const { shell } = require('electron')
const OSX = global.process.platform === 'darwin' const OSX = global.process.platform === 'darwin'
const defaultFontFamily = ['helvetica', 'arial', 'sans-serif'] const defaultFontFamily = ['helvetica', 'arial', 'sans-serif']
@@ -219,8 +229,32 @@ export default class MarkdownPreview extends React.Component {
} }
} }
handleContextMenu (e) { handleContextMenu (event) {
this.props.onContextMenu(e) // If a contextMenu handler was passed to us, use it instead of the self-defined one -> return
if (_.isFunction(this.props.onContextMenu)) {
this.props.onContextMenu(event)
return
}
// No contextMenu was passed to us -> execute our own link-opener
if (event.target.tagName.toLowerCase() === 'a') {
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)
}
}
}
} }
handleDoubleClick (e) { handleDoubleClick (e) {
@@ -397,6 +431,7 @@ export default class MarkdownPreview extends React.Component {
case 'dark': case 'dark':
case 'solarized-dark': case 'solarized-dark':
case 'monokai': case 'monokai':
case 'dracula':
return scrollBarDarkStyle return scrollBarDarkStyle
default: default:
return scrollBarStyle return scrollBarStyle
@@ -498,7 +533,8 @@ export default class MarkdownPreview extends React.Component {
prevProps.smartQuotes !== this.props.smartQuotes || prevProps.smartQuotes !== this.props.smartQuotes ||
prevProps.sanitize !== this.props.sanitize || prevProps.sanitize !== this.props.sanitize ||
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
) { ) {
this.initMarkdown() this.initMarkdown()
this.rewriteIframe() this.rewriteIframe()
@@ -827,6 +863,15 @@ export default class MarkdownPreview extends React.Component {
return return
} }
const regexIsLine = /^:line:[0-9]/
if (regexIsLine.test(linkHash)) {
const numberPattern = /\d+/g
const lineNumber = parseInt(linkHash.match(numberPattern)[0])
eventEmitter.emit('line:jump', lineNumber)
return
}
// this will match the old link format storage.key-note.key // this will match the old link format storage.key-note.key
// e.g. // e.g.
// 877f99c3268608328037-1c211eb7dcb463de6490 // 877f99c3268608328037-1c211eb7dcb463de6490

View File

@@ -20,12 +20,18 @@ class MarkdownSplitEditor extends React.Component {
} }
} }
setValue (value) {
this.refs.code.setValue(value)
}
handleOnChange () { handleOnChange () {
this.value = this.refs.code.value this.value = this.refs.code.value
this.props.onChange() this.props.onChange()
} }
handleScroll (e) { handleScroll (e) {
if (!this.props.config.preview.scrollSync) return
const previewDoc = _.get(this, 'refs.preview.refs.root.contentWindow.document') const previewDoc = _.get(this, 'refs.preview.refs.root.contentWindow.document')
const codeDoc = _.get(this, 'refs.code.editor.doc') const codeDoc = _.get(this, 'refs.code.editor.doc')
let srcTop, srcHeight, targetTop, targetHeight let srcTop, srcHeight, targetTop, targetHeight
@@ -145,7 +151,7 @@ class MarkdownSplitEditor extends React.Component {
styleName='codeEditor' styleName='codeEditor'
ref='code' ref='code'
width={this.state.codeEditorWidthInPercent + '%'} width={this.state.codeEditorWidthInPercent + '%'}
mode='GitHub Flavored Markdown' mode='Boost Flavored Markdown'
value={value} value={value}
theme={config.editor.theme} theme={config.editor.theme}
keyMap={config.editor.keyMap} keyMap={config.editor.keyMap}
@@ -158,6 +164,7 @@ class MarkdownSplitEditor extends React.Component {
rulers={config.editor.rulers} rulers={config.editor.rulers}
scrollPastEnd={config.editor.scrollPastEnd} scrollPastEnd={config.editor.scrollPastEnd}
fetchUrlTitle={config.editor.fetchUrlTitle} fetchUrlTitle={config.editor.fetchUrlTitle}
enableTableEditor={config.editor.enableTableEditor}
storageKey={storageKey} storageKey={storageKey}
noteKey={noteKey} noteKey={noteKey}
onChange={this.handleOnChange.bind(this)} onChange={this.handleOnChange.bind(this)}
@@ -192,6 +199,7 @@ class MarkdownSplitEditor extends React.Component {
noteKey={noteKey} noteKey={noteKey}
customCSS={config.preview.customCSS} customCSS={config.preview.customCSS}
allowCustomCSS={config.preview.allowCustomCSS} allowCustomCSS={config.preview.allowCustomCSS}
lineThroughCheckbox={config.preview.lineThroughCheckbox}
/> />
</div> </div>
) )

View File

@@ -74,24 +74,22 @@ const NoteItem = ({
? note.title ? note.title
: <span styleName='item-title-empty'>{i18n.__('Empty note')}</span>} : <span styleName='item-title-empty'>{i18n.__('Empty note')}</span>}
</div> </div>
{['ALL', 'STORAGE'].includes(viewType) && <div styleName='item-middle'>
<div styleName='item-middle'> <div styleName='item-middle-time'>{dateDisplay}</div>
<div styleName='item-middle-time'>{dateDisplay}</div> <div styleName='item-middle-app-meta'>
<div styleName='item-middle-app-meta'> <div
<div title={
title={ viewType === 'ALL'
viewType === 'ALL' ? storageName
? storageName : viewType === 'STORAGE' ? folderName : null
: viewType === 'STORAGE' ? folderName : null }
} styleName='item-middle-app-meta-label'
styleName='item-middle-app-meta-label' >
> {viewType === 'ALL' && storageName}
{viewType === 'ALL' && storageName} {viewType === 'STORAGE' && folderName}
{viewType === 'STORAGE' && folderName}
</div>
</div> </div>
</div>} </div>
</div>
<div styleName='item-bottom'> <div styleName='item-bottom'>
<div styleName='item-bottom-tagList'> <div styleName='item-bottom-tagList'>
{note.tags.length > 0 {note.tags.length > 0

View File

@@ -368,13 +368,13 @@ body[data-theme="monokai"]
.item-title .item-title
.item-title-icon .item-title-icon
.item-bottom-time .item-bottom-time
color $ui-monokai-text-color color $ui-monokai-active-color
.item-bottom-tagList-item .item-bottom-tagList-item
background-color alpha(white, 10%) background-color alpha(white, 10%)
color $ui-monokai-text-color color $ui-monokai-text-color
&:hover &:hover
// background-color alpha($ui-monokai-button--active-backgroundColor, 60%) // background-color alpha($ui-monokai-button--active-backgroundColor, 60%)
color #c0392b color #f92672
.item-bottom-tagList-item .item-bottom-tagList-item
background-color alpha(#fff, 20%) background-color alpha(#fff, 20%)
@@ -394,3 +394,76 @@ body[data-theme="monokai"]
.item-bottom-tagList-empty .item-bottom-tagList-empty
color $ui-inactive-text-color color $ui-inactive-text-color
vertical-align middle vertical-align middle
body[data-theme="dracula"]
.root
border-color $ui-dracula-borderColor
background-color $ui-dracula-noteList-backgroundColor
.item
border-color $ui-dracula-borderColor
background-color $ui-dracula-noteList-backgroundColor
&:hover
transition 0.15s
// background-color alpha($ui-dracula-noteList-backgroundColor, 20%)
color $ui-dracula-text-color
.item-title
.item-title-icon
.item-bottom-time
transition 0.15s
color $ui-dracula-text-color
.item-bottom-tagList-item
transition 0.15s
background-color alpha($ui-dracula-noteList-backgroundColor, 20%)
color $ui-dracula-text-color
&:active
transition 0.15s
background-color $ui-dracula-noteList-backgroundColor
color $ui-dracula-text-color
.item-title
.item-title-icon
.item-bottom-time
transition 0.15s
color $ui-dracula-text-color
.item-bottom-tagList-item
transition 0.15s
background-color alpha($ui-dracula-noteList-backgroundColor, 10%)
color $ui-dracula-text-color
.item-wrapper
border-color alpha($ui-dracula-button-backgroundColor, 60%)
.item--active
border-color $ui-dracula-borderColor
background-color $ui-dracula-button-backgroundColor
.item-wrapper
border-color transparent
.item-title
.item-title-icon
.item-bottom-time
color $ui-dracula-active-color
.item-bottom-tagList-item
background-color alpha(#f8f8f2, 10%)
color $ui-dracula-text-color
&:hover
// background-color alpha($ui-dracula-button--active-backgroundColor, 60%)
color #ff79c6
.item-bottom-tagList-item
background-color alpha(#f8f8f2, 20%)
.item-title
color $ui-inactive-text-color
.item-title-icon
color $ui-inactive-text-color
.item-title-empty
color $ui-inactive-text-color
.item-bottom-tagList-item
background-color alpha($ui-dark-button--active-backgroundColor, 40%)
color $ui-inactive-text-color
.item-bottom-tagList-empty
color $ui-inactive-text-color
vertical-align middle

View File

@@ -240,7 +240,7 @@ body[data-theme="monokai"]
.item-simple-title-icon .item-simple-title-icon
.item-simple-bottom-time .item-simple-bottom-time
transition 0.15s transition 0.15s
color $ui-solarized-dark-text-color color $ui-monokai-text-color
.item-simple-bottom-tagList-item .item-simple-bottom-tagList-item
transition 0.15s transition 0.15s
background-color alpha(#fff, 20%) background-color alpha(#fff, 20%)
@@ -286,3 +286,67 @@ body[data-theme="monokai"]
.item-simple-right-storageName .item-simple-right-storageName
padding-left 4px padding-left 4px
opacity 0.4 opacity 0.4
body[data-theme="dracula"]
.root
border-color $ui-dracula-borderColor
background-color $ui-dracula-noteList-backgroundColor
.item-simple
border-color $ui-dracula-borderColor
background-color $ui-dracula-noteList-backgroundColor
&:hover
transition 0.15s
background-color alpha($ui-dracula-button-backgroundColor, 60%)
color $ui-dracula-text-color
.item-simple-title
.item-simple-title-empty
.item-simple-title-icon
.item-simple-bottom-time
transition 0.15s
color $ui-dracula-text-color
.item-simple-bottom-tagList-item
transition 0.15s
background-color alpha(#f8f8f2, 20%)
color $ui-dracula-text-color
&:active
transition 0.15s
background-color $ui-dracula-button--active-backgroundColor
color $ui-dracula-text-color
.item-simple-title
.item-simple-title-empty
.item-simple-title-icon
.item-simple-bottom-time
transition 0.15s
color $ui-dracula-text-color
.item-simple-bottom-tagList-item
transition 0.15s
background-color alpha(#f8f8f2, 10%)
color $ui-dracula-text-color
.item-simple--active
border-color $ui-dracula-borderColor
background-color $ui-dracula-button--active-backgroundColor
.item-simple-wrapper
border-color transparent
.item-simple-title
.item-simple-title-empty
.item-simple-title-icon
.item-simple-bottom-time
color $ui-dracula-text-color
.item-simple-bottom-tagList-item
background-color alpha(#f8f8f2, 10%)
color $ui-dracula-text-color
&:hover
// background-color alpha($ui-dark-button--active-backgroundColor, 60%)
color #c0392b
.item-simple-bottom-tagList-item
background-color alpha(#f8f8f2, 20%)
.item-simple-title
color $ui-dark-text-color
border-bottom $ui-dark-borderColor
.item-simple-right
float right
.item-simple-right-storageName
padding-left 4px
opacity 0.4

View File

@@ -51,4 +51,15 @@ body[data-theme="monokai"]
border none border none
background-color $ui-monokai-button-backgroundColor background-color $ui-monokai-button-backgroundColor
&:hover &:hover
color #5CB85C color #5CB85C
body[data-theme="dracula"]
.notification-area
background-color none
.notification-link
color $ui-dracula-text-color
border none
background-color $ui-dracula-button-backgroundColor
&:hover
color #ff79c6

View File

@@ -263,4 +263,46 @@ body[data-theme="monokai"]
background-color $ui-monokai-button-backgroundColor background-color $ui-monokai-button-backgroundColor
color $ui-monokai-text-color color $ui-monokai-text-color
.menu-button-label .menu-button-label
color $ui-monokai-text-color color $ui-monokai-text-color
body[data-theme="dracula"]
.menu-button
&:active
background-color $ui-dracula-noteList-backgroundColor
color $ui-dracula-text-color
&:hover
background-color $ui-dracula-button-backgroundColor
color $ui-dracula-text-color
.menu-button--active
color $ui-dracula-text-color
background-color $ui-dracula-button-backgroundColor
.menu-button-label
color $ui-dracula-text-color
&:hover
background-color $ui-dracula-button-backgroundColor
color $ui-dracula-text-color
.menu-button-label
color $ui-dracula-text-color
.menu-button-star--active
color $ui-dracula-text-color
background-color $ui-dracula-button-backgroundColor
.menu-button-label
color $ui-dracula-text-color
&:hover
background-color $ui-dracula-button-backgroundColor
color $ui-dracula-text-color
.menu-button-label
color $ui-dracula-text-color
.menu-button-trash--active
color $ui-dracula-text-color
background-color $ui-dracula-button-backgroundColor
.menu-button-label
color $ui-dracula-text-color
&:hover
background-color $ui-dracula-button-backgroundColor
color $ui-dracula-text-color
.menu-button-label
color $ui-dracula-text-color

View File

@@ -180,4 +180,48 @@ body[data-theme="monokai"]
color $ui-monokai-text-color color $ui-monokai-text-color
.deleteButton .deleteButton
color alpha($ui-monokai-text-color, 30%) color alpha($ui-monokai-text-color, 30%)
body[data-theme="dracula"]
.root
color $ui-dracula-text-color
border-color $ui-dark-borderColor
&:hover
background-color $ui-dracula-noteDetail-backgroundColor
.deleteButton
color $ui-dracula-text-color
&:hover
background-color darken($ui-dracula-noteDetail-backgroundColor, 15%)
&:active
color $ui-dracula-text-color
background-color $ui-dark-button--active-backgroundColor
.root--active
color $ui-dracula-text-color
border-color $ui-dracula-borderColor
&:hover
background-color $ui-dracula-noteDetail-backgroundColor
.deleteButton
color $ui-dracula-text-color
&:hover
background-color darken($ui-dracula-noteDetail-backgroundColor, 15%)
&:active
color $ui-dracula-text-color
background-color $ui-dark-button--active-backgroundColor
.button
border none
color $ui-dracula-text-color
background-color transparent
transition color background-color 0.15s
border-left 4px solid transparent
&:hover
color $ui-dracula-text-color
background-color $ui-dracula-noteDetail-backgroundColor
.input
background-color $ui-dracula-noteDetail-backgroundColor
color $ui-dracula-text-color
.deleteButton
color alpha($ui-dracula-text-color, 30%)

View File

@@ -156,4 +156,23 @@ body[data-theme="monokai"]
background-color $ui-monokai-button-backgroundColor background-color $ui-monokai-button-backgroundColor
&:hover &:hover
color $ui-monokai-text-color color $ui-monokai-text-color
background-color $ui-monokai-button-backgroundColor background-color $ui-monokai-button-backgroundColor
body[data-theme="dracula"]
.folderList-item
&:hover
background-color $ui-dracula-button-backgroundColor
color $ui-dracula-text-color
&:active
color $ui-dracula-text-color
background-color $ui-dracula-button-backgroundColor
.folderList-item--active
@extend .folderList-item
color $ui-dracula-text-color
background-color $ui-dracula-button-backgroundColor
&:active
background-color $ui-dracula-button-backgroundColor
&:hover
color $ui-dracula-text-color
background-color $ui-dracula-button-backgroundColor

View File

@@ -14,8 +14,8 @@ import CSSModules from 'browser/lib/CSSModules'
* @param {bool} isRelated * @param {bool} isRelated
*/ */
const TagListItem = ({name, handleClickTagListItem, handleClickNarrowToTag, isActive, isRelated, count}) => ( const TagListItem = ({name, handleClickTagListItem, handleClickNarrowToTag, handleContextMenu, isActive, isRelated, count}) => (
<div styleName='tagList-itemContainer'> <div styleName='tagList-itemContainer' onContextMenu={e => handleContextMenu(e, name)}>
{isRelated {isRelated
? <button styleName={isActive ? 'tagList-itemNarrow-active' : 'tagList-itemNarrow'} onClick={() => handleClickNarrowToTag(name)}> ? <button styleName={isActive ? 'tagList-itemNarrow-active' : 'tagList-itemNarrow'} onClick={() => handleClickNarrowToTag(name)}>
<i className={isActive ? 'fa fa-minus-circle' : 'fa fa-plus-circle'} /> <i className={isActive ? 'fa fa-minus-circle' : 'fa fa-plus-circle'} />

View File

@@ -12,7 +12,7 @@ import styles from './TodoListPercentage.styl'
*/ */
const TodoListPercentage = ({ const TodoListPercentage = ({
percentageOfTodo percentageOfTodo, onClearCheckboxClick
}) => ( }) => (
<div styleName='percentageBar' style={{display: isNaN(percentageOfTodo) ? 'none' : ''}}> <div styleName='percentageBar' style={{display: isNaN(percentageOfTodo) ? 'none' : ''}}>
<div styleName='progressBar' style={{width: `${percentageOfTodo}%`}}> <div styleName='progressBar' style={{width: `${percentageOfTodo}%`}}>
@@ -20,11 +20,15 @@ const TodoListPercentage = ({
<p styleName='percentageText'>{percentageOfTodo}%</p> <p styleName='percentageText'>{percentageOfTodo}%</p>
</div> </div>
</div> </div>
<div styleName='todoClear'>
<p styleName='todoClearText' onClick={(e) => onClearCheckboxClick(e)}>clear</p>
</div>
</div> </div>
) )
TodoListPercentage.propTypes = { TodoListPercentage.propTypes = {
percentageOfTodo: PropTypes.number.isRequired percentageOfTodo: PropTypes.number.isRequired,
onClearCheckboxClick: PropTypes.func.isRequired
} }
export default CSSModules(TodoListPercentage, styles) export default CSSModules(TodoListPercentage, styles)

View File

@@ -1,4 +1,5 @@
.percentageBar .percentageBar
display: flex
position absolute position absolute
top 72px top 72px
right 0px right 0px
@@ -30,6 +31,20 @@
color #f4f4f4 color #f4f4f4
font-weight 600 font-weight 600
.todoClear
display flex
justify-content: flex-end
position absolute
z-index 120
width 100%
height 100%
padding 2px 10px
.todoClearText
color #f4f4f4
cursor pointer
font-weight 500
body[data-theme="dark"] body[data-theme="dark"]
.percentageBar .percentageBar
background-color #444444 background-color #444444
@@ -39,7 +54,10 @@ body[data-theme="dark"]
.percentageText .percentageText
color $ui-dark-text-color color $ui-dark-text-color
.todoClearText
color $ui-dark-text-color
body[data-theme="solarized-dark"] body[data-theme="solarized-dark"]
.percentageBar .percentageBar
background-color #002b36 background-color #002b36
@@ -50,12 +68,28 @@ body[data-theme="solarized-dark"]
.percentageText .percentageText
color #fdf6e3 color #fdf6e3
.todoClearText
color #fdf6e3
body[data-theme="monokai"] body[data-theme="monokai"]
.percentageBar .percentageBar
background-color #f92672 background-color: $ui-monokai-borderColor
.progressBar .progressBar
background-color: #373831 background-color $ui-monokai-active-color
.percentageText .percentageText
color #fdf6e3 color $ui-monokai-text-color
body[data-theme="dracula"]
.percentageBar
background-color $ui-dracula-borderColor
.progressBar
background-color: $ui-dracula-active-color
.percentageText
color $ui-dracula-text-color
.percentageText
color $ui-dracula-text-color

View File

@@ -80,6 +80,9 @@ li
&.checked &.checked
text-decoration line-through text-decoration line-through
opacity 0.5 opacity 0.5
&.taskListItem.checked
text-decoration line-through
opacity 0.5
div.math-rendered div.math-rendered
text-align center text-align center
.math-failed .math-failed
@@ -361,7 +364,7 @@ for name, val in admonition_types
.admonition.{name} .admonition.{name}
@extend $admonition @extend $admonition
border-left-color: val[color] border-left-color: val[color]
.admonition.{name}>.admonition-title .admonition.{name}>.admonition-title
@extend $admonition-title @extend $admonition-title
border-bottom-color: .1rem solid rgba(val[color], 0.2) border-bottom-color: .1rem solid rgba(val[color], 0.2)
@@ -476,5 +479,34 @@ body[data-theme="monokai"]
border-color themeMonokaiTableBorder border-color themeMonokaiTableBorder
&:last-child &:last-child
border-right solid 1px themeMonokaiTableBorder border-right solid 1px themeMonokaiTableBorder
kbd
background-color themeDarkBackground
themeDraculaTableOdd = $ui-dracula-noteDetail-backgroundColor
themeDraculaTableEven = darken($ui-dracula-noteDetail-backgroundColor, 10%)
themeDraculaTableHead = themeDraculaTableEven
themeDraculaTableBorder = themeDarkBorder
body[data-theme="dracula"]
color $ui-dracula-text-color
border-color themeDarkBorder
background-color $ui-dracula-noteDetail-backgroundColor
table
thead
tr
background-color themeDraculaTableHead
th
border-color themeDraculaTableBorder
&:last-child
border-right solid 1px themeDraculaTableBorder
tbody
tr:nth-child(2n + 1)
background-color themeDraculaTableOdd
tr:nth-child(2n)
background-color themeDraculaTableEven
td
border-color themeDraculaTableBorder
&:last-child
border-right solid 1px themeDraculaTableBorder
kbd kbd
background-color themeDarkBackground background-color themeDarkBackground

View File

@@ -2,8 +2,8 @@ import mermaidAPI from 'mermaid'
// fixes bad styling in the mermaid dark theme // fixes bad styling in the mermaid dark theme
const darkThemeStyling = ` const darkThemeStyling = `
.loopText tspan { .loopText tspan {
fill: white; fill: white;
}` }`
function getRandomInt (min, max) { function getRandomInt (min, max) {
@@ -21,7 +21,7 @@ function getId () {
function render (element, content, theme) { function render (element, content, theme) {
try { try {
let isDarkTheme = theme === 'dark' || theme === 'solarized-dark' || theme === 'monokai' let 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 : ''

View File

@@ -49,7 +49,7 @@ const languages = [
}, },
{ {
name: 'Portuguese', name: 'Portuguese',
locale: 'pt' locale: 'pt-BR'
}, },
{ {
name: 'Russian', name: 'Russian',

View File

@@ -1,53 +1,113 @@
import { Point } from '@susisu/mte-kernel' import { Point } from '@susisu/mte-kernel'
export default class TextEditorInterface { export default class TextEditorInterface {
constructor (editor) { constructor (editor) {
this.editor = editor this.editor = editor
} this.doc = editor.getDoc()
this.transaction = false
getCursorPosition () { }
const pos = this.editor.getCursor()
return new Point(pos.line, pos.ch) getCursorPosition () {
} const { line, ch } = this.doc.getCursor()
return new Point(line, ch)
setCursorPosition (pos) { }
this.editor.setCursor({line: pos.row, ch: pos.column})
} setCursorPosition (pos) {
this.doc.setCursor({
setSelectionRange (range) { line: pos.row,
this.editor.setSelection({ ch: pos.column
anchor: {line: range.start.row, ch: range.start.column}, })
head: {line: range.end.row, ch: range.end.column} }
})
} setSelectionRange (range) {
this.doc.setSelection(
getLastRow () { { line: range.start.row, ch: range.start.column },
return this.editor.lastLine() { line: range.end.row, ch: range.end.column }
} )
}
acceptsTableEdit (row) {
return true getLastRow () {
} return this.doc.lineCount() - 1
}
getLine (row) {
return this.editor.getLine(row) acceptsTableEdit () {
} return true
}
insertLine (row, line) {
this.editor.replaceRange(line, {line: row, ch: 0}) getLine (row) {
} return this.doc.getLine(row)
}
deleteLine (row) {
this.editor.replaceRange('', {line: row, ch: 0}, {line: row, ch: this.editor.getLine(row).length}) insertLine (row, line) {
} const lastRow = this.getLastRow()
if (row > lastRow) {
replaceLines (startRow, endRow, lines) { const lastLine = this.getLine(lastRow)
endRow-- // because endRow is a first line after a table. this.doc.replaceRange(
const endRowCh = this.editor.getLine(endRow).length '\n' + line,
this.editor.replaceRange(lines, {line: startRow, ch: 0}, {line: endRow, ch: endRowCh}) { line: lastRow, ch: lastLine.length },
} { line: lastRow, ch: lastLine.length }
)
transact (func) { } else {
func() this.doc.replaceRange(
} line + '\n',
} { line: row, ch: 0 },
{ line: row, ch: 0 }
)
}
}
deleteLine (row) {
const lastRow = this.getLastRow()
if (row >= lastRow) {
if (lastRow > 0) {
const preLastLine = this.getLine(lastRow - 1)
const lastLine = this.getLine(lastRow)
this.doc.replaceRange(
'',
{ line: lastRow - 1, ch: preLastLine.length },
{ line: lastRow, ch: lastLine.length }
)
} else {
const lastLine = this.getLine(lastRow)
this.doc.replaceRange(
'',
{ line: lastRow, ch: 0 },
{ line: lastRow, ch: lastLine.length }
)
}
} else {
this.doc.replaceRange(
'',
{ line: row, ch: 0 },
{ line: row + 1, ch: 0 }
)
}
}
replaceLines (startRow, endRow, lines) {
const lastRow = this.getLastRow()
if (endRow > lastRow) {
const lastLine = this.getLine(lastRow)
this.doc.replaceRange(
lines.join('\n'),
{ line: startRow, ch: 0 },
{ line: lastRow, ch: lastLine.length }
)
} else {
this.doc.replaceRange(
lines.join('\n') + '\n',
{ line: startRow, ch: 0 },
{ line: endRow, ch: 0 }
)
}
}
transact (func) {
this.transaction = true
func()
this.transaction = false
if (this.onDidFinishTransaction) {
this.onDidFinishTransaction.call(undefined)
}
}
}

View File

@@ -1,19 +1,37 @@
export function findNoteTitle (value) { export function findNoteTitle (value, enableFrontMatterTitle, frontMatterTitleField = 'title') {
const splitted = value.split('\n') const splitted = value.split('\n')
let title = null let title = null
let isInsideCodeBlock = false let isInsideCodeBlock = false
splitted.some((line, index) => { if (splitted[0] === '---') {
const trimmedLine = line.trim() let line = 0
const trimmedNextLine = splitted[index + 1] === undefined ? '' : splitted[index + 1].trim() while (++line < splitted.length) {
if (trimmedLine.match('```')) { if (enableFrontMatterTitle && splitted[line].startsWith(frontMatterTitleField + ':')) {
isInsideCodeBlock = !isInsideCodeBlock title = splitted[line].substring(frontMatterTitleField.length + 1).trim()
break
}
if (splitted[line] === '---') {
splitted.splice(0, line + 1)
break
}
} }
if (isInsideCodeBlock === false && (trimmedLine.match(/^# +/) || trimmedNextLine.match(/^=+$/))) { }
title = trimmedLine
return true if (title === null) {
} splitted.some((line, index) => {
}) const trimmedLine = line.trim()
const trimmedNextLine = splitted[index + 1] === undefined ? '' : splitted[index + 1].trim()
if (trimmedLine.match('```')) {
isInsideCodeBlock = !isInsideCodeBlock
}
if (isInsideCodeBlock === false && (trimmedLine.match(/^# +/) || trimmedNextLine.match(/^=+$/))) {
title = trimmedLine
return true
}
})
}
if (title === null) { if (title === null) {
title = '' title = ''

View File

@@ -0,0 +1,24 @@
'use strict'
module.exports = function frontMatterPlugin (md) {
function frontmatter (state, startLine, endLine, silent) {
if (startLine !== 0 || state.src.substr(startLine, state.eMarks[0]) !== '---') {
return false
}
let line = 0
while (++line < state.lineMax) {
if (state.src.substring(state.bMarks[line], state.eMarks[line]) === '---') {
state.line = line + 1
return true
}
}
return false
}
md.block.ruler.before('table', 'frontmatter', frontmatter, {
alt: [ 'paragraph', 'reference', 'blockquote', 'list' ]
})
}

View File

@@ -0,0 +1,100 @@
/**
* @fileoverview Markdown table of contents generator
*/
import toc from 'markdown-toc'
import diacritics from 'diacritics-map'
import stripColor from 'strip-color'
const EOL = require('os').EOL
/**
* @caseSensitiveSlugify Custom slugify function
* Same implementation that the original used by markdown-toc (node_modules/markdown-toc/lib/utils.js),
* but keeps original case to properly handle https://github.com/BoostIO/Boostnote/issues/2067
*/
function caseSensitiveSlugify (str) {
function replaceDiacritics (str) {
return str.replace(/[À-ž]/g, function (ch) {
return diacritics[ch] || ch
})
}
function getTitle (str) {
if (/^\[[^\]]+\]\(/.test(str)) {
var m = /^\[([^\]]+)\]/.exec(str)
if (m) return m[1]
}
return str
}
str = getTitle(str)
str = stripColor(str)
// str = str.toLowerCase() //let's be case sensitive
// `.split()` is often (but not always) faster than `.replace()`
str = str.split(' ').join('-')
str = str.split(/\t/).join('--')
str = str.split(/<\/?[^>]+>/).join('')
str = str.split(/[|$&`~=\\\/@+*!?({[\]})<>=.,;:'"^]/).join('')
str = str.split(/[。?!,、;:“”【】()〔〕[]﹃﹄“ ”‘’﹁﹂—…-~《》〈〉「」]/).join('')
str = replaceDiacritics(str)
return str
}
const TOC_MARKER_START = '<!-- toc -->'
const TOC_MARKER_END = '<!-- tocstop -->'
/**
* Takes care of proper updating given editor with TOC.
* If TOC doesn't exit in the editor, it's inserted at current caret position.
* Otherwise,TOC is updated in place.
* @param editor CodeMirror editor to be updated with TOC
*/
export function generateInEditor (editor) {
const tocRegex = new RegExp(`${TOC_MARKER_START}[\\s\\S]*?${TOC_MARKER_END}`)
function tocExistsInEditor () {
return tocRegex.test(editor.getValue())
}
function updateExistingToc () {
const toc = generate(editor.getValue())
const search = editor.getSearchCursor(tocRegex)
while (search.findNext()) {
search.replace(toc)
}
}
function addTocAtCursorPosition () {
const toc = generate(editor.getRange(editor.getCursor(), {line: Infinity}))
editor.replaceRange(wrapTocWithEol(toc, editor), editor.getCursor())
}
if (tocExistsInEditor()) {
updateExistingToc()
} else {
addTocAtCursorPosition()
}
}
/**
* Generates MD TOC based on MD document passed as string.
* @param markdownText MD document
* @returns generatedTOC String containing generated TOC
*/
export function generate (markdownText) {
const generatedToc = toc(markdownText, {slugify: caseSensitiveSlugify})
return TOC_MARKER_START + EOL + EOL + generatedToc.content + EOL + EOL + TOC_MARKER_END
}
function wrapTocWithEol (toc, editor) {
const leftWrap = editor.getCursor().ch === 0 ? '' : EOL
const rightWrap = editor.getLine(editor.getCursor().line).length === editor.getCursor().ch ? '' : EOL
return leftWrap + toc + rightWrap
}
export default {
generate,
generateInEditor
}

View File

@@ -7,6 +7,7 @@ import _ from 'lodash'
import ConfigManager from 'browser/main/lib/ConfigManager' import ConfigManager from 'browser/main/lib/ConfigManager'
import katex from 'katex' import katex from 'katex'
import { lastFindInArray } from './utils' import { lastFindInArray } from './utils'
import ee from 'browser/main/lib/eventEmitter'
function createGutter (str, firstLineNumber) { function createGutter (str, firstLineNumber) {
if (Number.isNaN(firstLineNumber)) firstLineNumber = 1 if (Number.isNaN(firstLineNumber)) firstLineNumber = 1
@@ -148,7 +149,9 @@ class Markdown {
} }
}) })
this.md.use(require('markdown-it-kbd')) this.md.use(require('markdown-it-kbd'))
this.md.use(require('markdown-it-admonition'))
this.md.use(require('markdown-it-admonition'), {types: ['note', 'hint', 'attention', 'caution', 'danger', 'error']})
this.md.use(require('./markdown-it-frontmatter'))
const deflate = require('markdown-it-plantuml/lib/deflate') const deflate = require('markdown-it-plantuml/lib/deflate')
this.md.use(require('markdown-it-plantuml'), '', { this.md.use(require('markdown-it-plantuml'), '', {
@@ -221,7 +224,11 @@ class Markdown {
if (!liToken.attrs) { if (!liToken.attrs) {
liToken.attrs = [] liToken.attrs = []
} }
liToken.attrs.push(['class', 'taskListItem']) if (config.preview.lineThroughCheckbox) {
liToken.attrs.push(['class', `taskListItem${match[1] !== ' ' ? ' checked' : ''}`])
} else {
liToken.attrs.push(['class', 'taskListItem'])
}
} }
content = `<label class='taskListItem${match[1] !== ' ' ? ' checked' : ''}' for='checkbox-${startLine + 1}'><input type='checkbox'${match[1] !== ' ' ? ' checked' : ''} id='checkbox-${startLine + 1}'/> ${content.substring(4, content.length)}</label>` content = `<label class='taskListItem${match[1] !== ' ' ? ' checked' : ''}' for='checkbox-${startLine + 1}'><input type='checkbox'${match[1] !== ' ' ? ' checked' : ''} id='checkbox-${startLine + 1}'/> ${content.substring(4, content.length)}</label>`
} }

62
browser/lib/newNote.js Normal file
View File

@@ -0,0 +1,62 @@
import { hashHistory } from 'react-router'
import dataApi from 'browser/main/lib/dataApi'
import ee from 'browser/main/lib/eventEmitter'
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
export function createMarkdownNote (storage, folder, dispatch, location) {
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_MARKDOWN')
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_ALLNOTE')
return dataApi
.createNote(storage, {
type: 'MARKDOWN_NOTE',
folder: folder,
title: '',
content: ''
})
.then(note => {
const noteHash = note.key
dispatch({
type: 'UPDATE_NOTE',
note: note
})
hashHistory.push({
pathname: location.pathname,
query: { key: noteHash }
})
ee.emit('list:jump', noteHash)
ee.emit('detail:focus')
})
}
export function createSnippetNote (storage, folder, dispatch, location, config) {
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_SNIPPET')
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_ALLNOTE')
return dataApi
.createNote(storage, {
type: 'SNIPPET_NOTE',
folder: folder,
title: '',
description: '',
snippets: [
{
name: '',
mode: config.editor.snippetDefaultLanguage || 'text',
content: ''
}
]
})
.then(note => {
const noteHash = note.key
dispatch({
type: 'UPDATE_NOTE',
note: note
})
hashHistory.push({
pathname: location.pathname,
query: { key: noteHash }
})
ee.emit('list:jump', noteHash)
ee.emit('detail:focus')
})
}

View File

@@ -23,7 +23,7 @@ body[data-theme="dark"]
border-left 1px solid $ui-dark-borderColor border-left 1px solid $ui-dark-borderColor
.empty-message .empty-message
color $ui-dark-inactive-text-color color $ui-dark-inactive-text-color
body[data-theme="solarized-dark"] body[data-theme="solarized-dark"]
.root .root
background-color $ui-solarized-dark-noteDetail-backgroundColor background-color $ui-solarized-dark-noteDetail-backgroundColor
@@ -37,3 +37,10 @@ body[data-theme="monokai"]
border-left 1px solid $ui-monokai-borderColor border-left 1px solid $ui-monokai-borderColor
.empty-message .empty-message
color $ui-monokai-text-color color $ui-monokai-text-color
body[data-theme="dracula"]
.root
background-color $ui-dracula-noteDetail-backgroundColor
border-left 1px solid $ui-dracula-borderColor
.empty-message
color $ui-dracula-text-color

View File

@@ -36,7 +36,7 @@
height 34px height 34px
width 20px width 20px
line-height 34px line-height 34px
.search-input .search-input
vertical-align middle vertical-align middle
position relative position relative
@@ -71,7 +71,7 @@
overflow ellipsis overflow ellipsis
cursor pointer cursor pointer
&:hover &:hover
background-color $ui-button--hover-backgroundColor background-color $ui-button--hover-backgroundColor
.search-optionList-item--active .search-optionList-item--active
@extend .search-optionList-item @extend .search-optionList-item
@@ -159,3 +159,29 @@ body[data-theme="monokai"]
color $ui-monokai-button--active-color color $ui-monokai-button--active-color
.search-optionList-item-name-surfix .search-optionList-item-name-surfix
color $ui-monokai-inactive-text-color color $ui-monokai-inactive-text-color
body[data-theme="dracula"]
.root
color $ui-dracula-text-color
&:hover
color #f8f8f2
background-color $ui-dark-button--hover-backgroundColor
border-color $ui-dracula-borderColor
.search-optionList
color #f8f8f2
border-color $ui-dracula-borderColor
background-color $ui-dracula-button-backgroundColor
.search-optionList-item
&:hover
background-color lighten($ui-dracula-button--hover-backgroundColor, 15%)
.search-optionList-item--active
background-color $ui-dracula-button--active-backgroundColor
color $ui-dracula-button--active-color
&:hover
background-color $ui-dark-button--hover-backgroundColor
color $ui-dracula-button--active-color
.search-optionList-item-name-surfix
color $ui-dracula-inactive-text-color

View File

@@ -257,3 +257,43 @@ body[data-theme="monokai"]
color $ui-dark-inactive-text-color color $ui-dark-inactive-text-color
&:hover &:hover
color $ui-monokai-text-color color $ui-monokai-text-color
body[data-theme="dracula"]
.control-infoButton-panel
background-color $ui-dracula-noteList-backgroundColor
.control-infoButton-panel-trash
background-color $ui-dracula-noteList-backgroundColor
.modification-date
color $ui-dracula-text-color
.modification-date-desc
color $ui-inactive-text-color
.infoPanel-defaul-count
color $ui-dracula-text-color
.infoPanel-sub-count
color $ui-inactive-text-color
.infoPanel-default
color $ui-dracula-text-color
.infoPanel-sub
color $ui-inactive-text-color
.infoPanel-noteLink
background-color alpha($ui-dracula-borderColor, 20%)
color $ui-dracula-text-color
[id=export-wrap]
button
color $ui-dark-inactive-text-color
&:hover
background-color alpha($ui-dracula-borderColor, 20%)
color $ui-dracula-text-color
p
color $ui-dark-inactive-text-color
&:hover
color $ui-dracula-text-color

View File

@@ -29,6 +29,7 @@ import { formatDate } from 'browser/lib/date-formatter'
import { getTodoPercentageOfCompleted } from 'browser/lib/getTodoStatus' 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'
class MarkdownNoteDetail extends React.Component { class MarkdownNoteDetail extends React.Component {
constructor (props) { constructor (props) {
@@ -47,6 +48,7 @@ class MarkdownNoteDetail extends React.Component {
this.dispatchTimer = null this.dispatchTimer = null
this.toggleLockButton = this.handleToggleLockButton.bind(this) this.toggleLockButton = this.handleToggleLockButton.bind(this)
this.generateToc = () => this.handleGenerateToc()
} }
focus () { focus () {
@@ -59,10 +61,14 @@ class MarkdownNoteDetail extends React.Component {
const reversedType = this.state.editorType === 'SPLIT' ? 'EDITOR_PREVIEW' : 'SPLIT' const reversedType = this.state.editorType === 'SPLIT' ? 'EDITOR_PREVIEW' : 'SPLIT'
this.handleSwitchMode(reversedType) this.handleSwitchMode(reversedType)
}) })
ee.on('hotkey:deletenote', this.handleDeleteNote.bind(this))
ee.on('code:generate-toc', this.generateToc)
} }
componentWillReceiveProps (nextProps) { componentWillReceiveProps (nextProps) {
if (nextProps.note.key !== this.props.note.key && !this.state.isMovingNote) { const isNewNote = nextProps.note.key !== this.props.note.key
const hasDeletedTags = nextProps.note.tags.length < this.props.note.tags.length
if (!this.state.isMovingNote && (isNewNote || hasDeletedTags)) {
if (this.saveQueue != null) this.saveNow() if (this.saveQueue != null) this.saveNow()
this.setState({ this.setState({
note: Object.assign({}, nextProps.note) note: Object.assign({}, nextProps.note)
@@ -75,6 +81,7 @@ class MarkdownNoteDetail extends React.Component {
componentWillUnmount () { componentWillUnmount () {
ee.off('topbar:togglelockbutton', this.toggleLockButton) ee.off('topbar:togglelockbutton', this.toggleLockButton)
ee.off('code:generate-toc', this.generateToc)
if (this.saveQueue != null) this.saveNow() if (this.saveQueue != null) this.saveNow()
} }
@@ -87,7 +94,7 @@ class MarkdownNoteDetail extends React.Component {
handleUpdateContent () { handleUpdateContent () {
const { note } = this.state const { note } = this.state
note.content = this.refs.content.value note.content = this.refs.content.value
note.title = markdown.strip(striptags(findNoteTitle(note.content))) note.title = markdown.strip(striptags(findNoteTitle(note.content, this.props.config.editor.enableFrontMatterTitle, this.props.config.editor.frontMatterTitleField)))
this.updateNote(note) this.updateNote(note)
} }
@@ -262,6 +269,11 @@ class MarkdownNoteDetail extends React.Component {
} }
} }
handleGenerateToc () {
const editor = this.refs.content.refs.code.editor
markdownToc.generateInEditor(editor)
}
handleFocus (e) { handleFocus (e) {
this.focus() this.focus()
} }
@@ -284,9 +296,33 @@ class MarkdownNoteDetail extends React.Component {
}) })
} }
handleDeleteNote () {
this.handleTrashButtonClick()
}
handleClearTodo () {
const { note } = this.state
const splitted = note.content.split('\n')
const clearTodoContent = splitted.map((line) => {
const trimmedLine = line.trim()
if (trimmedLine.match(/\[x\]/i)) {
return line.replace(/\[x\]/i, '[ ]')
} else {
return line
}
}).join('\n')
note.content = clearTodoContent
this.refs.content.setValue(note.content)
this.updateNote(note)
}
renderEditor () { renderEditor () {
const { config, ignorePreviewPointerEvents } = this.props const { config, ignorePreviewPointerEvents } = this.props
const { note } = this.state const { note } = this.state
if (this.state.editorType === 'EDITOR_PREVIEW') { if (this.state.editorType === 'EDITOR_PREVIEW') {
return <MarkdownEditor return <MarkdownEditor
ref='content' ref='content'
@@ -363,9 +399,10 @@ class MarkdownNoteDetail extends React.Component {
<TagSelect <TagSelect
ref='tags' ref='tags'
value={this.state.note.tags} value={this.state.note.tags}
data={data}
onChange={this.handleUpdateTag.bind(this)} onChange={this.handleUpdateTag.bind(this)}
/> />
<TodoListPercentage percentageOfTodo={getTodoPercentageOfCompleted(note.content)} /> <TodoListPercentage onClearCheckboxClick={(e) => this.handleClearTodo(e)} percentageOfTodo={getTodoPercentageOfCompleted(note.content)} />
</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} />

View File

@@ -76,3 +76,8 @@ body[data-theme="monokai"]
.root .root
border-left 1px solid $ui-monokai-borderColor border-left 1px solid $ui-monokai-borderColor
background-color $ui-monokai-noteDetail-backgroundColor background-color $ui-monokai-noteDetail-backgroundColor
body[data-theme="dracula"]
.root
border-left 1px solid $ui-dracula-borderColor
background-color $ui-dracula-noteDetail-backgroundColor

View File

@@ -13,6 +13,7 @@ $info-margin-under-border = 30px
display flex display flex
align-items center align-items center
padding 0 20px padding 0 20px
z-index 99
.info-left .info-left
padding 0 10px padding 0 10px
@@ -97,8 +98,13 @@ body[data-theme="solarized-dark"]
.info .info
border-color $ui-solarized-dark-borderColor border-color $ui-solarized-dark-borderColor
background-color $ui-solarized-dark-noteDetail-backgroundColor background-color $ui-solarized-dark-noteDetail-backgroundColor
body[data-theme="monokai"] body[data-theme="monokai"]
.info .info
border-color $ui-monokai-borderColor border-color $ui-monokai-borderColor
background-color $ui-monokai-noteDetail-backgroundColor background-color $ui-monokai-noteDetail-backgroundColor
body[data-theme="dracula"]
.info
border-color $ui-dracula-borderColor
background-color $ui-dracula-noteDetail-backgroundColor

View File

@@ -29,6 +29,7 @@ import InfoPanelTrashed from './InfoPanelTrashed'
import { formatDate } from 'browser/lib/date-formatter' 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'
const electron = require('electron') const electron = require('electron')
const { remote } = electron const { remote } = electron
@@ -52,6 +53,7 @@ class SnippetNoteDetail extends React.Component {
} }
this.scrollToNextTabThreshold = 0.7 this.scrollToNextTabThreshold = 0.7
this.generateToc = () => this.handleGenerateToc()
} }
componentDidMount () { componentDidMount () {
@@ -65,6 +67,7 @@ class SnippetNoteDetail extends React.Component {
enableLeftArrow: allTabs.offsetLeft !== 0 enableLeftArrow: allTabs.offsetLeft !== 0
}) })
} }
ee.on('code:generate-toc', this.generateToc)
} }
componentWillReceiveProps (nextProps) { componentWillReceiveProps (nextProps) {
@@ -91,6 +94,16 @@ class SnippetNoteDetail extends React.Component {
componentWillUnmount () { componentWillUnmount () {
if (this.saveQueue != null) this.saveNow() if (this.saveQueue != null) this.saveNow()
ee.off('code:generate-toc', this.generateToc)
}
handleGenerateToc () {
const { note, snippetIndex } = this.state
const currentMode = note.snippets[snippetIndex].mode
if (currentMode.includes('Markdown')) {
const currentEditor = this.refs[`code-${snippetIndex}`].refs.code.editor
markdownToc.generateInEditor(currentEditor)
}
} }
handleChange (e) { handleChange (e) {
@@ -99,7 +112,7 @@ class SnippetNoteDetail extends React.Component {
if (this.refs.tags) note.tags = this.refs.tags.value if (this.refs.tags) note.tags = this.refs.tags.value
note.description = this.refs.description.value note.description = this.refs.description.value
note.updatedAt = new Date() note.updatedAt = new Date()
note.title = findNoteTitle(note.description) note.title = findNoteTitle(note.description, false)
this.setState({ this.setState({
note note
@@ -441,7 +454,7 @@ class SnippetNoteDetail extends React.Component {
const isSuper = global.process.platform === 'darwin' const isSuper = global.process.platform === 'darwin'
? e.metaKey ? e.metaKey
: e.ctrlKey : e.ctrlKey
if (isSuper && !e.shiftKey) { if (isSuper && !e.shiftKey && !e.altKey) {
e.preventDefault() e.preventDefault()
this.addSnippet() this.addSnippet()
} }
@@ -692,6 +705,7 @@ class SnippetNoteDetail extends React.Component {
keyMap={config.editor.keyMap} keyMap={config.editor.keyMap}
scrollPastEnd={config.editor.scrollPastEnd} scrollPastEnd={config.editor.scrollPastEnd}
fetchUrlTitle={config.editor.fetchUrlTitle} fetchUrlTitle={config.editor.fetchUrlTitle}
enableTableEditor={config.editor.enableTableEditor}
onChange={(e) => this.handleCodeChange(index)(e)} onChange={(e) => this.handleCodeChange(index)(e)}
ref={'code-' + index} ref={'code-' + index}
/> />
@@ -745,6 +759,7 @@ class SnippetNoteDetail extends React.Component {
<TagSelect <TagSelect
ref='tags' ref='tags'
value={this.state.note.tags} value={this.state.note.tags}
data={data}
onChange={(e) => this.handleChange(e)} onChange={(e) => this.handleChange(e)}
/> />
</div> </div>

View File

@@ -169,4 +169,21 @@ body[data-theme="monokai"]
.tabList .tabList
background-color $ui-monokai-noteDetail-backgroundColor background-color $ui-monokai-noteDetail-backgroundColor
color $ui-monokai-text-color color $ui-monokai-text-color
body[data-theme="dracula"]
.root
border-left 1px solid $ui-dracula-borderColor
background-color $ui-dracula-noteDetail-backgroundColor
.body
background-color $ui-dracula-noteDetail-backgroundColor
.body .description textarea
background-color $ui-dracula-noteDetail-backgroundColor
color $ui-dracula-text-color
border 1px solid $ui-dracula-borderColor
.tabList
background-color $ui-dracula-noteDetail-backgroundColor
color $ui-dracula-text-color

View File

@@ -6,71 +6,33 @@ import _ from 'lodash'
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig' 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'
class TagSelect extends React.Component { class TagSelect extends React.Component {
constructor (props) { constructor (props) {
super(props) super(props)
this.state = { this.state = {
newTag: '' newTag: '',
suggestions: []
} }
this.addtagHandler = this.handleAddTag.bind(this)
this.handleAddTag = this.handleAddTag.bind(this)
this.onInputBlur = this.onInputBlur.bind(this)
this.onInputChange = this.onInputChange.bind(this)
this.onInputKeyDown = this.onInputKeyDown.bind(this)
this.onSuggestionsClearRequested = this.onSuggestionsClearRequested.bind(this)
this.onSuggestionsFetchRequested = this.onSuggestionsFetchRequested.bind(this)
this.onSuggestionSelected = this.onSuggestionSelected.bind(this)
} }
componentDidMount () { addNewTag (newTag) {
this.value = this.props.value
ee.on('editor:add-tag', this.addtagHandler)
}
componentDidUpdate () {
this.value = this.props.value
}
componentWillUnmount () {
ee.off('editor:add-tag', this.addtagHandler)
}
handleAddTag () {
this.refs.newTag.focus()
}
handleNewTagInputKeyDown (e) {
switch (e.keyCode) {
case 9:
e.preventDefault()
this.submitTag()
break
case 13:
this.submitTag()
break
case 8:
if (this.refs.newTag.value.length === 0) {
this.removeLastTag()
}
}
}
handleNewTagBlur (e) {
this.submitTag()
}
removeLastTag () {
this.removeTagByCallback((value) => {
value.pop()
})
}
reset () {
this.setState({
newTag: ''
})
}
submitTag () {
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_TAG') AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_TAG')
let { value } = this.props
let newTag = this.refs.newTag.value.trim().replace(/ +/g, '_') newTag = newTag.trim().replace(/ +/g, '_')
newTag = newTag.charAt(0) === '#' ? newTag.substring(1) : newTag if (newTag.charAt(0) === '#') {
newTag.substring(1)
}
if (newTag.length <= 0) { if (newTag.length <= 0) {
this.setState({ this.setState({
@@ -79,6 +41,7 @@ class TagSelect extends React.Component {
return return
} }
let { value } = this.props
value = _.isArray(value) value = _.isArray(value)
? value.slice() ? value.slice()
: [] : []
@@ -93,10 +56,41 @@ class TagSelect extends React.Component {
}) })
} }
handleNewTagInputChange (e) { buildSuggestions () {
this.setState({ this.suggestions = _.sortBy(this.props.data.tagNoteMap.map(
newTag: this.refs.newTag.value (tag, name) => ({
}) name,
nameLC: name.toLowerCase(),
size: tag.size
})
).filter(
tag => tag.size > 0
), ['name'])
}
componentDidMount () {
this.value = this.props.value
this.buildSuggestions()
ee.on('editor:add-tag', this.handleAddTag)
}
componentDidUpdate () {
this.value = this.props.value
}
componentWillUnmount () {
ee.off('editor:add-tag', this.handleAddTag)
}
handleAddTag () {
this.refs.newTag.input.focus()
}
handleTagLabelClick (tag) {
const { router } = this.context
router.push(`/tags/${tag}`)
} }
handleTagRemoveButtonClick (tag) { handleTagRemoveButtonClick (tag) {
@@ -105,6 +99,60 @@ class TagSelect extends React.Component {
}, tag) }, tag)
} }
onInputBlur (e) {
this.submitNewTag()
}
onInputChange (e, { newValue, method }) {
this.setState({
newTag: newValue
})
}
onInputKeyDown (e) {
switch (e.keyCode) {
case 9:
e.preventDefault()
this.submitNewTag()
break
case 13:
this.submitNewTag()
break
case 8:
if (this.state.newTag.length === 0) {
this.removeLastTag()
}
}
}
onSuggestionsClearRequested () {
this.setState({
suggestions: []
})
}
onSuggestionsFetchRequested ({ value }) {
const valueLC = value.toLowerCase()
const suggestions = _.filter(
this.suggestions,
tag => !_.includes(this.value, tag.name) && tag.nameLC.indexOf(valueLC) !== -1
)
this.setState({
suggestions
})
}
onSuggestionSelected (event, { suggestion, suggestionValue }) {
this.addNewTag(suggestionValue)
}
removeLastTag () {
this.removeTagByCallback((value) => {
value.pop()
})
}
removeTagByCallback (callback, tag = null) { removeTagByCallback (callback, tag = null) {
let { value } = this.props let { value } = this.props
@@ -118,6 +166,18 @@ class TagSelect extends React.Component {
this.props.onChange() this.props.onChange()
} }
reset () {
this.buildSuggestions()
this.setState({
newTag: ''
})
}
submitNewTag () {
this.addNewTag(this.refs.newTag.input.value)
}
render () { render () {
const { value, className } = this.props const { value, className } = this.props
@@ -127,7 +187,7 @@ class TagSelect extends React.Component {
<span styleName='tag' <span styleName='tag'
key={tag} key={tag}
> >
<span styleName='tag-label'>#{tag}</span> <span styleName='tag-label' onClick={(e) => this.handleTagLabelClick(tag)}>#{tag}</span>
<button styleName='tag-removeButton' <button styleName='tag-removeButton'
onClick={(e) => this.handleTagRemoveButtonClick(tag)} onClick={(e) => this.handleTagRemoveButtonClick(tag)}
> >
@@ -138,6 +198,8 @@ class TagSelect extends React.Component {
}) })
: [] : []
const { newTag, suggestions } = this.state
return ( return (
<div className={_.isString(className) <div className={_.isString(className)
? 'TagSelect ' + className ? 'TagSelect ' + className
@@ -146,24 +208,39 @@ class TagSelect extends React.Component {
styleName='root' styleName='root'
> >
{tagList} {tagList}
<input styleName='newTag' <Autosuggest
ref='newTag' ref='newTag'
value={this.state.newTag} suggestions={suggestions}
placeholder={i18n.__('Add tag...')} onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
onChange={(e) => this.handleNewTagInputChange(e)} onSuggestionsClearRequested={this.onSuggestionsClearRequested}
onKeyDown={(e) => this.handleNewTagInputKeyDown(e)} onSuggestionSelected={this.onSuggestionSelected}
onBlur={(e) => this.handleNewTagBlur(e)} getSuggestionValue={suggestion => suggestion.name}
renderSuggestion={suggestion => (
<div>
{suggestion.name}
</div>
)}
inputProps={{
placeholder: i18n.__('Add tag...'),
value: newTag,
onChange: this.onInputChange,
onKeyDown: this.onInputKeyDown,
onBlur: this.onInputBlur
}}
/> />
</div> </div>
) )
} }
} }
TagSelect.contextTypes = {
router: PropTypes.shape({})
}
TagSelect.propTypes = { TagSelect.propTypes = {
className: PropTypes.string, className: PropTypes.string,
value: PropTypes.arrayOf(PropTypes.string), value: PropTypes.arrayOf(PropTypes.string),
onChange: PropTypes.func onChange: PropTypes.func
} }
export default CSSModules(TagSelect, styles) export default CSSModules(TagSelect, styles)

View File

@@ -39,16 +39,9 @@
.tag-label .tag-label
font-size 13px font-size 13px
color: $ui-text-color color $ui-text-color
padding 4px 16px 4px 8px padding 4px 16px 4px 8px
cursor pointer
.newTag
box-sizing border-box
border none
background-color transparent
outline none
padding 0 4px
font-size 13px
body[data-theme="dark"] body[data-theme="dark"]
.tag .tag
@@ -62,11 +55,6 @@ body[data-theme="dark"]
.tag-label .tag-label
color $ui-dark-text-color color $ui-dark-text-color
.newTag
border-color none
background-color transparent
color $ui-dark-text-color
body[data-theme="solarized-dark"] body[data-theme="solarized-dark"]
.tag .tag
background-color $ui-solarized-dark-tag-backgroundColor background-color $ui-solarized-dark-tag-backgroundColor
@@ -78,14 +66,9 @@ body[data-theme="solarized-dark"]
.tag-label .tag-label
color $ui-solarized-dark-text-color color $ui-solarized-dark-text-color
.newTag
border-color none
background-color transparent
color $ui-solarized-dark-text-color
body[data-theme="monokai"] body[data-theme="monokai"]
.tag .tag
background-color $ui-monokai-button-backgroundColor background-color $ui-monokai-tag-backgroundColor
.tag-removeButton .tag-removeButton
border-color $ui-button--focus-borderColor border-color $ui-button--focus-borderColor
@@ -93,8 +76,14 @@ body[data-theme="monokai"]
.tag-label .tag-label
color $ui-monokai-text-color color $ui-monokai-text-color
.newTag body[data-theme="dracula"]
border-color none .tag
background-color $ui-dracula-tag-backgroundColor
.tag-removeButton
border-color $ui-dracula-button--focus-borderColor
background-color transparent background-color transparent
color $ui-monokai-text-color
.tag-label
color $ui-dracula-borderColor

View File

@@ -59,7 +59,14 @@ body[data-theme="solarized-dark"]
body[data-theme="monokai"] body[data-theme="monokai"]
.control-toggleModeButton .control-toggleModeButton
background-color #272822 background-color #373831
.active .active
background-color #1EC38B background-color #f92672
box-shadow 2px 0px 7px #222222
body[data-theme="dracula"]
.control-toggleModeButton
background-color #44475a
.active
background-color #bd93f9
box-shadow 2px 0px 7px #222222 box-shadow 2px 0px 7px #222222

View File

@@ -56,7 +56,7 @@ class Main extends React.Component {
init () { init () {
dataApi dataApi
.addStorage({ .addStorage({
name: 'My Storage', name: 'My Storage Location',
path: path.join(remote.app.getPath('home'), 'Boostnote') path: path.join(remote.app.getPath('home'), 'Boostnote')
}) })
.then(data => { .then(data => {
@@ -141,7 +141,7 @@ class Main extends React.Component {
componentDidMount () { componentDidMount () {
const { dispatch, config } = this.props const { dispatch, config } = this.props
const supportedThemes = ['dark', 'white', 'solarized-dark', 'monokai'] const supportedThemes = ['dark', 'white', 'solarized-dark', 'monokai', 'dracula']
if (supportedThemes.indexOf(config.ui.theme) !== -1) { if (supportedThemes.indexOf(config.ui.theme) !== -1) {
document.body.setAttribute('data-theme', config.ui.theme) document.body.setAttribute('data-theme', config.ui.theme)
@@ -297,7 +297,7 @@ class Main extends React.Component {
onMouseUp={e => this.handleMouseUp(e)} onMouseUp={e => this.handleMouseUp(e)}
> >
<SideNav <SideNav
{..._.pick(this.props, ['dispatch', 'data', 'config', 'location'])} {..._.pick(this.props, ['dispatch', 'data', 'config', 'params', 'location'])}
width={this.state.navWidth} width={this.state.navWidth}
/> />
{!config.isSideNavFolded && {!config.isSideNavFolded &&

View File

@@ -79,3 +79,7 @@ body[data-theme="solarized-dark"]
body[data-theme="monokai"] body[data-theme="monokai"]
.root, .root--expanded .root, .root--expanded
background-color $ui-monokai-noteList-backgroundColor background-color $ui-monokai-noteList-backgroundColor
body[data-theme="dracula"]
.root, .root--expanded
background-color $ui-dracula-noteList-backgroundColor

View File

@@ -7,6 +7,7 @@ import modal from 'browser/main/lib/modal'
import NewNoteModal from 'browser/main/modals/NewNoteModal' import NewNoteModal from 'browser/main/modals/NewNoteModal'
import eventEmitter from 'browser/main/lib/eventEmitter' import eventEmitter from 'browser/main/lib/eventEmitter'
import i18n from 'browser/lib/i18n' import i18n from 'browser/lib/i18n'
import { createMarkdownNote, createSnippetNote } from 'browser/lib/newNote'
const { remote } = require('electron') const { remote } = require('electron')
const { dialog } = remote const { dialog } = remote
@@ -37,13 +38,19 @@ class NewNoteButton extends React.Component {
const { location, dispatch, config } = this.props const { location, dispatch, config } = this.props
const { storage, folder } = this.resolveTargetFolder() const { storage, folder } = this.resolveTargetFolder()
modal.open(NewNoteModal, { if (config.ui.defaultNote === 'MARKDOWN_NOTE') {
storage: storage.key, createMarkdownNote(storage.key, folder.key, dispatch, location)
folder: folder.key, } else if (config.ui.defaultNote === 'SNIPPET_NOTE') {
dispatch, createSnippetNote(storage.key, folder.key, dispatch, location, config)
location, } else {
config modal.open(NewNoteModal, {
}) storage: storage.key,
folder: folder.key,
dispatch,
location,
config
})
}
} }
resolveTargetFolder () { resolveTargetFolder () {

View File

@@ -84,7 +84,7 @@ body[data-theme="dark"]
color $ui-dark-inactive-text-color color $ui-dark-inactive-text-color
&:hover &:hover
color $ui-dark-text-color color $ui-dark-text-color
.control-button--active .control-button--active
color $ui-dark-text-color color $ui-dark-text-color
&:active &:active
@@ -109,7 +109,7 @@ body[data-theme="solarized-dark"]
color $ui-solarized-dark-inactive-text-color color $ui-solarized-dark-inactive-text-color
&:hover &:hover
color $ui-solarized-dark-text-color color $ui-solarized-dark-text-color
.control-button--active .control-button--active
color $ui-solarized-dark-text-color color $ui-solarized-dark-text-color
&:active &:active
@@ -138,3 +138,27 @@ body[data-theme="monokai"]
color $ui-monokai-text-color color $ui-monokai-text-color
&:active &:active
color $ui-monokai-text-color color $ui-monokai-text-color
body[data-theme="dracula"]
.root
border-color $ui-dracula-borderColor
background-color $ui-dracula-noteList-backgroundColor
.control
background-color $ui-dracula-noteList-backgroundColor
border-color $ui-dracula-borderColor
.control-sortBy-select
&:hover
transition 0.2s
color $ui-dracula-text-color
.control-button
color $ui-dracula-inactive-text-color
&:hover
color $ui-dracula-text-color
.control-button--active
color $ui-dracula-text-color
&:active
color $ui-dracula-text-color

View File

@@ -80,6 +80,7 @@ class NoteList extends React.Component {
this.getViewType = this.getViewType.bind(this) this.getViewType = this.getViewType.bind(this)
this.restoreNote = this.restoreNote.bind(this) this.restoreNote = this.restoreNote.bind(this)
this.copyNoteLink = this.copyNoteLink.bind(this) this.copyNoteLink = this.copyNoteLink.bind(this)
this.navigate = this.navigate.bind(this)
// TODO: not Selected noteKeys but SelectedNote(for reusing) // TODO: not Selected noteKeys but SelectedNote(for reusing)
this.state = { this.state = {
@@ -98,6 +99,7 @@ class NoteList extends React.Component {
ee.on('list:isMarkdownNote', this.alertIfSnippetHandler) ee.on('list:isMarkdownNote', this.alertIfSnippetHandler)
ee.on('import:file', this.importFromFileHandler) ee.on('import:file', this.importFromFileHandler)
ee.on('list:jump', this.jumpNoteByHash) ee.on('list:jump', this.jumpNoteByHash)
ee.on('list:navigate', this.navigate)
} }
componentWillReceiveProps (nextProps) { componentWillReceiveProps (nextProps) {
@@ -517,7 +519,7 @@ class NoteList extends React.Component {
click: this.cloneNote.bind(this) click: this.cloneNote.bind(this)
}, { }, {
label: copyNoteLink, label: copyNoteLink,
click: this.copyNoteLink(note) click: this.copyNoteLink.bind(this, note)
}) })
if (note.type === 'MARKDOWN_NOTE') { if (note.type === 'MARKDOWN_NOTE') {
if (note.blog && note.blog.blogLink && note.blog.blogId) { if (note.blog && note.blog.blogLink && note.blog.blogId) {
@@ -687,6 +689,16 @@ class NoteList extends React.Component {
return copy(noteLink) return copy(noteLink)
} }
navigate (sender, pathname) {
const { router } = this.context
router.push({
pathname,
query: {
// key: noteKey
}
})
}
save (note) { save (note) {
const { dispatch } = this.props const { dispatch } = this.props
dataApi dataApi

View File

@@ -19,7 +19,7 @@
text-align center text-align center
.top-menu-label .top-menu-label
margin-left 5px margin-left 5px
overflow ellipsis overflow ellipsis
@@ -122,3 +122,8 @@ body[data-theme="monokai"]
.root, .root--folded .root, .root--folded
background-color $ui-monokai-backgroundColor background-color $ui-monokai-backgroundColor
border-right 1px solid $ui-monokai-borderColor border-right 1px solid $ui-monokai-borderColor
body[data-theme="dracula"]
.root, .root--folded
background-color $ui-dracula-backgroundColor
border-right 1px solid $ui-dracula-borderColor

View File

@@ -38,6 +38,22 @@ class StorageItem extends React.Component {
{ {
type: 'separator' type: 'separator'
}, },
{
label: i18n.__('Export Storage'),
submenu: [
{
label: i18n.__('Export as txt'),
click: (e) => this.handleExportStorageClick(e, 'txt')
},
{
label: i18n.__('Export as md'),
click: (e) => this.handleExportStorageClick(e, 'md')
}
]
},
{
type: 'separator'
},
{ {
label: i18n.__('Unlink Storage'), label: i18n.__('Unlink Storage'),
click: (e) => this.handleUnlinkStorageClick(e) click: (e) => this.handleUnlinkStorageClick(e)
@@ -68,6 +84,30 @@ class StorageItem extends React.Component {
} }
} }
handleExportStorageClick (e, fileType) {
const options = {
properties: ['openDirectory', 'createDirectory'],
buttonLabel: i18n.__('Select directory'),
title: i18n.__('Select a folder to export the files to'),
multiSelections: false
}
dialog.showOpenDialog(remote.getCurrentWindow(), options,
(paths) => {
if (paths && paths.length === 1) {
const { storage, dispatch } = this.props
dataApi
.exportStorage(storage.key, fileType, paths[0])
.then(data => {
dispatch({
type: 'EXPORT_STORAGE',
storage: data.storage,
fileType: data.fileType
})
})
}
})
}
handleToggleButtonClick (e) { handleToggleButtonClick (e) {
const { storage, dispatch } = this.props const { storage, dispatch } = this.props
const isOpen = !this.state.isOpen const isOpen = !this.state.isOpen

View File

@@ -18,6 +18,7 @@ import TagButton from './TagButton'
import {SortableContainer} from 'react-sortable-hoc' import {SortableContainer} 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 { remote } from 'electron'
class SideNav extends React.Component { class SideNav extends React.Component {
// TODO: should not use electron stuff v0.7 // TODO: should not use electron stuff v0.7
@@ -30,6 +31,52 @@ class SideNav extends React.Component {
EventEmitter.off('side:preferences', this.handleMenuButtonClick) EventEmitter.off('side:preferences', this.handleMenuButtonClick)
} }
deleteTag (tag) {
const selectedButton = remote.dialog.showMessageBox(remote.getCurrentWindow(), {
ype: 'warning',
message: i18n.__('Confirm tag deletion'),
detail: i18n.__('This will permanently remove this tag.'),
buttons: [i18n.__('Confirm'), i18n.__('Cancel')]
})
if (selectedButton === 0) {
const { data, dispatch, location, params } = this.props
const notes = data.noteMap
.map(note => note)
.filter(note => note.tags.indexOf(tag) !== -1)
.map(note => {
note = Object.assign({}, note)
note.tags = note.tags.slice()
note.tags.splice(note.tags.indexOf(tag), 1)
return note
})
Promise
.all(notes.map(note => dataApi.updateNote(note.storage, note.key, note)))
.then(updatedNotes => {
updatedNotes.forEach(note => {
dispatch({
type: 'UPDATE_NOTE',
note
})
})
if (location.pathname.match('/tags')) {
const tags = params.tagname.split(' ')
const index = tags.indexOf(tag)
if (index !== -1) {
tags.splice(index, 1)
this.context.router.push(`/tags/${tags.map(tag => encodeURIComponent(tag)).join(' ')}`)
}
}
})
}
}
handleMenuButtonClick (e) { handleMenuButtonClick (e) {
openModal(PreferencesModal) openModal(PreferencesModal)
} }
@@ -44,6 +91,17 @@ class SideNav extends React.Component {
router.push('/starred') router.push('/starred')
} }
handleTagContextMenu (e, tag) {
const menu = []
menu.push({
label: i18n.__('Delete Tag'),
click: this.deleteTag.bind(this, tag)
})
context.popup(menu)
}
handleToggleButtonClick (e) { handleToggleButtonClick (e) {
const { dispatch, config } = this.props const { dispatch, config } = this.props
@@ -165,6 +223,7 @@ class SideNav extends React.Component {
name={tag.name} name={tag.name}
handleClickTagListItem={this.handleClickTagListItem.bind(this)} handleClickTagListItem={this.handleClickTagListItem.bind(this)}
handleClickNarrowToTag={this.handleClickNarrowToTag.bind(this)} handleClickNarrowToTag={this.handleClickNarrowToTag.bind(this)}
handleContextMenu={this.handleTagContextMenu.bind(this)}
isActive={this.getTagActive(location.pathname, tag.name)} isActive={this.getTagActive(location.pathname, tag.name)}
isRelated={tag.related} isRelated={tag.related}
key={tag.name} key={tag.name}
@@ -198,12 +257,12 @@ class SideNav extends React.Component {
const tags = pathSegments[pathSegments.length - 1] const tags = pathSegments[pathSegments.length - 1]
return (tags === 'alltags') return (tags === 'alltags')
? [] ? []
: tags.split(' ') : tags.split(' ').map(tag => decodeURIComponent(tag))
} }
handleClickTagListItem (name) { handleClickTagListItem (name) {
const { router } = this.context const { router } = this.context
router.push(`/tags/${name}`) router.push(`/tags/${encodeURIComponent(name)}`)
} }
handleSortTagsByChange (e) { handleSortTagsByChange (e) {
@@ -230,7 +289,7 @@ class SideNav extends React.Component {
} else { } else {
listOfTags.push(tag) listOfTags.push(tag)
} }
router.push(`/tags/${listOfTags.join(' ')}`) router.push(`/tags/${listOfTags.map(tag => encodeURIComponent(tag)).join(' ')}`)
} }
emptyTrash (entries) { emptyTrash (entries) {

View File

@@ -34,7 +34,7 @@
color $ui-active-color color $ui-active-color
span span
margin-left 5px margin-left 5px
.update .update
navButtonColor() navButtonColor()
height 24px height 24px
@@ -80,3 +80,14 @@ body[data-theme="monokai"]
color $ui-monokai-active-color color $ui-monokai-active-color
&:active &:active
color $ui-monokai-active-color color $ui-monokai-active-color
body[data-theme="dracula"]
navButtonColor()
.zoom
border-color $ui-dark-borderColor
color $ui-dracula-text-color
&:hover
transition 0.15s
color $ui-dracula-active-color
&:active
color $ui-dracula-active-color

View File

@@ -256,3 +256,25 @@ body[data-theme="monokai"]
input input
background-color $ui-monokai-noteList-backgroundColor background-color $ui-monokai-noteList-backgroundColor
color $ui-monokai-text-color color $ui-monokai-text-color
body[data-theme="dracula"]
.root, .root--expanded
background-color $ui-dracula-noteList-backgroundColor
.control
border-color $ui-dracula-borderColor
.control-search
background-color $ui-dracula-noteList-backgroundColor
.control-search-icon
absolute top bottom left
line-height 32px
width 35px
color $ui-dracula-inactive-text-color
background-color $ui-dracula-noteList-backgroundColor
.control-search-input
background-color $ui-dracula-noteList-backgroundColor
input
background-color $ui-dracula-noteList-backgroundColor
color $ui-dracula-text-color

View File

@@ -18,6 +18,9 @@ body
::-webkit-scrollbar ::-webkit-scrollbar
width 12px width 12px
::-webkit-scrollbar-corner
background-color: transparent;
::-webkit-scrollbar-thumb ::-webkit-scrollbar-thumb
background-color rgba(0, 0, 0, 0.15) background-color rgba(0, 0, 0, 0.15)
@@ -132,6 +135,15 @@ body[data-theme="dark"]
.CodeMirror-foldgutter-folded:after .CodeMirror-foldgutter-folded:after
content: "\25B8" content: "\25B8"
.CodeMirror-hover
padding 2px 4px 0 4px
position absolute
z-index 99
.CodeMirror-hyperlink
cursor pointer
.sortableItemHelper .sortableItemHelper
z-index modalZIndex + 5 z-index modalZIndex + 5
@@ -153,6 +165,17 @@ body[data-theme="monokai"]
.sortableItemHelper .sortableItemHelper
color: $ui-monokai-text-color color: $ui-monokai-text-color
body[data-theme="dracula"]
::-webkit-scrollbar-thumb
background-color rgba(0, 0, 0, 0.3)
.ModalBase
.modalBack
background-color $ui-dracula-backgroundColor
.sortableItemHelper
color: $ui-dracula-text-color
body[data-theme="default"] body[data-theme="default"]
.SideNav ::-webkit-scrollbar-thumb .SideNav ::-webkit-scrollbar-thumb
background-color rgba(255, 255, 255, 0.3) background-color rgba(255, 255, 255, 0.3)
@import '../styles/Detail/TagSelect.styl'

View File

@@ -24,7 +24,8 @@ export const DEFAULT_CONFIG = {
amaEnabled: true, amaEnabled: true,
hotkey: { hotkey: {
toggleMain: OSX ? 'Command + Alt + L' : 'Super + Alt + E', toggleMain: OSX ? 'Command + Alt + L' : 'Super + Alt + E',
toggleMode: OSX ? 'Command + M' : 'Ctrl + M' toggleMode: OSX ? 'Command + Alt + M' : 'Ctrl + M',
deleteNote: OSX ? 'Command + Shift + Backspace' : 'Ctrl + Shift + Backspace'
}, },
ui: { ui: {
language: 'en', language: 'en',
@@ -46,7 +47,10 @@ export const DEFAULT_CONFIG = {
switchPreview: 'BLUR', // Available value: RIGHTCLICK, BLUR switchPreview: 'BLUR', // Available value: RIGHTCLICK, BLUR
scrollPastEnd: false, scrollPastEnd: false,
type: 'SPLIT', type: 'SPLIT',
fetchUrlTitle: true fetchUrlTitle: true,
enableTableEditor: false,
enableFrontMatterTitle: true,
frontMatterTitleField: 'title'
}, },
preview: { preview: {
fontSize: '14', fontSize: '14',
@@ -59,12 +63,14 @@ export const DEFAULT_CONFIG = {
latexBlockClose: '$$', latexBlockClose: '$$',
plantUMLServerAddress: 'http://www.plantuml.com/plantuml', plantUMLServerAddress: 'http://www.plantuml.com/plantuml',
scrollPastEnd: false, scrollPastEnd: false,
scrollSync: true,
smartQuotes: true, smartQuotes: true,
breaks: true, breaks: true,
smartArrows: false, smartArrows: false,
allowCustomCSS: false, allowCustomCSS: false,
customCSS: '', customCSS: '',
sanitize: 'STRICT' // 'STRICT', 'ALLOW_STYLES', 'NONE' sanitize: 'STRICT', // 'STRICT', 'ALLOW_STYLES', 'NONE'
lineThroughCheckbox: true
}, },
blog: { blog: {
type: 'wordpress', // Available value: wordpress, add more types in the future plz type: 'wordpress', // Available value: wordpress, add more types in the future plz
@@ -146,6 +152,8 @@ function set (updates) {
document.body.setAttribute('data-theme', 'solarized-dark') document.body.setAttribute('data-theme', 'solarized-dark')
} else if (newConfig.ui.theme === 'monokai') { } else if (newConfig.ui.theme === 'monokai') {
document.body.setAttribute('data-theme', 'monokai') document.body.setAttribute('data-theme', 'monokai')
} else if (newConfig.ui.theme === 'dracula') {
document.body.setAttribute('data-theme', 'dracula')
} else { } else {
document.body.setAttribute('data-theme', 'default') document.body.setAttribute('data-theme', 'default')
} }
@@ -194,6 +202,7 @@ function rewriteHotkey (config) {
const keys = [...Object.keys(config.hotkey)] const keys = [...Object.keys(config.hotkey)]
keys.forEach(key => { keys.forEach(key => {
config.hotkey[key] = config.hotkey[key].replace(/Cmd/g, 'Command') config.hotkey[key] = config.hotkey[key].replace(/Cmd/g, 'Command')
config.hotkey[key] = config.hotkey[key].replace(/Opt/g, 'Alt')
}) })
return config return config
} }

View File

@@ -11,6 +11,118 @@ import i18n from 'browser/lib/i18n'
const STORAGE_FOLDER_PLACEHOLDER = ':storage' const STORAGE_FOLDER_PLACEHOLDER = ':storage'
const DESTINATION_FOLDER = 'attachments' const DESTINATION_FOLDER = 'attachments'
const PATH_SEPARATORS = escapeStringRegexp(path.posix.sep) + escapeStringRegexp(path.win32.sep) const PATH_SEPARATORS = escapeStringRegexp(path.posix.sep) + escapeStringRegexp(path.win32.sep)
/**
* @description
* Create a Image element to get the real size of image.
* @param {File} file the File object dropped.
* @returns {Promise<Image>} Image element created
*/
function getImage (file) {
return new Promise((resolve) => {
const reader = new FileReader()
const img = new Image()
img.onload = () => resolve(img)
reader.onload = e => {
img.src = e.target.result
}
reader.readAsDataURL(file)
})
}
/**
* @description
* Get the orientation info from iamges's EXIF data.
* case 1: The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side.
* case 2: The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side.
* case 3: The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side.
* case 4: The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side.
* case 5: The 0th row is the visual left-hand side of the image, and the 0th column is the visual top.
* case 6: The 0th row is the visual right-hand side of the image, and the 0th column is the visual top.
* case 7: The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom.
* case 8: The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom.
* Other: reserved
* ref: http://sylvana.net/jpegcrop/exif_orientation.html
* @param {File} file the File object dropped.
* @returns {Promise<Number>} Orientation info
*/
function getOrientation (file) {
const getData = arrayBuffer => {
const view = new DataView(arrayBuffer)
// Not start with SOI(Start of image) Marker return fail value
if (view.getUint16(0, false) !== 0xFFD8) return -2
const length = view.byteLength
let offset = 2
while (offset < length) {
const marker = view.getUint16(offset, false)
offset += 2
// Loop and seed for APP1 Marker
if (marker === 0xFFE1) {
// return fail value if it isn't EXIF data
if (view.getUint32(offset += 2, false) !== 0x45786966) {
return -1
}
// Read TIFF header,
// First 2bytes defines byte align of TIFF data.
// If it is 0x4949="II", it means "Intel" type byte align.
// If it is 0x4d4d="MM", it means "Motorola" type byte align
const little = view.getUint16(offset += 6, false) === 0x4949
offset += view.getUint32(offset + 4, little)
const tags = view.getUint16(offset, little) // Get TAG number
offset += 2
for (let i = 0; i < tags; i++) {
// Loop to find Orientation TAG and return the value
if (view.getUint16(offset + (i * 12), little) === 0x0112) {
return view.getUint16(offset + (i * 12) + 8, little)
}
}
} else if ((marker & 0xFF00) !== 0xFF00) { // If not start with 0xFF, not a Marker
break
} else {
offset += view.getUint16(offset, false)
}
}
return -1
}
return new Promise((resolve) => {
const reader = new FileReader()
reader.onload = event => resolve(getData(event.target.result))
reader.readAsArrayBuffer(file.slice(0, 64 * 1024))
})
}
/**
* @description
* Rotate image file to correct direction.
* Create a canvas and draw the image with correct direction, then export to base64 format.
* @param {*} file the File object dropped.
* @return {String} Base64 encoded image.
*/
function fixRotate (file) {
return Promise.all([getImage(file), getOrientation(file)])
.then(([img, orientation]) => {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
if (orientation > 4 && orientation < 9) {
canvas.width = img.height
canvas.height = img.width
} else {
canvas.width = img.width
canvas.height = img.height
}
switch (orientation) {
case 2: ctx.transform(-1, 0, 0, 1, img.width, 0); break
case 3: ctx.transform(-1, 0, 0, -1, img.width, img.height); break
case 4: ctx.transform(1, 0, 0, -1, 0, img.height); break
case 5: ctx.transform(0, 1, 1, 0, 0, 0); break
case 6: ctx.transform(0, 1, -1, 0, img.height, 0); break
case 7: ctx.transform(0, -1, -1, 0, img.height, img.width); break
case 8: ctx.transform(0, -1, 1, 0, 0, img.width); break
default: break
}
ctx.drawImage(img, 0, 0)
return canvas.toDataURL()
})
}
/** /**
* @description * @description
@@ -38,26 +150,34 @@ function copyAttachment (sourceFilePath, storageKey, noteKey, useRandomName = tr
} }
try { try {
if (!fs.existsSync(sourceFilePath)) { const isBase64 = typeof sourceFilePath === 'object' && sourceFilePath.type === 'base64'
reject('source file does not exist') if (!fs.existsSync(sourceFilePath) && !isBase64) {
return reject('source file does not exist')
} }
const targetStorage = findStorage.findStorage(storageKey) const targetStorage = findStorage.findStorage(storageKey)
const inputFileStream = fs.createReadStream(sourceFilePath)
let destinationName let destinationName
if (useRandomName) { if (useRandomName) {
destinationName = `${uniqueSlug()}${path.extname(sourceFilePath)}` destinationName = `${uniqueSlug()}${path.extname(sourceFilePath.sourceFilePath || sourceFilePath)}`
} else { } else {
destinationName = path.basename(sourceFilePath) destinationName = path.basename(sourceFilePath.sourceFilePath || sourceFilePath)
} }
const destinationDir = path.join(targetStorage.path, DESTINATION_FOLDER, noteKey) const destinationDir = path.join(targetStorage.path, DESTINATION_FOLDER, noteKey)
createAttachmentDestinationFolder(targetStorage.path, noteKey) createAttachmentDestinationFolder(targetStorage.path, noteKey)
const outputFile = fs.createWriteStream(path.join(destinationDir, destinationName)) const outputFile = fs.createWriteStream(path.join(destinationDir, destinationName))
inputFileStream.pipe(outputFile)
inputFileStream.on('end', () => { if (isBase64) {
resolve(destinationName) const base64Data = sourceFilePath.data.replace(/^data:image\/\w+;base64,/, '')
}) const dataBuffer = new Buffer(base64Data, 'base64')
outputFile.write(dataBuffer, () => {
resolve(destinationName)
})
} else {
const inputFileStream = fs.createReadStream(sourceFilePath)
inputFileStream.pipe(outputFile)
inputFileStream.on('end', () => {
resolve(destinationName)
})
}
} catch (e) { } catch (e) {
return reject(e) return reject(e)
} }
@@ -137,10 +257,17 @@ function handleAttachmentDrop (codeEditor, storageKey, noteKey, dropEvent) {
const filePath = file.path const filePath = file.path
const originalFileName = path.basename(filePath) const originalFileName = path.basename(filePath)
const fileType = file['type'] const fileType = file['type']
const isImage = fileType.startsWith('image')
copyAttachment(filePath, storageKey, noteKey).then((fileName) => { let promise
const showPreview = fileType.startsWith('image') if (isImage) {
const imageMd = generateAttachmentMarkdown(originalFileName, path.join(STORAGE_FOLDER_PLACEHOLDER, noteKey, fileName), showPreview) promise = fixRotate(file).then(base64data => {
return copyAttachment({type: 'base64', data: base64data, sourceFilePath: filePath}, storageKey, noteKey)
})
} else {
promise = copyAttachment(filePath, storageKey, noteKey)
}
promise.then((fileName) => {
const imageMd = generateAttachmentMarkdown(originalFileName, path.join(STORAGE_FOLDER_PLACEHOLDER, noteKey, fileName), isImage)
codeEditor.insertAttachmentMd(imageMd) codeEditor.insertAttachmentMd(imageMd)
}) })
} }

View File

@@ -0,0 +1,63 @@
import { findStorage } from 'browser/lib/findStorage'
import resolveStorageData from './resolveStorageData'
import resolveStorageNotes from './resolveStorageNotes'
import filenamify from 'filenamify'
import * as path from 'path'
import * as fs from 'fs'
/**
* @param {String} storageKey
* @param {String} fileType
* @param {String} exportDir
*
* @return {Object}
* ```
* {
* storage: Object,
* fileType: String,
* exportDir: String
* }
* ```
*/
function exportStorage (storageKey, fileType, exportDir) {
let targetStorage
try {
targetStorage = findStorage(storageKey)
} catch (e) {
return Promise.reject(e)
}
return resolveStorageData(targetStorage)
.then(storage => (
resolveStorageNotes(storage).then(notes => ({storage, notes}))
))
.then(function exportNotes (data) {
const { storage, notes } = data
const folderNamesMapping = {}
storage.folders.forEach(folder => {
const folderExportedDir = path.join(exportDir, filenamify(folder.name, {replacement: '_'}))
folderNamesMapping[folder.key] = folderExportedDir
// make sure directory exists
try {
fs.mkdirSync(folderExportedDir)
} catch (e) {}
})
notes
.filter(note => !note.isTrashed && note.type === 'MARKDOWN_NOTE')
.forEach(markdownNote => {
const folderExportedDir = folderNamesMapping[markdownNote.folder]
const snippetName = `${filenamify(markdownNote.title, {replacement: '_'})}.${fileType}`
const notePath = path.join(folderExportedDir, snippetName)
fs.writeFileSync(notePath, markdownNote.content)
})
return {
storage,
fileType,
exportDir
}
})
}
module.exports = exportStorage

View File

@@ -9,6 +9,7 @@ const dataApi = {
deleteFolder: require('./deleteFolder'), deleteFolder: require('./deleteFolder'),
reorderFolder: require('./reorderFolder'), reorderFolder: require('./reorderFolder'),
exportFolder: require('./exportFolder'), exportFolder: require('./exportFolder'),
exportStorage: require('./exportStorage'),
createNote: require('./createNote'), createNote: require('./createNote'),
updateNote: require('./updateNote'), updateNote: require('./updateNote'),
deleteNote: require('./deleteNote'), deleteNote: require('./deleteNote'),

View File

@@ -3,5 +3,8 @@ import ee from 'browser/main/lib/eventEmitter'
module.exports = { module.exports = {
'toggleMode': () => { 'toggleMode': () => {
ee.emit('topbar:togglemodebutton') ee.emit('topbar:togglemodebutton')
},
'deleteNote': () => {
ee.emit('hotkey:deletenote')
} }
} }

View File

@@ -128,3 +128,29 @@ body[data-theme="monokai"]
.control-confirmButton .control-confirmButton
colorMonokaiPrimaryButton() colorMonokaiPrimaryButton()
body[data-theme="dracula"]
.root
modalDracula()
width 500px
height 270px
overflow hidden
position relative
.header
background-color transparent
border-color $ui-dark-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()

View File

@@ -1,12 +1,9 @@
import React from 'react' import React from 'react'
import CSSModules from 'browser/lib/CSSModules' import CSSModules from 'browser/lib/CSSModules'
import styles from './NewNoteModal.styl' import styles from './NewNoteModal.styl'
import dataApi from 'browser/main/lib/dataApi'
import { hashHistory } from 'react-router'
import ee from 'browser/main/lib/eventEmitter'
import ModalEscButton from 'browser/components/ModalEscButton' import ModalEscButton from 'browser/components/ModalEscButton'
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
import i18n from 'browser/lib/i18n' import i18n from 'browser/lib/i18n'
import { createMarkdownNote, createSnippetNote } from 'browser/lib/newNote'
class NewNoteModal extends React.Component { class NewNoteModal extends React.Component {
constructor (props) { constructor (props) {
@@ -24,31 +21,10 @@ class NewNoteModal extends React.Component {
} }
handleMarkdownNoteButtonClick (e) { handleMarkdownNoteButtonClick (e) {
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_MARKDOWN')
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_ALLNOTE')
const { storage, folder, dispatch, location } = this.props const { storage, folder, dispatch, location } = this.props
dataApi createMarkdownNote(storage, folder, dispatch, location).then(() => {
.createNote(storage, { setTimeout(this.props.close, 200)
type: 'MARKDOWN_NOTE', })
folder: folder,
title: '',
content: ''
})
.then(note => {
const noteHash = note.key
dispatch({
type: 'UPDATE_NOTE',
note: note
})
hashHistory.push({
pathname: location.pathname,
query: { key: noteHash }
})
ee.emit('list:jump', noteHash)
ee.emit('detail:focus')
setTimeout(this.props.close, 200)
})
} }
handleMarkdownNoteButtonKeyDown (e) { handleMarkdownNoteButtonKeyDown (e) {
@@ -59,38 +35,10 @@ class NewNoteModal extends React.Component {
} }
handleSnippetNoteButtonClick (e) { handleSnippetNoteButtonClick (e) {
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_SNIPPET')
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_ALLNOTE')
const { storage, folder, dispatch, location, config } = this.props const { storage, folder, dispatch, location, config } = this.props
createSnippetNote(storage, folder, dispatch, location, config).then(() => {
dataApi setTimeout(this.props.close, 200)
.createNote(storage, { })
type: 'SNIPPET_NOTE',
folder: folder,
title: '',
description: '',
snippets: [
{
name: '',
mode: config.editor.snippetDefaultLanguage || 'text',
content: ''
}
]
})
.then(note => {
const noteHash = note.key
dispatch({
type: 'UPDATE_NOTE',
note: note
})
hashHistory.push({
pathname: location.pathname,
query: { key: noteHash }
})
ee.emit('list:jump', noteHash)
ee.emit('detail:focus')
setTimeout(this.props.close, 200)
})
} }
handleSnippetNoteButtonKeyDown (e) { handleSnippetNoteButtonKeyDown (e) {

View File

@@ -97,3 +97,20 @@ body[data-theme="monokai"]
.description .description
color $ui-monokai-text-color color $ui-monokai-text-color
body[data-theme="dracula"]
.root
background-color transparent
.header
color $ui-dracula-text-color
.control-button
border-color $ui-dracula-borderColor
color $ui-dracula-text-color
background-color transparent
&:focus
colorDraculaPrimaryButton()
.description
color $ui-dracula-text-color

View File

@@ -43,7 +43,7 @@ class Blog extends React.Component {
this.handleSettingError = (err) => { this.handleSettingError = (err) => {
this.setState({BlogAlert: { this.setState({BlogAlert: {
type: 'error', type: 'error',
message: err.message != null ? err.message : i18n.__('Error occurs!') message: err.message != null ? err.message : i18n.__('An error occurred!')
}}) }})
} }
this.oldBlog = this.state.config.blog this.oldBlog = this.state.config.blog
@@ -70,7 +70,7 @@ class Blog extends React.Component {
this.props.haveToSave({ this.props.haveToSave({
tab: 'Blog', tab: 'Blog',
type: 'warning', type: 'warning',
message: i18n.__('You have to save!') message: i18n.__('Unsaved Changes!')
}) })
} }
} }

View File

@@ -68,9 +68,9 @@
:global :global
.alert .alert
display inline-block display inline-block
position absolute position fixed
top 60px top 130px
right 15px right 100px
font-size 14px font-size 14px
.success .success
color #1EC38B color #1EC38B
@@ -127,7 +127,7 @@ colorDarkControl()
border-color $ui-dark-borderColor border-color $ui-dark-borderColor
background-color $ui-dark-backgroundColor background-color $ui-dark-backgroundColor
color $ui-dark-text-color color $ui-dark-text-color
colorSolarizedDarkControl() colorSolarizedDarkControl()
border none border none
background-color $ui-solarized-dark-button-backgroundColor background-color $ui-solarized-dark-button-backgroundColor
@@ -138,6 +138,10 @@ colorMonokaiControl()
background-color $ui-monokai-button-backgroundColor background-color $ui-monokai-button-backgroundColor
color $ui-monokai-text-color color $ui-monokai-text-color
colorDraculaControl()
border none
background-color $ui-dracula-button-backgroundColor
color $ui-dracula-text-color
body[data-theme="dark"] body[data-theme="dark"]
.root .root
@@ -165,27 +169,27 @@ body[data-theme="dark"]
.group-section-control .group-section-control
select, .group-section-control-input select, .group-section-control-input
colorDarkControl() colorDarkControl()
body[data-theme="solarized-dark"] body[data-theme="solarized-dark"]
.root .root
color $ui-solarized-dark-text-color color $ui-solarized-dark-text-color
.group-header .group-header
color $ui-solarized-dark-text-color color $ui-solarized-dark-text-color
border-color $ui-solarized-dark-borderColor border-color $ui-solarized-dark-borderColor
.group-header2 .group-header2
color $ui-solarized-dark-text-color color $ui-solarized-dark-text-color
.group-section-control-input .group-section-control-input
border-color $ui-solarized-dark-borderColor border-color $ui-solarized-dark-borderColor
.group-control .group-control
border-color $ui-solarized-dark-borderColor border-color $ui-solarized-dark-borderColor
.group-control-leftButton .group-control-leftButton
colorDarkDefaultButton() colorDarkDefaultButton()
border-color $ui-solarized-dark-borderColor border-color $ui-solarized-dark-borderColor
.group-control-rightButton .group-control-rightButton
colorSolarizedDarkPrimaryButton() colorSolarizedDarkPrimaryButton()
.group-hint .group-hint
@@ -200,19 +204,19 @@ body[data-theme="monokai"]
.group-header .group-header
color $ui-monokai-text-color color $ui-monokai-text-color
border-color $ui-monokai-borderColor border-color $ui-monokai-borderColor
.group-header2 .group-header2
color $ui-monokai-text-color color $ui-monokai-text-color
.group-section-control-input .group-section-control-input
border-color $ui-monokai-borderColor border-color $ui-monokai-borderColor
.group-control .group-control
border-color $ui-monokai-borderColor border-color $ui-monokai-borderColor
.group-control-leftButton .group-control-leftButton
colorDarkDefaultButton() colorDarkDefaultButton()
border-color $ui-monokai-borderColor border-color $ui-monokai-borderColor
.group-control-rightButton .group-control-rightButton
colorMonokaiPrimaryButton() colorMonokaiPrimaryButton()
.group-hint .group-hint
@@ -220,3 +224,30 @@ body[data-theme="monokai"]
.group-section-control .group-section-control
select, .group-section-control-input select, .group-section-control-input
colorMonokaiControl() colorMonokaiControl()
body[data-theme="dracula"]
.root
color $ui-dracula-text-color
.group-header
color $ui-dracula-text-color
border-color $ui-dracula-borderColor
.group-header2
color $ui-dracula-text-color
.group-section-control-input
border-color $ui-dracula-borderColor
.group-control
border-color $ui-dracula-borderColor
.group-control-leftButton
colorDarkDefaultButton()
border-color $ui-dracula-borderColor
.group-control-rightButton
colorDraculaPrimaryButton()
.group-hint
colorDraculaControl()
.group-section-control
select, .group-section-control-input
colorDraculaControl()

View File

@@ -23,21 +23,29 @@ class Crowdfunding extends React.Component {
return ( return (
<div styleName='root'> <div styleName='root'>
<div styleName='header'>{i18n.__('Crowdfunding')}</div> <div styleName='header'>{i18n.__('Crowdfunding')}</div>
<p>{i18n.__('Dear everyone,')}</p>
<br />
<p>{i18n.__('Thank you for using Boostnote!')}</p> <p>{i18n.__('Thank you for using Boostnote!')}</p>
<p>{i18n.__('Boostnote is used in about 200 different countries and regions by an awesome community of developers.')}</p>
<br /> <br />
<p>{i18n.__('To continue supporting this growth, and to satisfy community expectations,')}</p> <p>{i18n.__('We launched IssueHunt which is an issue-based crowdfunding / sourcing platform for open source projects.')}</p>
<p>{i18n.__('we would like to invest more time and resources in this project.')}</p> <p>{i18n.__('Anyone can put a bounty on not only a bug but also on OSS feature requests listed on IssueHunt. Collected funds will be distributed to project owners and contributors.')}</p>
<br /> <br />
<p>{i18n.__('If you like this project and see its potential, you can help by supporting us on OpenCollective!')}</p> <p>{i18n.__('### Sustainable Open Source Ecosystem')}</p>
<p>{i18n.__('We discussed about open-source ecosystem and IssueHunt concept with the Boostnote team repeatedly. We actually also discussed with Matz who father of Ruby.')}</p>
<p>{i18n.__('The original reason why we made IssueHunt was to reward our contributors of Boostnote project. Weve got tons of Github stars and hundred of contributors in two years.')}</p>
<p>{i18n.__('We thought that it will be nice if we can pay reward for our contributors.')}</p>
<br /> <br />
<p>{i18n.__('Thanks,')}</p> <p>{i18n.__('### We believe Meritocracy')}</p>
<p>{i18n.__('Boostnote maintainers')}</p> <p>{i18n.__('We think developers who has skill and did great things must be rewarded properly.')}</p>
<p>{i18n.__('OSS projects are used in everywhere on the internet, but no matter how they great, most of owners of those projects need to have another job to sustain their living.')}</p>
<p>{i18n.__('It sometimes looks like exploitation.')}</p>
<p>{i18n.__('Weve realized IssueHunt could enhance sustainability of open-source ecosystem.')}</p>
<br />
<p>{i18n.__('As same as issues of Boostnote are already funded on IssueHunt, your open-source projects can be also started funding from now.')}</p>
<br />
<p>{i18n.__('Thank you,')}</p>
<p>{i18n.__('The Boostnote Team')}</p>
<br /> <br />
<button styleName='cf-link'> <button styleName='cf-link'>
<a href='https://opencollective.com/boostnoteio' onClick={(e) => this.handleLinkClick(e)}>{i18n.__('Support via OpenCollective')}</a> <a href='http://bit.ly/issuehunt-from-boostnote-app' onClick={(e) => this.handleLinkClick(e)}>{i18n.__('See IssueHunt')}</a>
</button> </button>
</div> </div>
) )

View File

@@ -29,7 +29,7 @@ p
body[data-theme="dark"] body[data-theme="dark"]
p p
color $ui-dark-text-color color $ui-dark-text-color
body[data-theme="solarized-dark"] body[data-theme="solarized-dark"]
.root .root
color $ui-solarized-dark-text-color color $ui-solarized-dark-text-color
@@ -41,3 +41,9 @@ body[data-theme="monokai"]
color $ui-monokai-text-color color $ui-monokai-text-color
p p
color $ui-monokai-text-color color $ui-monokai-text-color
body[data-theme="dracula"]
.root
color $ui-dracula-text-color
p
color $ui-dracula-text-color

View File

@@ -2,6 +2,7 @@
height 35px height 35px
box-sizing border-box box-sizing border-box
padding 2.5px 15px padding 2.5px 15px
display flex
&:hover &:hover
background-color darken(white, 3%) background-color darken(white, 3%)
@@ -18,7 +19,10 @@
border-left solid 2px transparent border-left solid 2px transparent
padding 0 10px padding 0 10px
line-height 30px line-height 30px
float left flex 1
white-space nowrap
text-overflow ellipsis
overflow hidden
.folderItem-left-danger .folderItem-left-danger
color $danger-color color $danger-color
font-weight bold font-weight bold
@@ -52,7 +56,8 @@
outline none outline none
.folderItem-right .folderItem-right
float right -webkit-box-flex: 1
white-space nowrap
.folderItem-right-button .folderItem-right-button
vertical-align middle vertical-align middle
@@ -149,3 +154,26 @@ body[data-theme="monokai"]
.folderItem-right-dangerButton .folderItem-right-dangerButton
colorMonokaiPrimaryButton() colorMonokaiPrimaryButton()
body[data-theme="dracula"]
.folderItem
&:hover
background-color $ui-dracula-button-backgroundColor
.folderItem-left-danger
color $danger-color
.folderItem-left-key
color $ui-dark-inactive-text-color
.folderItem-left-colorButton
colorDraculaPrimaryButton()
.folderItem-right-button
colorDraculaPrimaryButton()
.folderItem-right-confirmButton
colorDraculaPrimaryButton()
.folderItem-right-dangerButton
colorDraculaPrimaryButton()

View File

@@ -30,7 +30,7 @@ class HotkeyTab extends React.Component {
this.handleSettingError = (err) => { this.handleSettingError = (err) => {
this.setState({keymapAlert: { this.setState({keymapAlert: {
type: 'error', type: 'error',
message: err.message != null ? err.message : i18n.__('Error occurs!') message: err.message != null ? err.message : i18n.__('An error occurred!')
}}) }})
} }
this.oldHotkey = this.state.config.hotkey this.oldHotkey = this.state.config.hotkey
@@ -68,7 +68,8 @@ class HotkeyTab extends React.Component {
const { config } = this.state const { config } = this.state
config.hotkey = { 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
} }
this.setState({ this.setState({
config config
@@ -79,7 +80,7 @@ class HotkeyTab extends React.Component {
this.props.haveToSave({ this.props.haveToSave({
tab: 'Hotkey', tab: 'Hotkey',
type: 'warning', type: 'warning',
message: i18n.__('You have to save!') message: i18n.__('Unsaved Changes!')
}) })
} }
} }
@@ -117,7 +118,7 @@ class HotkeyTab extends React.Component {
</div> </div>
</div> </div>
<div styleName='group-section'> <div styleName='group-section'>
<div styleName='group-section-label'>{i18n.__('Toggle editor mode')}</div> <div styleName='group-section-label'>{i18n.__('Toggle Editor Mode')}</div>
<div styleName='group-section-control'> <div styleName='group-section-control'>
<input styleName='group-section-control-input' <input styleName='group-section-control-input'
onChange={(e) => this.handleHotkeyChange(e)} onChange={(e) => this.handleHotkeyChange(e)}
@@ -127,6 +128,17 @@ class HotkeyTab extends React.Component {
/> />
</div> </div>
</div> </div>
<div styleName='group-section'>
<div styleName='group-section-label'>{i18n.__('Delete Note')}</div>
<div styleName='group-section-control'>
<input styleName='group-section-control-input'
onChange={(e) => this.handleHotkeyChange(e)}
ref='deleteNote'
value={config.hotkey.deleteNote}
type='text'
/>
</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)}

View File

@@ -84,7 +84,7 @@ class InfoTab extends React.Component {
>{i18n.__('GitHub')}</a> >{i18n.__('GitHub')}</a>
</li> </li>
<li> <li>
<a href='https://boostlog.io/@junp1234' <a href='https://medium.com/boostnote'
onClick={(e) => this.handleLinkClick(e)} onClick={(e) => this.handleLinkClick(e)}
>{i18n.__('Blog')}</a> >{i18n.__('Blog')}</a>
</li> </li>

View File

@@ -60,7 +60,7 @@
body[data-theme="dark"] body[data-theme="dark"]
.root .root
color alpha($tab--dark-text-color, 80%) color alpha($tab--dark-text-color, 80%)
body[data-theme="solarized-dark"] body[data-theme="solarized-dark"]
.root .root
@@ -75,3 +75,10 @@ body[data-theme="monokai"]
.list .list
a a
color $ui-monokai-active-color color $ui-monokai-active-color
body[data-theme="dracula"]
.root
color $ui-dracula-text-color
.list
a
color $ui-dracula-active-color

View File

@@ -90,7 +90,7 @@ body[data-theme="dark"]
background-color $dark-primary-button-background--active background-color $dark-primary-button-background--active
&:hover &:hover
color white color white
body[data-theme="solarized-dark"] body[data-theme="solarized-dark"]
.root .root
@@ -139,3 +139,27 @@ body[data-theme="monokai"]
background-color $ui-monokai-button--active-backgroundColor background-color $ui-monokai-button--active-backgroundColor
&:hover &:hover
color white color white
body[data-theme="dracula"]
.root
background-color transparent
.top-bar
background-color transparent
border-color $ui-dracula-borderColor
p
color $ui-dracula-text-color
.nav
background-color transparent
border-color $ui-dracula-borderColor
.nav-button
background-color transparent
color $ui-dracula-text-color
&:hover
color $ui-dracula-text-color
.nav-button--active
@extend .nav-button
color $ui-dracula-button--active-color
background-color $ui-dracula-button--active-backgroundColor
&:hover
color #f8f8f2

View File

@@ -55,7 +55,11 @@ class SnippetList extends React.Component {
defineSnippetStyleName (snippet) { defineSnippetStyleName (snippet) {
const { currentSnippet } = this.props const { currentSnippet } = this.props
if (currentSnippet == null) return
if (currentSnippet == null) {
return 'snippet-item'
}
if (currentSnippet.id === snippet.id) { if (currentSnippet.id === snippet.id) {
return 'snippet-item-selected' return 'snippet-item-selected'
} else { } else {

View File

@@ -6,6 +6,9 @@ import i18n from 'browser/lib/i18n'
import dataApi from 'browser/main/lib/dataApi' import dataApi from 'browser/main/lib/dataApi'
import SnippetList from './SnippetList' import SnippetList from './SnippetList'
import eventEmitter from 'browser/main/lib/eventEmitter' import eventEmitter from 'browser/main/lib/eventEmitter'
import copy from 'copy-to-clipboard'
const path = require('path')
class SnippetTab extends React.Component { class SnippetTab extends React.Component {
constructor (props) { constructor (props) {
@@ -16,6 +19,17 @@ class SnippetTab extends React.Component {
this.changeDelay = null this.changeDelay = null
} }
notify (title, options) {
if (global.process.platform === 'win32') {
options.icon = path.join(
'file://',
global.__dirname,
'../../resources/app.png'
)
}
return new window.Notification(title, options)
}
handleSnippetNameOrPrefixChange () { handleSnippetNameOrPrefixChange () {
clearTimeout(this.changeDelay) clearTimeout(this.changeDelay)
this.changeDelay = setTimeout(() => { this.changeDelay = setTimeout(() => {
@@ -27,12 +41,14 @@ class SnippetTab extends React.Component {
handleSnippetSelect (snippet) { handleSnippetSelect (snippet) {
const { currentSnippet } = this.state const { currentSnippet } = this.state
if (currentSnippet === null || currentSnippet.id !== snippet.id) { if (snippet !== null) {
dataApi.fetchSnippet(snippet.id).then(changedSnippet => { if (currentSnippet === null || currentSnippet.id !== snippet.id) {
// notify the snippet editor to load the content of the new snippet dataApi.fetchSnippet(snippet.id).then(changedSnippet => {
this.snippetEditor.onSnippetChanged(changedSnippet) // notify the snippet editor to load the content of the new snippet
this.setState({currentSnippet: changedSnippet}) this.snippetEditor.onSnippetChanged(changedSnippet)
}) this.setState({currentSnippet: changedSnippet})
})
}
} }
} }
@@ -54,6 +70,17 @@ class SnippetTab extends React.Component {
} }
} }
handleCopySnippet (e) {
const showCopyNotification = this.props.config.ui.showCopyNotification
copy(this.state.currentSnippet.content)
if (showCopyNotification) {
this.notify('Saved to Clipboard!', {
body: 'Paste it wherever you want!',
silent: true
})
}
}
render () { render () {
const { config, storageKey } = this.props const { config, storageKey } = this.props
const { currentSnippet } = this.state const { currentSnippet } = this.state
@@ -70,6 +97,13 @@ class SnippetTab extends React.Component {
onSnippetDeleted={this.handleDeleteSnippet.bind(this)} onSnippetDeleted={this.handleDeleteSnippet.bind(this)}
currentSnippet={currentSnippet} /> currentSnippet={currentSnippet} />
<div styleName='snippet-detail' style={{visibility: currentSnippet ? 'visible' : 'hidden'}}> <div styleName='snippet-detail' style={{visibility: currentSnippet ? 'visible' : 'hidden'}}>
<div styleName='group-section'>
<div styleName='group-section-control'>
<button styleName='group-control-rightButton'
onClick={e => this.handleCopySnippet(e)}>{i18n.__('Copy')}
</button>
</div>
</div>
<div styleName='group-section'> <div styleName='group-section'>
<div styleName='group-section-label'>{i18n.__('Snippet name')}</div> <div styleName='group-section-label'>{i18n.__('Snippet name')}</div>
<div styleName='group-section-control'> <div styleName='group-section-control'>

View File

@@ -196,3 +196,19 @@ body[data-theme="monokai"]
color white color white
.group-control-button .group-control-button
colorMonokaiPrimaryButton() colorMonokaiPrimaryButton()
body[data-theme="dracula"]
.snippets
background $ui-dracula-backgroundColor
.snippet-item
color #f8f8f2
&::after
background $ui-dracula-borderColor
&:hover
background darken($ui-dracula-backgroundColor, 5)
.snippet-item-selected
background darken($ui-dracula-backgroundColor, 5)
.snippet-detail
color #f8f8f2
.group-control-button
colorDraculaPrimaryButton()

View File

@@ -9,13 +9,17 @@
box-sizing border-box box-sizing border-box
border-bottom $default-border border-bottom $default-border
margin-bottom 5px margin-bottom 5px
display flex
.header-label .header-label
float left
cursor pointer cursor pointer
&:hover &:hover
.header-label-editButton .header-label-editButton
opacity 1 opacity 1
flex 1
white-space nowrap
text-overflow ellipsis
overflow hidden
.header-label-path .header-label-path
color $ui-inactive-text-color color $ui-inactive-text-color
@@ -38,8 +42,8 @@
outline none outline none
.header-control .header-control
float right -webkit-box-flex: 1
white-space nowrap
.header-control-button .header-control-button
width 30px width 30px
height 25px height 25px

View File

@@ -70,7 +70,7 @@ class StoragesTab extends React.Component {
}) })
return ( return (
<div styleName='list'> <div styleName='list'>
<div styleName='header'>{i18n.__('Storages')}</div> <div styleName='header'>{i18n.__('Storage Locations')}</div>
{storageList.length > 0 {storageList.length > 0
? storageList ? storageList
: <div styleName='list-empty'>{i18n.__('No storage found.')}</div> : <div styleName='list-empty'>{i18n.__('No storage found.')}</div>

View File

@@ -158,7 +158,7 @@ body[data-theme="dark"]
.addStorage-body-control-cancelButton .addStorage-body-control-cancelButton
colorDarkDefaultButton() colorDarkDefaultButton()
border-color $ui-dark-borderColor border-color $ui-dark-borderColor
body[data-theme="solarized-dark"] body[data-theme="solarized-dark"]
@@ -236,3 +236,41 @@ body[data-theme="monokai"]
.addStorage-body-control-cancelButton .addStorage-body-control-cancelButton
colorDarkDefaultButton() colorDarkDefaultButton()
border-color $ui-monokai-borderColor border-color $ui-monokai-borderColor
body[data-theme="dracula"]
.root
color $ui-dracula-text-color
.folderList-item
border-bottom $ui-dracula-borderColor
.folderList-empty
color $ui-dracula-text-color
.list-empty
color $ui-dracula-text-color
.list-control-addStorageButton
border-color $ui-dracula-button-backgroundColor
background-color $ui-dracula-button-backgroundColor
color $ui-dracula-text-color
.addStorage-header
color $ui-dracula-text-color
border-color $ui-dracula-borderColor
.addStorage-body-section-name-input
border-color $$ui-dracula-borderColor
.addStorage-body-section-type-description
color $ui-dracula-text-color
.addStorage-body-section-path-button
colorPrimaryButton()
.addStorage-body-control
border-color $ui-dracula-borderColor
.addStorage-body-control-createButton
colorDarkPrimaryButton()
.addStorage-body-control-cancelButton
colorDarkDefaultButton()
border-color $ui-dracula-borderColor

View File

@@ -40,7 +40,7 @@ class UiTab extends React.Component {
this.handleSettingError = (err) => { this.handleSettingError = (err) => {
this.setState({UiAlert: { this.setState({UiAlert: {
type: 'error', type: 'error',
message: err.message != null ? err.message : i18n.__('Error occurs!') message: err.message != null ? err.message : i18n.__('An error occurred!')
}}) }})
} }
ipc.addListener('APP_SETTING_DONE', this.handleSettingDone) ipc.addListener('APP_SETTING_DONE', this.handleSettingDone)
@@ -67,6 +67,7 @@ class UiTab extends React.Component {
ui: { ui: {
theme: this.refs.uiTheme.value, theme: this.refs.uiTheme.value,
language: this.refs.uiLanguage.value, language: this.refs.uiLanguage.value,
defaultNote: this.refs.defaultNote.value,
showCopyNotification: this.refs.showCopyNotification.checked, showCopyNotification: this.refs.showCopyNotification.checked,
confirmDeletion: this.refs.confirmDeletion.checked, confirmDeletion: this.refs.confirmDeletion.checked,
showOnlyRelatedTags: this.refs.showOnlyRelatedTags.checked, showOnlyRelatedTags: this.refs.showOnlyRelatedTags.checked,
@@ -87,7 +88,10 @@ class UiTab extends React.Component {
keyMap: this.refs.editorKeyMap.value, keyMap: this.refs.editorKeyMap.value,
snippetDefaultLanguage: this.refs.editorSnippetDefaultLanguage.value, snippetDefaultLanguage: this.refs.editorSnippetDefaultLanguage.value,
scrollPastEnd: this.refs.scrollPastEnd.checked, scrollPastEnd: this.refs.scrollPastEnd.checked,
fetchUrlTitle: this.refs.editorFetchUrlTitle.checked fetchUrlTitle: this.refs.editorFetchUrlTitle.checked,
enableTableEditor: this.refs.enableTableEditor.checked,
enableFrontMatterTitle: this.refs.enableFrontMatterTitle.checked,
frontMatterTitleField: this.refs.frontMatterTitleField.value
}, },
preview: { preview: {
fontSize: this.refs.previewFontSize.value, fontSize: this.refs.previewFontSize.value,
@@ -100,11 +104,13 @@ class UiTab extends React.Component {
latexBlockClose: this.refs.previewLatexBlockClose.value, latexBlockClose: this.refs.previewLatexBlockClose.value,
plantUMLServerAddress: this.refs.previewPlantUMLServerAddress.value, plantUMLServerAddress: this.refs.previewPlantUMLServerAddress.value,
scrollPastEnd: this.refs.previewScrollPastEnd.checked, scrollPastEnd: this.refs.previewScrollPastEnd.checked,
scrollSync: this.refs.previewScrollSync.checked,
smartQuotes: this.refs.previewSmartQuotes.checked, smartQuotes: this.refs.previewSmartQuotes.checked,
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,
allowCustomCSS: this.refs.previewAllowCustomCSS.checked, allowCustomCSS: this.refs.previewAllowCustomCSS.checked,
lineThroughCheckbox: this.refs.lineThroughCheckbox.checked,
customCSS: this.customCSSCM.getCodeMirror().getValue() customCSS: this.customCSSCM.getCodeMirror().getValue()
} }
} }
@@ -123,7 +129,7 @@ class UiTab extends React.Component {
this.props.haveToSave({ this.props.haveToSave({
tab: 'UI', tab: 'UI',
type: 'warning', type: 'warning',
message: i18n.__('You have to save!') message: i18n.__('Unsaved Changes!')
}) })
} }
}) })
@@ -173,7 +179,9 @@ class UiTab extends React.Component {
<div styleName='group-header'>{i18n.__('Interface')}</div> <div styleName='group-header'>{i18n.__('Interface')}</div>
<div styleName='group-section'> <div styleName='group-section'>
{i18n.__('Interface Theme')} <div styleName='group-section-label'>
{i18n.__('Interface Theme')}
</div>
<div styleName='group-section-control'> <div styleName='group-section-control'>
<select value={config.ui.theme} <select value={config.ui.theme}
onChange={(e) => this.handleUIChange(e)} onChange={(e) => this.handleUIChange(e)}
@@ -183,13 +191,16 @@ class UiTab extends React.Component {
<option value='white'>{i18n.__('White')}</option> <option value='white'>{i18n.__('White')}</option>
<option value='solarized-dark'>{i18n.__('Solarized Dark')}</option> <option value='solarized-dark'>{i18n.__('Solarized Dark')}</option>
<option value='monokai'>{i18n.__('Monokai')}</option> <option value='monokai'>{i18n.__('Monokai')}</option>
<option value='dracula'>{i18n.__('Dracula')}</option>
<option value='dark'>{i18n.__('Dark')}</option> <option value='dark'>{i18n.__('Dark')}</option>
</select> </select>
</div> </div>
</div> </div>
<div styleName='group-section'> <div styleName='group-section'>
{i18n.__('Language')} <div styleName='group-section-label'>
{i18n.__('Language')}
</div>
<div styleName='group-section-control'> <div styleName='group-section-control'>
<select value={config.ui.language} <select value={config.ui.language}
onChange={(e) => this.handleUIChange(e)} onChange={(e) => this.handleUIChange(e)}
@@ -202,6 +213,22 @@ class UiTab extends React.Component {
</div> </div>
</div> </div>
<div styleName='group-section'>
<div styleName='group-section-label'>
{i18n.__('Default New Note')}
</div>
<div styleName='group-section-control'>
<select value={config.ui.defaultNote}
onChange={(e) => this.handleUIChange(e)}
ref='defaultNote'
>
<option value='ALWAYS_ASK'>{i18n.__('Always Ask')}</option>
<option value='MARKDOWN_NOTE'>{i18n.__('Markdown Note')}</option>
<option value='SNIPPET_NOTE'>{i18n.__('Snippet Note')}</option>
</select>
</div>
</div>
<div styleName='group-checkBoxSection'> <div styleName='group-checkBoxSection'>
<label> <label>
<input onChange={(e) => this.handleUIChange(e)} <input onChange={(e) => this.handleUIChange(e)}
@@ -404,6 +431,31 @@ class UiTab extends React.Component {
</div> </div>
</div> </div>
<div styleName='group-section'>
<div styleName='group-section-label'>
{i18n.__('Front matter title field')}
</div>
<div styleName='group-section-control'>
<input styleName='group-section-control-input'
ref='frontMatterTitleField'
value={config.editor.frontMatterTitleField}
onChange={(e) => this.handleUIChange(e)}
type='text'
/>
</div>
</div>
<div styleName='group-checkBoxSection'>
<label>
<input onChange={(e) => this.handleUIChange(e)}
checked={this.state.config.editor.enableFrontMatterTitle}
ref='enableFrontMatterTitle'
type='checkbox'
/>&nbsp;
{i18n.__('Extract title from front matter')}
</label>
</div>
<div styleName='group-checkBoxSection'> <div styleName='group-checkBoxSection'>
<label> <label>
<input onChange={(e) => this.handleUIChange(e)} <input onChange={(e) => this.handleUIChange(e)}
@@ -437,6 +489,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.enableTableEditor}
ref='enableTableEditor'
type='checkbox'
/>&nbsp;
{i18n.__('Enable smart table editor')}
</label>
</div>
<div styleName='group-header2'>{i18n.__('Preview')}</div> <div styleName='group-header2'>{i18n.__('Preview')}</div>
<div styleName='group-section'> <div styleName='group-section'>
<div styleName='group-section-label'> <div styleName='group-section-label'>
@@ -465,7 +528,7 @@ class UiTab extends React.Component {
</div> </div>
</div> </div>
<div styleName='group-section'> <div styleName='group-section'>
<div styleName='group-section-label'>{i18n.__('Code block Theme')}</div> <div styleName='group-section-label'>{i18n.__('Code Block Theme')}</div>
<div styleName='group-section-control'> <div styleName='group-section-control'>
<select value={config.preview.codeBlockTheme} <select value={config.preview.codeBlockTheme}
ref='previewCodeBlockTheme' ref='previewCodeBlockTheme'
@@ -479,6 +542,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.lineThroughCheckbox}
ref='lineThroughCheckbox'
type='checkbox'
/>&nbsp;
{i18n.__('Allow line through checkbox')}
</label>
</div>
<div styleName='group-checkBoxSection'> <div styleName='group-checkBoxSection'>
<label> <label>
<input onChange={(e) => this.handleUIChange(e)} <input onChange={(e) => this.handleUIChange(e)}
@@ -489,6 +562,16 @@ class UiTab extends React.Component {
{i18n.__('Allow preview to scroll past the last line')} {i18n.__('Allow preview to scroll past the last line')}
</label> </label>
</div> </div>
<div styleName='group-checkBoxSection'>
<label>
<input onChange={(e) => this.handleUIChange(e)}
checked={this.state.config.preview.scrollSync}
ref='previewScrollSync'
type='checkbox'
/>&nbsp;
{i18n.__('When scrolling, synchronize preview with editor')}
</label>
</div>
<div styleName='group-checkBoxSection'> <div styleName='group-checkBoxSection'>
<label> <label>
<input onChange={(e) => this.handleUIChange(e)} <input onChange={(e) => this.handleUIChange(e)}

View File

@@ -216,16 +216,10 @@ function data (state = defaultDataMap(), action) {
return state return state
} }
case 'UPDATE_FOLDER': case 'UPDATE_FOLDER':
state = Object.assign({}, state)
state.storageMap = new Map(state.storageMap)
state.storageMap.set(action.storage.key, action.storage)
return state
case 'REORDER_FOLDER': case 'REORDER_FOLDER':
state = Object.assign({}, state)
state.storageMap = new Map(state.storageMap)
state.storageMap.set(action.storage.key, action.storage)
return state
case 'EXPORT_FOLDER': case 'EXPORT_FOLDER':
case 'RENAME_STORAGE':
case 'EXPORT_STORAGE':
state = Object.assign({}, state) state = Object.assign({}, state)
state.storageMap = new Map(state.storageMap) state.storageMap = new Map(state.storageMap)
state.storageMap.set(action.storage.key, action.storage) state.storageMap.set(action.storage.key, action.storage)
@@ -355,11 +349,6 @@ function data (state = defaultDataMap(), action) {
}) })
} }
return state return state
case 'RENAME_STORAGE':
state = Object.assign({}, state)
state.storageMap = new Map(state.storageMap)
state.storageMap.set(action.storage.key, action.storage)
return state
case 'EXPAND_STORAGE': case 'EXPAND_STORAGE':
state = Object.assign({}, state) state = Object.assign({}, state)
state.storageMap = new Map(state.storageMap) state.storageMap = new Map(state.storageMap)

View File

@@ -0,0 +1,126 @@
.TagSelect
.react-autosuggest__input
box-sizing border-box
border none
background-color transparent
outline none
padding 0 4px
font-size 13px
ul
position fixed
z-index 999
box-sizing border-box
list-style none
padding 0
margin 0
border-radius 4px
margin .5rem 0 0
background-color $ui-noteList-backgroundColor
border 1px solid rgba(0,0,0,.3)
box-shadow .05em .2em .6em rgba(0,0,0,.2)
text-shadow none
&:empty,
&[hidden]
display none
&:before
content ""
position absolute
top -7px
left 14px
width 0 height 0
padding 6px
background-color $ui-noteList-backgroundColor
border inherit
border-right 0
border-bottom 0
-webkit-transform rotate(45deg)
transform rotate(45deg)
li
position relative
padding 6px 18px 6px 10px
cursor pointer
li[aria-selected="true"]
background-color alpha($ui-button--active-backgroundColor, 40%)
color $ui-text-color
body[data-theme="dark"]
.TagSelect
.react-autosuggest__input
color $ui-dark-text-color
ul
border-color $ui-dark-borderColor
background-color $ui-dark-noteList-backgroundColor
color $ui-dark-text-color
&:before
background-color $ui-dark-noteList-backgroundColor
li[aria-selected="true"]
background-color $ui-dark-button--active-backgroundColor
color $ui-dark-text-color
body[data-theme="monokai"]
.TagSelect
.react-autosuggest__input
color $ui-monokai-text-color
ul
border-color $ui-monokai-borderColor
background-color $ui-monokai-noteList-backgroundColor
color $ui-monokai-text-color
&:before
background-color $ui-dark-noteList-backgroundColor
li[aria-selected="true"]
background-color $ui-monokai-button-backgroundColor
color $ui-monokai-text-color
body[data-theme="dracula"]
.TagSelect
.react-autosuggest__input
color $ui-dracula-text-color
ul
border-color $ui-dracula-borderColor
background-color $ui-dracula-noteList-backgroundColor
color $ui-dracula-text-color
&:before
background-color $ui-dark-noteList-backgroundColor
li[aria-selected="true"]
background-color $ui-dracula-button-backgroundColor
color $ui-dracula-text-color
body[data-theme="solarized-dark"]
.TagSelect
.react-autosuggest__input
color $ui-solarized-dark-text-color
ul
border-color $ui-solarized-dark-borderColor
background-color $ui-solarized-dark-noteList-backgroundColor
color $ui-solarized-dark-text-color
&:before
background-color $ui-solarized-dark-noteList-backgroundColor
li[aria-selected="true"]
background-color $ui-dark-button--active-backgroundColor
color $ui-solarized-dark-text-color
body[data-theme="white"]
.TagSelect
ul
background-color $ui-white-noteList-backgroundColor
li[aria-selected="true"]
background-color $ui-button--active-backgroundColor

View File

@@ -128,6 +128,16 @@ colorMonokaiPrimaryButton()
&:active:hover &:active:hover
background-color $dark-primary-button-background--active background-color $dark-primary-button-background--active
colorDraculaPrimaryButton()
color $ui-dracula-text-color
background-color $ui-dracula-button-backgroundColor
border none
&:hover
background-color $ui-dracula-button--active-backgroundColor
&:active
&:active:hover
background-color $ui-dracula-button--active-backgroundColor
// Danger button(Brand color) // Danger button(Brand color)
$danger-button-background = #c9302c $danger-button-background = #c9302c
@@ -369,7 +379,7 @@ $ui-monokai-active-color = #f92672
$ui-monokai-borderColor = #373831 $ui-monokai-borderColor = #373831
$ui-monokai-tag-backgroundColor = #f92672 $ui-monokai-tag-backgroundColor = #373831
$ui-monokai-button-backgroundColor = #373831 $ui-monokai-button-backgroundColor = #373831
$ui-monokai-button--active-color = white $ui-monokai-button--active-color = white
@@ -383,4 +393,30 @@ modalMonokai()
width 100% width 100%
background-color $ui-monokai-backgroundColor background-color $ui-monokai-backgroundColor
overflow hidden overflow hidden
border-radius $modal-border-radius
/******* Dracula theme ********/
$ui-dracula-backgroundColor = #282a36
$ui-dracula-noteList-backgroundColor = #282a36
$ui-dracula-noteDetail-backgroundColor = #282a36
$ui-dracula-text-color = #f8f8f2
$ui-dracula-active-color = #bd93f9
$ui-dracula-borderColor = #44475a
$ui-dracula-tag-backgroundColor = #8be9fd
$ui-dracula-button-backgroundColor = #44475a
$ui-dracula-button--active-color = #f8f8f2
$ui-dracula-button--active-backgroundColor = #bd93f9
$ui-dracula-button--hover-backgroundColor = lighten($ui-dracula-backgroundColor, 10%)
$ui-dracula-button--focus-borderColor = lighten(#44475a, 25%)
modalDracula()
position relative
z-index $modal-z-index
width 100%
background-color $ui-dracula-backgroundColor
overflow hidden
border-radius $modal-border-radius border-radius $modal-border-radius

View File

@@ -1,18 +1,18 @@
# Contributing to Boostnote (English) # Contributing to Boostnote (English)
### When you open an issue of a bug report ### When you open an issue or a bug report
There are no issue template. But there is a request. There is no issue template, but there is a request.
**Please paste screenshots of Boostnote with developer tool open** **Please paste screenshots of Boostnote with the developer tool open**
Thank you for your help in advance. Thank you in advance for your help.
### About copyright of Pull Request ### Concerning Copyright
If you make a pull request, It means you agree to transfer the copyright of the code changes to BoostIO. By making a pull request you agree to transfer ownership of your code to BoostIO.
It doesn't mean Boostnote will become a paid app. If we want to earn some money, We will try other way, which is some kind of cloud storage, Mobile app integration or some SPECIAL features. This doesn't mean Boostnote will become a paid app. If we want to earn money, we will find other way. Potentially some kind of cloud storage, mobile app integration, or some premium features.
Because GPL v3 is too strict to be compatible with any other License, We thought this is needed to replace the license with much freer one(like BSD, MIT) somewhen. GPL v3 is too strict to be compatible with another license, so we thought it might be necessary to replace the license with a more open one (like BSD, MIT) eventually.
--- ---
@@ -86,4 +86,23 @@ Pull requestをすることはその変化分のコードの著作権をBoostIO
如果您提供了一个Pull Request这表示您将您所修改的代码的著作权移交给BoostIO。 如果您提供了一个Pull Request这表示您将您所修改的代码的著作权移交给BoostIO。
这并不表示Boostnote会成为一个需要付费的软件。如果我们想获得收益我们会尝试一些其他的方法比如说云存储、绑定手机软件等。 这并不表示Boostnote会成为一个需要付费的软件。如果我们想获得收益我们会尝试一些其他的方法比如说云存储、绑定手机软件等。
因为GPLv3过于严格不能和其他的一些协议兼容所以我们有可能在将来会把BoostNote的协议改为一些较为宽松的协议比如说BSD、MIT。 因为GPLv3过于严格不能和其他的一些协议兼容所以我们有可能在将来会把BoostNote的协议改为一些较为宽松的协议比如说BSD、MIT。
---
# Contributing to Boostnote (Français)
### Lorsque vous signalez un problème ou un bug
Il n'y a pas de modèle pour un signaler problème. Mais nous vous demandons :
**Merci de founir une capture d'écran de Boostnote avec l'outil de développement ouvert**
(vous pouvez l'ouvrir avec `Ctrl+Shift+I`)
Merci en avance pour votre aide.
### À propos des droits d'auteurs et des requêtes (`Pull Request`)
Si vous faites une requête, vous acceptez de transmettre les modifications du code à BoostIO.
Cela ne veut pas dire que Boostnote deviendra une application payante. Si nous voulons gagner de l'argent, nous trouverons un autre moyen, comme un service de sauvegarde sur le Cloud, une application mobile ou des options payantes.
Puisque GPL v3 est trop strict pour être compatible avec n'importe quelle autre licence, nous pensons avoir un jour besoin de la remplacer avec une licence bien plus libre (comme BSD, MIT).

View File

@@ -0,0 +1,130 @@
(function (mod) {
if (typeof exports === 'object' && typeof module === 'object') { // Common JS
mod(require('../codemirror/lib/codemirror'))
} else if (typeof define === 'function' && define.amd) { // AMD
define(['../codemirror/lib/codemirror'], mod)
} else { // Plain browser env
mod(CodeMirror)
}
})(function (CodeMirror) {
'use strict'
const shell = require('electron').shell
const yOffset = 2
const macOS = global.process.platform === 'darwin'
const modifier = macOS ? 'metaKey' : 'ctrlKey'
class HyperLink {
constructor(cm) {
this.cm = cm
this.lineDiv = cm.display.lineDiv
this.onMouseDown = this.onMouseDown.bind(this)
this.onMouseEnter = this.onMouseEnter.bind(this)
this.onMouseLeave = this.onMouseLeave.bind(this)
this.onMouseMove = this.onMouseMove.bind(this)
this.tooltip = document.createElement('div')
this.tooltipContent = document.createElement('div')
this.tooltipIndicator = document.createElement('div')
this.tooltip.setAttribute('class', 'CodeMirror-hover CodeMirror-matchingbracket CodeMirror-selected')
this.tooltip.setAttribute('cm-ignore-events', 'true')
this.tooltip.appendChild(this.tooltipContent)
this.tooltip.appendChild(this.tooltipIndicator)
this.tooltipContent.textContent = `${macOS ? 'Cmd(⌘)' : 'Ctrl(^)'} + click to follow link`
this.lineDiv.addEventListener('mousedown', this.onMouseDown)
this.lineDiv.addEventListener('mouseenter', this.onMouseEnter, {
capture: true,
passive: true
})
this.lineDiv.addEventListener('mouseleave', this.onMouseLeave, {
capture: true,
passive: true
})
this.lineDiv.addEventListener('mousemove', this.onMouseMove, {
passive: true
})
}
getUrl(el) {
const className = el.className.split(' ')
if (className.indexOf('cm-url') !== -1) {
const match = /^\((.*)\)|\[(.*)\]|(.*)$/.exec(el.textContent)
const url = match[1] || match[2] || match[3]
// `:storage` is the value of the variable `STORAGE_FOLDER_PLACEHOLDER` defined in `browser/main/lib/dataApi/attachmentManagement`
return /^:storage(?:\/|%5C)/.test(url) ? null : url
}
return null
}
onMouseDown(e) {
const { target } = e
if (!e[modifier]) {
return
}
const url = this.getUrl(target)
if (url) {
e.preventDefault()
shell.openExternal(url)
}
}
onMouseEnter(e) {
const { target } = e
const url = this.getUrl(target)
if (url) {
if (e[modifier]) {
target.classList.add('CodeMirror-activeline-background', 'CodeMirror-hyperlink')
}
else {
target.classList.add('CodeMirror-activeline-background')
}
this.showInfo(target)
}
}
onMouseLeave(e) {
if (this.tooltip.parentElement === this.lineDiv) {
e.target.classList.remove('CodeMirror-activeline-background', 'CodeMirror-hyperlink')
this.lineDiv.removeChild(this.tooltip)
}
}
onMouseMove(e) {
if (this.tooltip.parentElement === this.lineDiv) {
if (e[modifier]) {
e.target.classList.add('CodeMirror-hyperlink')
}
else {
e.target.classList.remove('CodeMirror-hyperlink')
}
}
}
showInfo(relatedTo) {
const b1 = relatedTo.getBoundingClientRect()
const b2 = this.lineDiv.getBoundingClientRect()
const tdiv = this.tooltip
tdiv.style.left = (b1.left - b2.left) + 'px'
this.lineDiv.appendChild(tdiv)
const b3 = tdiv.getBoundingClientRect()
const top = b1.top - b2.top - b3.height - yOffset
if (top < 0) {
tdiv.style.top = (b1.top - b2.top + b1.height + yOffset) + 'px'
}
else {
tdiv.style.top = top + 'px'
}
}
}
CodeMirror.defineOption('hyperlink', true, (cm) => {
const addon = new HyperLink(cm)
})
})

View File

@@ -0,0 +1,45 @@
.cm-table-row-even { background-color: rgb(242, 242, 242); }
.cm-s-3024-day.CodeMirror .cm-table-row-even { background-color: rgb(238, 237, 237); }
.cm-s-3024-night.CodeMirror .cm-table-row-even { background-color: rgb(30, 24, 21); }
.cm-s-abcdef.CodeMirror .cm-table-row-even { background-color: rgb(36, 39, 37); }
.cm-s-ambiance.CodeMirror .cm-table-row-even { background-color: rgb(242, 242, 242); }
.cm-s-base16-dark.CodeMirror .cm-table-row-even { background-color: rgb(41, 41, 41); }
.cm-s-base16-light.CodeMirror .cm-table-row-even { background-color: rgb(234, 234, 234); }
.cm-s-bespin.CodeMirror .cm-table-row-even { background-color: rgb(52, 45, 40); }
.cm-s-blackboard.CodeMirror .cm-table-row-even { background-color: rgb(36, 39, 55); }
.cm-s-cobalt.CodeMirror .cm-table-row-even { background-color: rgb(26, 56, 83); }
.cm-s-colorforth.CodeMirror .cm-table-row-even { background-color: rgb(25, 25, 25); }
.cm-s-darcula.CodeMirror .cm-table-row-even { background-color: rgb(56, 57, 59); }
.cm-s-dracula.CodeMirror .cm-table-row-even { background-color: rgb(61, 63, 73); }
.cm-s-duotone-dark.CodeMirror .cm-table-row-even { background-color: rgb(49, 45, 60); }
.cm-s-duotone-light.CodeMirror .cm-table-row-even { background-color: rgb(246, 243, 238); }
.cm-s-erlang-dark.CodeMirror .cm-table-row-even { background-color: rgb(26, 56, 83); }
.cm-s-gruvbox-dark.CodeMirror .cm-table-row-even { background-color: rgb(55, 53, 51); }
.cm-s-hopscotch.CodeMirror .cm-table-row-even { background-color: rgb(66, 58, 65); }
.cm-s-isotope.CodeMirror .cm-table-row-even { background-color: rgb(22, 22, 22); }
.cm-s-lesser-dark.CodeMirror .cm-table-row-even { background-color: rgb(58, 58, 57); }
.cm-s-liquibyte.CodeMirror .cm-table-row-even { background-color: rgb(26, 26, 26); }
.cm-s-lucario.CodeMirror .cm-table-row-even { background-color: rgb(64, 81, 96); }
.cm-s-material.CodeMirror .cm-table-row-even { background-color: rgb(58, 69, 74); }
.cm-s-mbo.CodeMirror .cm-table-row-even { background-color: rgb(65, 65, 63); }
.cm-s-midnight.CodeMirror .cm-table-row-even { background-color: rgb(34, 46, 63); }
.cm-s-monokai.CodeMirror .cm-table-row-even { background-color: rgb(60, 61, 55); }
.cm-s-neo.CodeMirror .cm-table-row-even { background-color: rgb(245, 245, 245); }
.cm-s-night.CodeMirror .cm-table-row-even { background-color: rgb(34, 25, 53); }
.cm-s-oceanic-next.CodeMirror .cm-table-row-even { background-color: rgb(68, 83, 89); }
.cm-s-paraiso-dark.CodeMirror .cm-table-row-even { background-color: rgb(61, 45, 59); }
.cm-s-paraiso-light.CodeMirror .cm-table-row-even { background-color: rgb(223, 224, 211); }
.cm-s-pastel-on-dark.CodeMirror .cm-table-row-even { background-color: rgb(54, 51, 49); }
.cm-s-railscasts.CodeMirror .cm-table-row-even { background-color: rgb(63, 63, 62); }
.cm-s-rubyblue.CodeMirror .cm-table-row-even { background-color: rgb(41, 58, 73); }
.cm-s-seti.CodeMirror .cm-table-row-even { background-color: rgb(40, 42, 43); }
.cm-s-shadowfox.CodeMirror .cm-table-row-even { background-color: rgb(56, 56, 59); }
.cm-s-the-matrix.CodeMirror .cm-table-row-even { background-color: rgb(0, 26, 0); }
.cm-s-tomorrow-night-bright.CodeMirror .cm-table-row-even { background-color: rgb(23, 23, 23); }
.cm-s-tomorrow-night-eighties.CodeMirror .cm-table-row-even { background-color: rgb(20, 20, 20); }
.cm-s-twilight.CodeMirror .cm-table-row-even { background-color: rgb(43, 43, 43); }
.cm-s-vibrant-ink.CodeMirror .cm-table-row-even { background-color: rgb(26, 26, 26); }
.cm-s-xq-dark.CodeMirror .cm-table-row-even { background-color: rgb(34, 25, 53); }
.cm-s-yeti.CodeMirror .cm-table-row-even { background-color: rgb(235, 232, 230); }
.cm-s-solarized.cm-s-dark .cm-table-row-even { background-color: rgb(13, 54, 64); }
.cm-s-solarized.cm-s-light .cm-table-row-even { background-color: rgb(245, 240, 222); }

View File

@@ -0,0 +1,74 @@
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../codemirror/lib/codemirror"), require("../codemirror/mode/gfm/gfm"))
else if (typeof define == "function" && define.amd) // AMD
define(["../codemirror/lib/codemirror", "../codemirror/mode/gfm/gfm"], mod)
else // Plain browser env
mod(CodeMirror)
})(function(CodeMirror) {
'use strict'
CodeMirror.defineMode('bfm', function(config, gfmConfig) {
const bfmOverlay = {
startState() {
return {
inTable: false,
rowIndex: 0
}
},
copyState(s) {
return {
inTable: s.inTable,
rowIndex: s.rowIndex
}
},
token(stream, state) {
state.combineTokens = true
if (state.inTable) {
if (stream.match(/^\|/)) {
++state.rowIndex
stream.skipToEnd()
if (state.rowIndex === 1) {
return 'table table-separator'
} else if (state.rowIndex % 2 === 0) {
return 'table table-row table-row-even'
} else {
return 'table table-row table-row-odd'
}
} else {
state.inTable = false
stream.skipToEnd()
return null
}
} else if (stream.match(/^\|/)) {
state.inTable = true
state.rowIndex = 0
stream.skipToEnd()
return 'table table-header'
}
stream.skipToEnd()
return null
},
blankLine(state) {
state.inTable = false
}
}
gfmConfig.name = 'gfm'
return CodeMirror.overlayMode(CodeMirror.getMode(config, gfmConfig), bfmOverlay)
})
CodeMirror.defineMIME('text/x-bfm', 'bfm')
CodeMirror.modeInfo.push({
name: "Boost Flavored Markdown",
mime: "text/x-bfm",
mode: "bfm"
})
})

View File

@@ -1,3 +1,4 @@
const fs = require('fs')
const path = require('path') const path = require('path')
const ChildProcess = require('child_process') const ChildProcess = require('child_process')
const packager = require('electron-packager') const packager = require('electron-packager')
@@ -284,5 +285,61 @@ module.exports = function (grunt) {
} }
}) })
grunt.registerTask('bfm', function () {
const Color = require('color')
const parseCSS = require('css').parse
function generateRule (selector, bgColor, fgColor) {
if (bgColor.isLight()) {
bgColor = bgColor.mix(fgColor, 0.05)
} else {
bgColor = bgColor.mix(fgColor, 0.1)
}
if (selector && selector.length > 0) {
return `${selector} .cm-table-row-even { background-color: ${bgColor.rgb().string()}; }`
} else {
return `.cm-table-row-even { background-color: ${bgColor.rgb().string()}; }`
}
}
const root = path.join(__dirname, 'node_modules/codemirror/theme/')
const colors = fs.readdirSync(root).filter(file => file !== 'solarized.css').map(file => {
const css = parseCSS(fs.readFileSync(path.join(root, file), 'utf8'))
const rules = css.stylesheet.rules.filter(rule => rule.selectors && /\b\.CodeMirror$/.test(rule.selectors[0]))
if (rules.length === 1) {
let bgColor = Color('white')
let fgColor = Color('black')
rules[0].declarations.forEach(declaration => {
if (declaration.property === 'background-color' || declaration.property === 'background') {
bgColor = Color(declaration.value.split(' ')[0])
} else if (declaration.property === 'color') {
const value = /^(.*?)(?:\s*!important)?$/.exec(declaration.value)[1]
const match = /^rgba\((.*?),\s*1\)$/.exec(value)
if (match) {
fgColor = Color(`rgb(${match[1]})`)
} else {
fgColor = Color(value)
}
}
})
return generateRule(rules[0].selectors[0], bgColor, fgColor)
}
}).filter(value => !!value)
// default
colors.unshift(generateRule(null, Color('white'), Color('black')))
// solarized dark
colors.push(generateRule('.cm-s-solarized.cm-s-dark', Color('#002b36'), Color('#839496')))
// solarized light
colors.push(generateRule('.cm-s-solarized.cm-s-light', Color('#fdf6e3'), Color('#657b83')))
fs.writeFileSync(path.join(__dirname, 'extra_scripts/codemirror/mode/bfm/bfm.css'), colors.join('\n'), 'utf8')
})
grunt.registerTask('default', ['build']) grunt.registerTask('default', ['build'])
} }

View File

@@ -78,9 +78,11 @@ app.on('ready', function () {
var template = require('./main-menu') var template = require('./main-menu')
var menu = Menu.buildFromTemplate(template) var menu = Menu.buildFromTemplate(template)
var touchBarMenu = require('./touchbar-menu')
switch (process.platform) { switch (process.platform) {
case 'darwin': case 'darwin':
Menu.setApplicationMenu(menu) Menu.setApplicationMenu(menu)
mainWindow.setTouchBar(touchBarMenu)
break break
case 'win32': case 'win32':
mainWindow.setMenu(menu) mainWindow.setMenu(menu)

View File

@@ -145,6 +145,16 @@ const file = {
{ {
type: 'separator' type: 'separator'
}, },
{
label: 'Generate/Update Markdown TOC',
accelerator: 'Shift+Ctrl+T',
click () {
mainWindow.webContents.send('code:generate-toc')
}
},
{
type: 'separator'
},
{ {
label: 'Print', label: 'Print',
accelerator: 'CommandOrControl+P', accelerator: 'CommandOrControl+P',

View File

@@ -10,6 +10,8 @@
<link rel="stylesheet" href="../node_modules/codemirror/lib/codemirror.css"> <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/katex/dist/katex.min.css">
<link rel="stylesheet" href="../node_modules/codemirror/addon/dialog/dialog.css"> <link rel="stylesheet" href="../node_modules/codemirror/addon/dialog/dialog.css">
<link rel="stylesheet" href="../extra_scripts/codemirror/mode/bfm/bfm.css">
<title>Boostnote</title> <title>Boostnote</title>
<style> <style>
@@ -94,8 +96,13 @@
<script src="../node_modules/codemirror/keymap/emacs.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/runmode/runmode.js"></script>
<script src="../node_modules/codemirror/addon/display/panel.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="../extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js"></script> <script src="../extra_scripts/boost/boostNewLineIndentContinueMarkdownList.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>

41
lib/touchbar-menu.js Normal file
View File

@@ -0,0 +1,41 @@
const {TouchBar} = require('electron')
const {TouchBarButton, TouchBarSpacer} = TouchBar
const mainWindow = require('./main-window')
const allNotes = new TouchBarButton({
label: '📒',
click: () => {
mainWindow.webContents.send('list:navigate', '/home')
}
})
const starredNotes = new TouchBarButton({
label: '⭐️',
click: () => {
mainWindow.webContents.send('list:navigate', '/starred')
}
})
const trash = new TouchBarButton({
label: '🗑',
click: () => {
mainWindow.webContents.send('list:navigate', '/trashed')
}
})
const newNote = new TouchBarButton({
label: '✎',
click: () => {
mainWindow.webContents.send('list:navigate', '/home')
mainWindow.webContents.send('top:new-note')
}
})
module.exports = new TouchBar([
allNotes,
starredNotes,
trash,
new TouchBarSpacer({size: 'small'}),
newNote
])

View File

@@ -20,7 +20,7 @@
".html": ".html", ".html": ".html",
"Print": "Print", "Print": "Print",
"Your preferences for Boostnote": "Your preferences for Boostnote", "Your preferences for Boostnote": "Your preferences for Boostnote",
"Storages": "Storages", "Storage Locations": "Storage Locations",
"Add Storage Location": "Add Storage Location", "Add Storage Location": "Add Storage Location",
"Add Folder": "Add Folder", "Add Folder": "Add Folder",
"Open Storage folder": "Open Storage folder", "Open Storage folder": "Open Storage folder",
@@ -55,7 +55,7 @@
"Preview": "Preview", "Preview": "Preview",
"Preview Font Size": "Preview Font Size", "Preview Font Size": "Preview Font Size",
"Preview Font Family": "Preview Font Family", "Preview Font Family": "Preview Font Family",
"Code block Theme": "Code block Theme", "Code Block Theme": "Code Block Theme",
"Allow preview to scroll past the last line": "Allow preview to scroll past the last line", "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", "Show line numbers for preview code blocks": "Show line numbers for preview code blocks",
"LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter",
@@ -83,14 +83,14 @@
"You can choose to enable or disable this option.": "You can choose to enable or disable this option.", "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", "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote",
"Crowdfunding": "Crowdfunding", "Crowdfunding": "Crowdfunding",
"Dear everyone,": "Dear everyone,", "Dear Boostnote users,": "Dear Boostnote users,",
"Thank you for using Boostnote!": "Thank you for using Boostnote!", "Thank you for using Boostnote!": "Thank you for using Boostnote!",
"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.", "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.",
"To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", "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.", "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 like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", "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,", "Thanks,": "Thanks,",
"Boostnote maintainers": "Boostnote maintainers", "The Boostnote Team": "The Boostnote Team",
"Support via OpenCollective": "Support via OpenCollective", "Support via OpenCollective": "Support via OpenCollective",
"Language": "Language", "Language": "Language",
"English": "English", "English": "English",
@@ -141,7 +141,7 @@
"Polish": "Polish", "Polish": "Polish",
"Portuguese": "Portuguese", "Portuguese": "Portuguese",
"Spanish": "Spanish", "Spanish": "Spanish",
"You have to save!": "You have to save!", "Unsaved Changes!": "Unsaved Changes!",
"Russian": "Russian", "Russian": "Russian",
"Command(⌘)": "Command(⌘)", "Command(⌘)": "Command(⌘)",
"Editor Rulers": "Editor Rulers", "Editor Rulers": "Editor Rulers",

View File

@@ -20,7 +20,7 @@
".html": ".html", ".html": ".html",
"Print": "Drucken", "Print": "Drucken",
"Your preferences for Boostnote": "Boostnote Einstellungen", "Your preferences for Boostnote": "Boostnote Einstellungen",
"Storages": "Speicherverwaltung", "Storage Locations": "Speicherverwaltung",
"Add Storage Location": "Speicherort hinzufügen", "Add Storage Location": "Speicherort hinzufügen",
"Add Folder": "Ordner hinzufügen", "Add Folder": "Ordner hinzufügen",
"Open Storage folder": "Speicherort öffnen", "Open Storage folder": "Speicherort öffnen",
@@ -55,7 +55,7 @@
"Preview": "Vorschau", "Preview": "Vorschau",
"Preview Font Size": "Vorschau Schriftgröße", "Preview Font Size": "Vorschau Schriftgröße",
"Preview Font Family": "Vorschau Schriftart", "Preview Font Family": "Vorschau Schriftart",
"Code block Theme": "Code-Block Theme", "Code Block Theme": "Code-Block Theme",
"Allow preview to scroll past the last line": "Vorschau das Scrollen über das Ende hinaus erlauben", "Allow preview to scroll past the last line": "Vorschau das Scrollen über das Ende hinaus erlauben",
"Show line numbers for preview code blocks": "Zeilennummern in Vorschau-Code-Blöcken anzeigen", "Show line numbers for preview code blocks": "Zeilennummern in Vorschau-Code-Blöcken anzeigen",
"LaTeX Inline Open Delimiter": "LaTeX Inline Beginn Kennzeichen", "LaTeX Inline Open Delimiter": "LaTeX Inline Beginn Kennzeichen",
@@ -83,14 +83,14 @@
"You can choose to enable or disable this option.": "Du kannst wählen, ob du diese Option aktivieren oder daektivieren möchtest.", "You can choose to enable or disable this option.": "Du kannst wählen, ob du diese Option aktivieren oder daektivieren möchtest.",
"Enable analytics to help improve Boostnote": "Datenerhebung zur Verbesserung von Boostnote aktivieren", "Enable analytics to help improve Boostnote": "Datenerhebung zur Verbesserung von Boostnote aktivieren",
"Crowdfunding": "Crowdfunding", "Crowdfunding": "Crowdfunding",
"Dear everyone,": "Hallo,", "Dear Boostnote users,": "Hallo,",
"Thank you for using Boostnote!": "Danke, dass du Boostnote verwendest.", "Thank you for using Boostnote!": "Danke, dass du Boostnote verwendest.",
"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.", "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.",
"To continue supporting this growth, and to satisfy community expectations,": "Um die Erwartungen der Community weiterhin erfüllen zu können und die Verbreitung von Boostnote weiter voranzutreiben,", "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,",
"we would like to invest more time and resources in this project.": "würden wir gern mehr Zeit und Resourcen in dieses Projekt investieren.", "we would like to invest more time and resources in this project.": "würden wir gern mehr Zeit und Resourcen in dieses Projekt investieren.",
"If you like this project and see its potential, you can help by supporting us on OpenCollective!": "Wenn dir dieses Projekt gefällt und du sein Potential erkennst, kannst du uns gern mit OpenCollective unterstützen!", "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!",
"Thanks,": "Vielen Dank,", "Thanks,": "Vielen Dank,",
"Boostnote maintainers": "Dein Boostnote Team", "The Boostnote Team": "Dein Boostnote Team",
"Support via OpenCollective": "Unterstützen mit OpenCollective", "Support via OpenCollective": "Unterstützen mit OpenCollective",
"Language": "Sprache", "Language": "Sprache",
"English": "Englisch", "English": "Englisch",
@@ -130,7 +130,7 @@
"Permanent Delete": "Dauerhaft löschen", "Permanent Delete": "Dauerhaft löschen",
"Confirm note deletion": "Löschen bestätigen", "Confirm note deletion": "Löschen bestätigen",
"This will permanently remove this note.": "Diese Notiz wird dauerhaft gelöscht.", "This will permanently remove this note.": "Diese Notiz wird dauerhaft gelöscht.",
"You have to save!": "Speichern notwendig!", "Unsaved Changes!": "Speichern notwendig!",
"Albanian": "Albanisch", "Albanian": "Albanisch",
"Danish": "Dänisch", "Danish": "Dänisch",
"Japanese": "Japanisch", "Japanese": "Japanisch",

View File

@@ -23,7 +23,7 @@
"Your preferences for Boostnote": "Your preferences for Boostnote", "Your preferences for Boostnote": "Your preferences for Boostnote",
"Help": "Help", "Help": "Help",
"Hide Help": "Hide Help", "Hide Help": "Hide Help",
"Storages": "Storages", "Storage Locations": "Storage Locations",
"Add Storage Location": "Add Storage Location", "Add Storage Location": "Add Storage Location",
"Add Folder": "Add Folder", "Add Folder": "Add Folder",
"Select Folder": "Select Folder", "Select Folder": "Select Folder",
@@ -62,7 +62,7 @@
"Preview": "Preview", "Preview": "Preview",
"Preview Font Size": "Preview Font Size", "Preview Font Size": "Preview Font Size",
"Preview Font Family": "Preview Font Family", "Preview Font Family": "Preview Font Family",
"Code block Theme": "Code block Theme", "Code Block Theme": "Code Block Theme",
"Allow preview to scroll past the last line": "Allow preview to scroll past the last line", "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", "Show line numbers for preview code blocks": "Show line numbers for preview code blocks",
"LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter",
@@ -90,14 +90,14 @@
"You can choose to enable or disable this option.": "You can choose to enable or disable this option.", "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", "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote",
"Crowdfunding": "Crowdfunding", "Crowdfunding": "Crowdfunding",
"Dear everyone,": "Dear everyone,", "Dear Boostnote users,": "Dear Boostnote users,",
"Thank you for using Boostnote!": "Thank you for using Boostnote!", "Thank you for using Boostnote!": "Thank you for using Boostnote!",
"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.", "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.",
"To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", "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.", "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 like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", "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,", "Thanks,": "Thanks,",
"Boostnote maintainers": "Boostnote maintainers", "The Boostnote Team": "The Boostnote Team",
"Support via OpenCollective": "Support via OpenCollective", "Support via OpenCollective": "Support via OpenCollective",
"Language": "Language", "Language": "Language",
"English": "English", "English": "English",
@@ -134,7 +134,8 @@
"Storage": "Storage", "Storage": "Storage",
"Hotkeys": "Hotkeys", "Hotkeys": "Hotkeys",
"Show/Hide Boostnote": "Show/Hide Boostnote", "Show/Hide Boostnote": "Show/Hide Boostnote",
"Toggle editor mode": "Toggle editor mode", "Toggle Editor Mode": "Toggle Editor Mode",
"Delete Note": "Delete Note",
"Restore": "Restore", "Restore": "Restore",
"Permanent Delete": "Permanent Delete", "Permanent Delete": "Permanent Delete",
"Confirm note deletion": "Confirm note deletion", "Confirm note deletion": "Confirm note deletion",
@@ -150,7 +151,7 @@
"Polish": "Polish", "Polish": "Polish",
"Portuguese": "Portuguese", "Portuguese": "Portuguese",
"Spanish": "Spanish", "Spanish": "Spanish",
"You have to save!": "You have to save!", "Unsaved Changes!": "Unsaved Changes!",
"UserName": "UserName", "UserName": "UserName",
"Password": "Password", "Password": "Password",
"Russian": "Russian", "Russian": "Russian",
@@ -177,5 +178,6 @@
"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.", "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.",
"⚠ 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! ⚠", "⚠ 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! ⚠",
"Disabled": "Disabled", "Disabled": "Disabled",
"Enable smart table editor": "Enable smart table editor",
"Snippet Default Language": "Snippet Default Language" "Snippet Default Language": "Snippet Default Language"
} }

View File

@@ -1,8 +1,8 @@
{ {
"Notes": "Notas", "Notes": "Notas",
"Tags": "Etiquetas", "Tags": "Etiquetas",
"Preferences": "Preferencias", "Preferences": "Preferencias",
"Make a note": "Tomar una 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",
@@ -14,16 +14,16 @@
"STORAGE": "ALMACENAMIENTO", "STORAGE": "ALMACENAMIENTO",
"FOLDER": "CARPETA", "FOLDER": "CARPETA",
"CREATION DATE": "FECHA DE CREACIÓN", "CREATION DATE": "FECHA DE CREACIÓN",
"NOTE LINK": "ENLACE A LA NOTA", "NOTE LINK": "ENLACE DE LA NOTA",
".md": ".md", ".md": ".md",
".txt": ".txt", ".txt": ".txt",
".html": ".html", ".html": ".html",
"Print": "Imprimir", "Print": "Imprimir",
"Your preferences for Boostnote": "Tus preferencias para Boostnote", "Your preferences for Boostnote": "Tus preferencias para Boostnote",
"Storages": "Almacenamientos", "Storage Locations": "Almacenamientos",
"Add Storage Location": "Añadir ubicación de almacenamiento", "Add Storage Location": "Añadir ubicación de almacenamiento",
"Add Folder": "Añadir carpeta", "Add Folder": "Añadir carpeta",
"Open Storage folder": "Añadir carpeta de almacenamiento", "Open Storage folder": "Abrir carpeta de almacenamiento",
"Unlink": "Desvincular", "Unlink": "Desvincular",
"Edit": "Editar", "Edit": "Editar",
"Delete": "Eliminar", "Delete": "Eliminar",
@@ -39,8 +39,8 @@
"Editor Font Family": "Fuente del editor", "Editor Font Family": "Fuente del editor",
"Editor Indent Style": "Estilo de indentado del editor", "Editor Indent Style": "Estilo de indentado del editor",
"Spaces": "Espacios", "Spaces": "Espacios",
"Tabs": "Tabulación", "Tabs": "Tabulaciones",
"Switch to Preview": "Cambiar a Previsualización", "Switch to Preview": "Cambiar a previsualización",
"When Editor Blurred": "Cuando el editor pierde el foco", "When Editor Blurred": "Cuando el editor pierde el foco",
"When Editor Blurred, Edit On Double Click": "Cuando el editor pierde el foco, editar con doble clic", "When Editor Blurred, Edit On Double Click": "Cuando el editor pierde el foco, editar con doble clic",
"On Right Click": "Al hacer clic derecho", "On Right Click": "Al hacer clic derecho",
@@ -48,20 +48,20 @@
"default": "por defecto", "default": "por defecto",
"vim": "vim", "vim": "vim",
"emacs": "emacs", "emacs": "emacs",
"⚠️ Please restart boostnote after you change the keymap": "⚠️ Reinicie boostnote después de cambiar el mapeo de teclas", "⚠️ Please restart boostnote after you change the keymap": "⚠️ Por favor reinicie boostnote después de cambiar el mapeo de teclas",
"Show line numbers in the editor": "Mostrar números de línea en el editor", "Show line numbers in the editor": "Mostrar números de línea en el editor",
"Allow editor to scroll past the last line": "Permitir al editor desplazarse más allá de la última línea", "Allow editor to scroll past the last line": "Permitir al editor desplazarse más allá de la última línea",
"Bring in web page title when pasting URL on editor": "Al pegar una URL en el editor, insertar el título de la web automáticamente", "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": "Previsualización", "Preview": "Previsualizar",
"Preview Font Size": "Previsualizar tamaño de la fuente", "Preview Font Size": "Previsualizar tamaño de la fuente",
"Preview Font Family": "Previsualizar fuente", "Preview Font Family": "Previsualizar fuente",
"Code block Theme": "Tema de los bloques de código", "Code Block Theme": "Tema de los 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", "Allow preview to scroll past the last line": "Permitir a la previsualización desplazarse más allá de la última línea",
"Show line numbers for preview code blocks": "Mostar números de línea al previsualizar bloques de código", "Show line numbers for preview code blocks": "Mostrar números de línea al previsualizar bloques de código",
"LaTeX Inline Open Delimiter": "Delimitador de apertura LaTeX en línea", "LaTeX Inline Open Delimiter": "Delimitador de apertura de LaTeX en línea",
"LaTeX Inline Close Delimiter": "Delimitador de cierre LaTeX en línea", "LaTeX Inline Close Delimiter": "Delimitador de cierre de LaTeX en línea",
"LaTeX Block Open Delimiter": "Delimitado de apertura bloque LaTeX", "LaTeX Block Open Delimiter": "Delimitador de apertura de bloque LaTeX",
"LaTeX Block Close Delimiter": "Delimitador de cierre bloque LaTeX", "LaTeX Block Close Delimiter": "Delimitador de cierre de bloque LaTeX",
"PlantUML Server": "PlantUML Server", "PlantUML Server": "PlantUML Server",
"Community": "Comunidad", "Community": "Comunidad",
"Subscribe to Newsletter": "Suscribirse al boletín", "Subscribe to Newsletter": "Suscribirse al boletín",
@@ -71,26 +71,26 @@
"Twitter": "Twitter", "Twitter": "Twitter",
"About": "Sobre", "About": "Sobre",
"Boostnote": "Boostnote", "Boostnote": "Boostnote",
"An open source note-taking app made for programmers just like you.": "Una aplicación para tomar notas de código abieto para programadores como tú.", "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ú.",
"Website": "Página web", "Website": "Página web",
"Development": "Desarrollo", "Development": "Desarrollo",
" : Development configurations for Boostnote.": " : Configuraciones de desarrollo para Boostnote.", " : Development configurations for Boostnote.": " : Configuraciones de desarrollo para Boostnote.",
"Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO",
"License: GPL v3": "Licencia: GPL v3", "License: GPL v3": "Licencia: GPL v3",
"Analytics": "Analítica", "Analytics": "Analítica",
"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. No recopila ninguna información personal, como puede ser el contenido de sus notas.", "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 see how it works on ": "Puedes ver cómo funciona en ", "You can see how it works on ": "Puedes ver cómo funciona en ",
"You can choose to enable or disable this option.": "Puedes elegir activar o desactivar esta opción.", "You can choose to enable or disable this option.": "Puedes elegir activar o desactivar esta opción.",
"Enable analytics to help improve Boostnote": "Activa analítica para ayudar a mejorar Boostnote", "Enable analytics to help improve Boostnote": "Activar recopilación de datos para ayudar a mejorar Boostnote",
"Crowdfunding": "Crowdfunding", "Crowdfunding": "Crowdfunding",
"Dear everyone,": "Hola a todos,", "Dear Boostnote users,": "Hola a todos,",
"Thank you for using Boostnote!": "Gracias por usar Boostnote!", "Thank you for using Boostnote!": "¡Gracias por usar Boostnote!",
"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.", "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.",
"To continue supporting this growth, and to satisfy community expectations,": "Para continuar apoyando este crecimiento y satisfacer las expectativas de la comunidad,", "To support our growing userbase, and satisfy community expectations,": "Para continuar apoyando este crecimiento y satisfacer las expectativas de la comunidad,",
"we would like to invest more time and resources in this project.": "nos gustaría invertir más tiempo y recursos en este proyecto.", "we would like to invest more time and resources in this project.": "nos gustaría invertir más tiempo y recursos en este proyecto.",
"If you like this project and see its potential, you can help by supporting us on OpenCollective!": "Si te gusta este proyecto y ves su potencial, ¡puedes ayudar apoyándonos en OpenCollective!", "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!",
"Thanks,": "Gracias,", "Thanks,": "Gracias,",
"Boostnote maintainers": "Equipo de Boostnote", "The Boostnote Team": "Equipo de Boostnote",
"Support via OpenCollective": "Contribuir vía OpenCollective", "Support via OpenCollective": "Contribuir vía OpenCollective",
"Language": "Idioma", "Language": "Idioma",
"English": "Inglés", "English": "Inglés",
@@ -99,7 +99,7 @@
"Show \"Saved to Clipboard\" notification when copying": "Mostrar la notificaión \"Guardado en Portapapeles\" al copiar", "Show \"Saved to Clipboard\" notification when copying": "Mostrar la notificaión \"Guardado en Portapapeles\" al copiar",
"All Notes": "Todas las notas", "All Notes": "Todas las notas",
"Starred": "Destacado", "Starred": "Destacado",
"Are you sure to ": "Estás seguro de ", "Are you sure to ": "¿Estás seguro de ",
" delete": " eliminar", " delete": " eliminar",
"this folder?": "esta carpeta?", "this folder?": "esta carpeta?",
"Confirm": "Confirmar", "Confirm": "Confirmar",
@@ -118,7 +118,7 @@
"Blog Type": "Tipo de blog", "Blog Type": "Tipo de blog",
"Blog Address": "Dirección del blog", "Blog Address": "Dirección del blog",
"Save": "Guardar", "Save": "Guardar",
"Auth": "Auth", "Auth": "Autentificación",
"Authentication Method": "Método de autentificación", "Authentication Method": "Método de autentificación",
"JWT": "JWT", "JWT": "JWT",
"USER": "USUARIO", "USER": "USUARIO",
@@ -129,8 +129,8 @@
"Restore": "Restaurar", "Restore": "Restaurar",
"Permanent Delete": "Eliminar permanentemente", "Permanent Delete": "Eliminar permanentemente",
"Confirm note deletion": "Confirmar eliminación de nota", "Confirm note deletion": "Confirmar eliminación de nota",
"This will permanently remove this note.": "La nota se eliminará permanentemente.", "This will permanently remove this note.": "Esto eliminará la nota permanentemente.",
"Successfully applied!": "Aplicado con éxito!", "Successfully applied!": "¡Aplicado con éxito!",
"Albanian": "Albanés", "Albanian": "Albanés",
"Chinese (zh-CN)": "Chino - China", "Chinese (zh-CN)": "Chino - China",
"Chinese (zh-TW)": "Chino - Taiwan", "Chinese (zh-TW)": "Chino - Taiwan",
@@ -139,11 +139,11 @@
"Korean": "Coreano", "Korean": "Coreano",
"Norwegian": "Noruego", "Norwegian": "Noruego",
"Polish": "Polaco", "Polish": "Polaco",
"Portuguese": "Portugues", "Portuguese": "Portugués",
"Spanish": "Español", "Spanish": "Español",
"You have to save!": "Tienes que guardar!", "Unsaved Changes!": "¡Tienes que guardar!",
"Russian": "Ruso", "Russian": "Ruso",
"Command(⌘)": "Command(⌘)", "Command(⌘)": "Comando(⌘)",
"Editor Rulers": "Reglas del editor", "Editor Rulers": "Reglas del editor",
"Enable": "Activar", "Enable": "Activar",
"Disable": "Desactivar", "Disable": "Desactivar",
@@ -151,7 +151,8 @@
"Only allow secure html tags (recommended)": "Solo permitir etiquetas html seguras (recomendado)", "Only allow secure html tags (recommended)": "Solo permitir etiquetas html seguras (recomendado)",
"Allow styles": "Permitir estilos", "Allow styles": "Permitir estilos",
"Allow dangerous html tags": "Permitir etiquetas html peligrosas", "Allow dangerous html tags": "Permitir etiquetas html peligrosas",
"⚠ 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! ⚠", "⚠ 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! ⚠",
"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.", "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.",
"Disabled": "Disabled" "Disabled": "Disabled",
"Snippet Default Language": "Lenguaje por defecto de los fragmentos de código"
} }

View File

@@ -20,7 +20,7 @@
".html": ".html", ".html": ".html",
"Print": "پرینت", "Print": "پرینت",
"Your preferences for Boostnote": "تنظیمات شما برای boostnote", "Your preferences for Boostnote": "تنظیمات شما برای boostnote",
"Storages": "ذخیره سازی", "Storage Locations": "ذخیره سازی",
"Add Storage Location": "افزودن محل ذخیره سازی", "Add Storage Location": "افزودن محل ذخیره سازی",
"Add Folder": "ساخت پوشه", "Add Folder": "ساخت پوشه",
"Open Storage folder": "بازکردن پوشه ذخیره سازی", "Open Storage folder": "بازکردن پوشه ذخیره سازی",
@@ -55,7 +55,7 @@
"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": "جداکننده آغازین لاتکس خطی",
@@ -83,14 +83,14 @@
"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 everyone,": "عزیزان,", "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 continue supporting this growth, and to 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 like this project and see its potential, you can help by supporting us on OpenCollective!": "اگر این پروژه را دوست دارید و پتانسیلی در آن می‌بینید، میتوانید مارا در اوپن‌ کالکتیو حمایت کنید.", "If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "اگر این پروژه را دوست دارید و پتانسیلی در آن می‌بینید، میتوانید مارا در اوپن‌ کالکتیو حمایت کنید.",
"Thanks,": "با تشکر,", "Thanks,": "با تشکر,",
"Boostnote maintainers": "Boostnote نگهدارندگان", "The Boostnote Team": "Boostnote نگهدارندگان",
"Support via OpenCollective": "حمایت کنید OpenCollective از طریق", "Support via OpenCollective": "حمایت کنید OpenCollective از طریق",
"Language": "زبان", "Language": "زبان",
"English": "انگلیسی", "English": "انگلیسی",
@@ -142,7 +142,7 @@
"Polish": "لهستانی", "Polish": "لهستانی",
"Portuguese": "پرتغالی", "Portuguese": "پرتغالی",
"Spanish": "اسپانیایی", "Spanish": "اسپانیایی",
"You have to save!": "!باید ذخیره کنید", "Unsaved Changes!": "!باید ذخیره کنید",
"UserName": "نام کاربری", "UserName": "نام کاربری",
"Password": "رمز عبور", "Password": "رمز عبور",
"Russian": "روسی", "Russian": "روسی",
@@ -157,4 +157,4 @@
"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.", "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.",
"⚠ 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! ⚠", "⚠ 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! ⚠",
"Disabled": "Disabled" "Disabled": "Disabled"
} }

View File

@@ -20,7 +20,7 @@
".html": ".html", ".html": ".html",
"Print": "Imprimer", "Print": "Imprimer",
"Your preferences for Boostnote": "Vos préférences pour Boostnote", "Your preferences for Boostnote": "Vos préférences pour Boostnote",
"Storages": "Stockages", "Storage Locations": "Stockages",
"Add Storage Location": "Ajouter un espace de stockage", "Add Storage Location": "Ajouter un espace de stockage",
"Add Folder": "Ajouter un dossier", "Add Folder": "Ajouter un dossier",
"Open Storage folder": "Ouvrir un dossier de stockage", "Open Storage folder": "Ouvrir un dossier de stockage",
@@ -55,7 +55,7 @@
"Preview": "Aperçu", "Preview": "Aperçu",
"Preview Font Size": "Taille de police de l'aperçu", "Preview Font Size": "Taille de police de l'aperçu",
"Preview Font Family": "Police de l'aperçu", "Preview Font Family": "Police de l'aperçu",
"Code block Theme": "Thème des blocs de code", "Code Block Theme": "Thème des blocs de code",
"Show line numbers for preview code blocks": "Montrer les numéros de lignes dans les blocs de code dans 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",
"LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter",
"LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter",
@@ -82,14 +82,14 @@
"You can choose to enable or disable this option.": "Vous pouvez choisir d'activer/désactiver cette option.", "You can choose to enable or disable this option.": "Vous pouvez choisir d'activer/désactiver cette option.",
"Enable analytics to help improve Boostnote": "Activer la collecte de données anonymisées pour améliorer Boostnote", "Enable analytics to help improve Boostnote": "Activer la collecte de données anonymisées pour améliorer Boostnote",
"Crowdfunding": "Crowdfunding", "Crowdfunding": "Crowdfunding",
"Dear everyone,": "Cher utilisateur,", "Dear Boostnote users,": "Cher utilisateur,",
"Thank you for using Boostnote!": "Merci d'utiliser Boostnote !", "Thank you for using Boostnote!": "Merci d'utiliser Boostnote !",
"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.", "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.",
"To continue supporting this growth, and to satisfy community expectations,": "Afin de continuer à grandir, et de satisfaire les attentes de la communauté,", "To support our growing userbase, and satisfy community expectations,": "Afin de continuer à grandir, et de satisfaire les attentes de la communauté,",
"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.", "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.",
"If you like this project and see its potential, you can help by supporting us on OpenCollective!": "Si vous aimez ce projet et que vous en voyez tout le potentiel, vous pouvez aider par un support sur OpenCollective !", "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 !",
"Thanks,": "Merci,", "Thanks,": "Merci,",
"Boostnote maintainers": "Les mainteneurs de Boostnote", "The Boostnote Team": "Les mainteneurs de Boostnote",
"Support via OpenCollective": "Support via OpenCollective", "Support via OpenCollective": "Support via OpenCollective",
"Language": "Langues", "Language": "Langues",
"English": "Anglais", "English": "Anglais",
@@ -140,7 +140,7 @@
"Polish": "Polonais", "Polish": "Polonais",
"Portuguese": "Portugais", "Portuguese": "Portugais",
"Spanish": "Espagnol", "Spanish": "Espagnol",
"You have to save!": "Il faut sauvegarder !", "Unsaved Changes!": "Il faut sauvegarder !",
"Russian": "Russe", "Russian": "Russe",
"Command(⌘)": "Command(⌘)", "Command(⌘)": "Command(⌘)",
"Editor Rulers": "Règles dans l'éditeur", "Editor Rulers": "Règles dans l'éditeur",
@@ -153,6 +153,8 @@
"Allow dangerous html tags": "Accepter les tags html dangereux", "Allow dangerous html tags": "Accepter les tags html dangereux",
"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.", "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.",
"⚠ 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 ! ⚠", "⚠ 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 smart table editor": "Activer l'intelligent éditeur de tableaux",
"Snippet Default Language": "Langage par défaut d'un snippet",
"Disabled": "Disabled", "Disabled": "Disabled",
"Snippet Default Language": "Langage par défaut d'un snippet" "Delete Note": "Supprimer la note"
} }

View File

@@ -23,7 +23,7 @@
"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",
"Storages": "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",
"Select Folder": "Könyvtár Kiválasztása", "Select Folder": "Könyvtár Kiválasztása",
@@ -62,7 +62,7 @@
"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",
@@ -90,14 +90,14 @@
"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 everyone,": "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 continue supporting this growth, and to 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 like this project and see its potential, you can help by supporting us 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!",
"Boostnote maintainers": "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",
@@ -134,7 +134,7 @@
"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",
@@ -150,7 +150,7 @@
"Polish": "Polish", "Polish": "Polish",
"Portuguese": "Portuguese", "Portuguese": "Portuguese",
"Spanish": "Spanish", "Spanish": "Spanish",
"You have to save!": "Mentened kell!", "Unsaved Changes!": "Mentened kell!",
"UserName": "FelhasznaloNev", "UserName": "FelhasznaloNev",
"Password": "Jelszo", "Password": "Jelszo",
"Russian": "Russian", "Russian": "Russian",

View File

@@ -20,7 +20,7 @@
".html": ".html", ".html": ".html",
"Print": "Stampa", "Print": "Stampa",
"Your preferences for Boostnote": "Le tue preferenze per Boostnote", "Your preferences for Boostnote": "Le tue preferenze per Boostnote",
"Storages": "Posizioni", "Storage Locations": "Posizioni",
"Add Storage Location": "Aggiungi posizione", "Add Storage Location": "Aggiungi posizione",
"Add Folder": "Aggiungi cartella", "Add Folder": "Aggiungi cartella",
"Open Storage folder": "Apri cartella di memoria", "Open Storage folder": "Apri cartella di memoria",
@@ -55,7 +55,7 @@
"Preview": "Anteprima", "Preview": "Anteprima",
"Preview Font Size": "Dimensione font nell'anteprima", "Preview Font Size": "Dimensione font nell'anteprima",
"Preview Font Family": "Famiglia del font dell'anteprima", "Preview Font Family": "Famiglia del font dell'anteprima",
"Code block Theme": "Tema blocco di codice", "Code Block Theme": "Tema blocco di codice",
"Allow preview to scroll past the last line": "Consenti scrolling oltre l'ultima linea", "Allow preview to scroll past the last line": "Consenti scrolling oltre l'ultima linea",
"Show line numbers for preview code blocks": "Mostra numero di linea per i blocchi di codice nell'Anteprima", "Show line numbers for preview code blocks": "Mostra numero di linea per i blocchi di codice nell'Anteprima",
"LaTeX Inline Open Delimiter": "Delimitatore inline per apertura LaTex", "LaTeX Inline Open Delimiter": "Delimitatore inline per apertura LaTex",
@@ -83,14 +83,14 @@
"You can choose to enable or disable this option.": "Puoi scegliere se attivare o disattivare questa opzione.", "You can choose to enable or disable this option.": "Puoi scegliere se attivare o disattivare questa opzione.",
"Enable analytics to help improve Boostnote": "Attiva raccolta dati per aiutare a migliorare Boostnote", "Enable analytics to help improve Boostnote": "Attiva raccolta dati per aiutare a migliorare Boostnote",
"Crowdfunding": "Crowdfunding", "Crowdfunding": "Crowdfunding",
"Dear everyone,": "Cari utenti,", "Dear Boostnote users,": "Cari utenti,",
"Thank you for using Boostnote!": "Grazie per stare utilizzando Boostnote!", "Thank you for using Boostnote!": "Grazie per stare utilizzando Boostnote!",
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote è usato in circa 200 Paesi da una fantastica community di sviluppatori.", "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote è usato in circa 200 Paesi da una fantastica community di sviluppatori.",
"To continue supporting this growth, and to satisfy community expectations,": "Per continuare a supportarne la crescita, e per soddisfare le aspettative della comunità,", "To support our growing userbase, and satisfy community expectations,": "Per continuare a supportarne la crescita, e per soddisfare le aspettative della comunità,",
"we would like to invest more time and resources in this project.": "ci piacerebbe investire più tempo e risorse in questo progetto.", "we would like to invest more time and resources in this project.": "ci piacerebbe investire più tempo e risorse in questo progetto.",
"If you like this project and see its potential, you can help by supporting us on OpenCollective!": "Se ti piace questo progetto e ci vedi del potenziale, puoi aiutarci dandodci supporto su OpenCollective!", "If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "Se ti piace questo progetto e ci vedi del potenziale, puoi aiutarci dandodci supporto su OpenCollective!",
"Thanks,": "Grazie,", "Thanks,": "Grazie,",
"Boostnote maintainers": "I mantainers di Boostnote", "The Boostnote Team": "I mantainers di Boostnote",
"Support via OpenCollective": "Supporta su OpenCollective", "Support via OpenCollective": "Supporta su OpenCollective",
"Language": "Lingua", "Language": "Lingua",
"English": "Inglese", "English": "Inglese",
@@ -142,7 +142,7 @@
"Polish": "Polacco", "Polish": "Polacco",
"Portuguese": "Portoghese", "Portuguese": "Portoghese",
"Spanish": "Spagnolo", "Spanish": "Spagnolo",
"You have to save!": "Devi salvare!", "Unsaved Changes!": "Devi salvare!",
"UserName": "UserName", "UserName": "UserName",
"Password": "Password", "Password": "Password",
"Russian": "Russo", "Russian": "Russo",

View File

@@ -23,7 +23,7 @@
"Your preferences for Boostnote": "Boostnoteの個人設定", "Your preferences for Boostnote": "Boostnoteの個人設定",
"Help": "ヘルプ", "Help": "ヘルプ",
"Hide Help": "ヘルプを隠す", "Hide Help": "ヘルプを隠す",
"Storages": "ストレージ", "Storage Locations": "ストレージ",
"Add Storage Location": "ストレージロケーションを追加", "Add Storage Location": "ストレージロケーションを追加",
"Add Folder": "フォルダを追加", "Add Folder": "フォルダを追加",
"Select Folder": "フォルダを選択", "Select Folder": "フォルダを選択",
@@ -62,7 +62,7 @@
"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 開始デリミタ(インライン)", "LaTeX Inline Open Delimiter": "LaTeX 開始デリミタ(インライン)",
@@ -90,14 +90,14 @@
"You can choose to enable or disable this option.": "このオプションは有効/無効を選択できます。", "You can choose to enable or disable this option.": "このオプションは有効/無効を選択できます。",
"Enable analytics to help improve Boostnote": "Boostnote の機能向上のための解析機能を有効にする", "Enable analytics to help improve Boostnote": "Boostnote の機能向上のための解析機能を有効にする",
"Crowdfunding": "クラウドファンディング", "Crowdfunding": "クラウドファンディング",
"Dear everyone,": "みなさまへ", "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 はおよそ 200 の国と地域において、開発者コミュニティを中心に利用されています。", "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote はおよそ 200 の国と地域において、開発者コミュニティを中心に利用されています。",
"To continue supporting this growth, and to 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 like this project and see its potential, you can help by supporting us on OpenCollective!": "もしあなたがこのプロジェクトとそのポテンシャルを気に入っていただけたのであれば、OpenCollective を通じて支援いただくことができます!", "If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "もしあなたがこのプロジェクトとそのポテンシャルを気に入っていただけたのであれば、OpenCollective を通じて支援いただくことができます!",
"Thanks,": "ありがとうございます。", "Thanks,": "ありがとうございます。",
"Boostnote maintainers": "Boostnote メンテナンスチーム", "The Boostnote Team": "Boostnote メンテナンスチーム",
"Support via OpenCollective": "OpenCollective を通じて支援します", "Support via OpenCollective": "OpenCollective を通じて支援します",
"Language": "言語", "Language": "言語",
"English": "英語", "English": "英語",
@@ -134,7 +134,7 @@
"Storage": "ストレージ", "Storage": "ストレージ",
"Hotkeys": "ホットキー", "Hotkeys": "ホットキー",
"Show/Hide Boostnote": "Boostnote の表示/非表示", "Show/Hide Boostnote": "Boostnote の表示/非表示",
"Toggle editor mode": "エディタモードの切替", "Toggle Editor Mode": "エディタモードの切替",
"Restore": "リストア", "Restore": "リストア",
"Permanent Delete": "永久に削除", "Permanent Delete": "永久に削除",
"Confirm note deletion": "ノート削除確認", "Confirm note deletion": "ノート削除確認",
@@ -150,7 +150,7 @@
"Polish": "ポーランド語", "Polish": "ポーランド語",
"Portuguese": "ポルトガル語", "Portuguese": "ポルトガル語",
"Spanish": "スペイン語", "Spanish": "スペイン語",
"You have to save!": "保存してください!", "Unsaved Changes!": "保存してください!",
"UserName": "ユーザー名", "UserName": "ユーザー名",
"Password": "パスワード", "Password": "パスワード",
"Russian": "ロシア語", "Russian": "ロシア語",

View File

@@ -20,7 +20,7 @@
".html": ".html", ".html": ".html",
"Print": "인쇄", "Print": "인쇄",
"Your preferences for Boostnote": "Boostnote 설정", "Your preferences for Boostnote": "Boostnote 설정",
"Storages": "저장소", "Storage Locations": "저장소",
"Add Storage Location": "저장소 위치 추가", "Add Storage Location": "저장소 위치 추가",
"Add Folder": "폴더 추가", "Add Folder": "폴더 추가",
"Open Storage folder": "저장소 위치 열기", "Open Storage folder": "저장소 위치 열기",
@@ -55,7 +55,7 @@
"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", "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", "Show line numbers for preview code blocks": "Show line numbers for preview code blocks",
"LaTeX Inline Open Delimiter": "LaTeX 인라인 블록 열기 기호", "LaTeX Inline Open Delimiter": "LaTeX 인라인 블록 열기 기호",
@@ -83,14 +83,14 @@
"You can choose to enable or disable this option.": "사용 통계/분석 수집 여부는 직접 선택하실 수 있습니다.", "You can choose to enable or disable this option.": "사용 통계/분석 수집 여부는 직접 선택하실 수 있습니다.",
"Enable analytics to help improve Boostnote": "Boostnote 개선을 돕기위해 사용 통계/분석 수집 허가", "Enable analytics to help improve Boostnote": "Boostnote 개선을 돕기위해 사용 통계/분석 수집 허가",
"Crowdfunding": "크라우드펀딩", "Crowdfunding": "크라우드펀딩",
"Dear everyone,": "모두들에게,", "Dear Boostnote users,": "모두들에게,",
"Thank you for using Boostnote!": "사용해주셔서 감사합니다!", "Thank you for using Boostnote!": "사용해주셔서 감사합니다!",
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote는 200여개의 국가에서 뛰어난 개발자들에게 사용되어지고 있습니다.", "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote는 200여개의 국가에서 뛰어난 개발자들에게 사용되어지고 있습니다.",
"To continue supporting this growth, and to 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 like this project and see its potential, you can help by supporting us on OpenCollective!": "만약 이 프로젝트가 마음에 들고 가능성이 보이신다면, 저희를 OpenCollective에서 도와주세요!", "If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "만약 이 프로젝트가 마음에 들고 가능성이 보이신다면, 저희를 OpenCollective에서 도와주세요!",
"Thanks,": "감사합니다,", "Thanks,": "감사합니다,",
"Boostnote maintainers": "Boostnote 메인테이너", "The Boostnote Team": "Boostnote 메인테이너",
"Support via OpenCollective": "OpenCollective로 지원하기", "Support via OpenCollective": "OpenCollective로 지원하기",
"Language": "언어(Language)", "Language": "언어(Language)",
"English": "English", "English": "English",
@@ -141,7 +141,7 @@
"Polish": "Polish", "Polish": "Polish",
"Portuguese": "Portuguese", "Portuguese": "Portuguese",
"Spanish": "Spanish", "Spanish": "Spanish",
"You have to save!": "저장해주세요!", "Unsaved Changes!": "저장해주세요!",
"Russian": "Russian", "Russian": "Russian",
"Command(⌘)": "Command(⌘)", "Command(⌘)": "Command(⌘)",
"Delete Folder": "폴더 삭제", "Delete Folder": "폴더 삭제",

View File

@@ -20,7 +20,7 @@
".html": ".html", ".html": ".html",
"Print": "Print", "Print": "Print",
"Your preferences for Boostnote": "Your preferences for Boostnote", "Your preferences for Boostnote": "Your preferences for Boostnote",
"Storages": "Storages", "Storage Locations": "Storage Locations",
"Add Storage Location": "Add Storage Location", "Add Storage Location": "Add Storage Location",
"Add Folder": "Add Folder", "Add Folder": "Add Folder",
"Open Storage folder": "Open Storage folder", "Open Storage folder": "Open Storage folder",
@@ -55,7 +55,7 @@
"Preview": "Preview", "Preview": "Preview",
"Preview Font Size": "Preview Font Size", "Preview Font Size": "Preview Font Size",
"Preview Font Family": "Preview Font Family", "Preview Font Family": "Preview Font Family",
"Code block Theme": "Code block Theme", "Code Block Theme": "Code Block Theme",
"Allow preview to scroll past the last line": "Allow preview to scroll past the last line", "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", "Show line numbers for preview code blocks": "Show line numbers for preview code blocks",
"LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter",
@@ -83,14 +83,14 @@
"You can choose to enable or disable this option.": "You can choose to enable or disable this option.", "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", "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote",
"Crowdfunding": "Crowdfunding", "Crowdfunding": "Crowdfunding",
"Dear everyone,": "Dear everyone,", "Dear Boostnote users,": "Dear Boostnote users,",
"Thank you for using Boostnote!": "Thank you for using Boostnote!", "Thank you for using Boostnote!": "Thank you for using Boostnote!",
"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.", "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.",
"To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", "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.", "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 like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", "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,", "Thanks,": "Thanks,",
"Boostnote maintainers": "Boostnote maintainers", "The Boostnote Team": "The Boostnote Team",
"Support via OpenCollective": "Support via OpenCollective", "Support via OpenCollective": "Support via OpenCollective",
"Language": "Language", "Language": "Language",
"English": "English", "English": "English",
@@ -141,7 +141,7 @@
"Polish": "Polish", "Polish": "Polish",
"Portuguese": "Portuguese", "Portuguese": "Portuguese",
"Spanish": "Spanish", "Spanish": "Spanish",
"You have to save!": "You have to save!", "Unsaved Changes!": "Unsaved Changes!",
"Russian": "Russian", "Russian": "Russian",
"Editor Rulers": "Editor Rulers", "Editor Rulers": "Editor Rulers",
"Enable": "Enable", "Enable": "Enable",

View File

@@ -1,156 +1,165 @@
{ {
"Notes": "Notes", "Notes": "Notatki",
"Tags": "Tags", "Tags": "Tagi",
"Preferences": "Preferences", "Preferences": "Ustawienia",
"Make a note": "Make a note", "Make a note": "Stwórz notatkę",
"Ctrl": "Ctrl", "Ctrl": "Ctrl",
"Ctrl(^)": "Ctrl", "Ctrl(^)": "Ctrl",
"to create a new note": "to create a new note", "to create a new note": "Aby stworzyć nową notatkę",
"Toggle Mode": "Toggle Mode", "Toggle Mode": "Przełącz tryb",
"Trash": "Trash", "Trash": "Kosz",
"MODIFICATION DATE": "MODIFICATION DATE", "MODIFICATION DATE": "DATA MODYFIKACJI",
"Words": "Words", "Words": "Słowa",
"Letters": "Letters", "Letters": "Litery",
"STORAGE": "STORAGE", "STORAGE": "MIEJSCE ZAPISU",
"FOLDER": "FOLDER", "FOLDER": "FOLDER",
"CREATION DATE": "CREATION DATE", "CREATION DATE": "DATA UTWORZENIA",
"NOTE LINK": "NOTE LINK", "NOTE LINK": "LINK NOTATKI",
"Toggle Editor Mode": "Przełączanie trybu edytora",
".md": ".md", ".md": ".md",
".txt": ".txt", ".txt": ".txt",
".html": ".html", ".html": ".html",
"Print": "Print", "Print": "Drukuj",
"Your preferences for Boostnote": "Your preferences for Boostnote", "Help": "Pomoc",
"Storages": "Storages", "Your preferences for Boostnote": "Twoje ustawienia dla Boostnote",
"Add Storage Location": "Add Storage Location", "Storage Locations": "Storage Locations",
"Add Folder": "Add Folder", "Add Storage Location": "Dodaj miejsce zapisu",
"Open Storage folder": "Open Storage folder", "Add Folder": "Dodaj Folder",
"Unlink": "Unlink", "Open Storage folder": "Otwórz folder zapisu",
"Edit": "Edit", "Unlink": "Odlinkuj",
"Delete": "Delete", "Edit": "Edytuj",
"Interface": "Interface", "Delete": "Usuń",
"Interface Theme": "Interface Theme", "Interface": "Interfejs",
"Default": "Default", "Interface Theme": "Styl interfejsu",
"White": "White", "Default": "Domyślny",
"White": "Biały",
"Solarized Dark": "Solarized Dark", "Solarized Dark": "Solarized Dark",
"Dark": "Dark", "Dark": "Ciemny",
"Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", "Show a confirmation dialog when deleting notes": "Zatwierdzaj usunięcie notatek",
"Editor Theme": "Editor Theme", "Show only related tags": "Pokazuj tylko powiązane tagi",
"Editor Font Size": "Editor Font Size", "Editor Theme": "Wygląd edytora",
"Editor Font Family": "Editor Font Family", "Editor Font Size": "Rozmiar czcionki",
"Editor Indent Style": "Editor Indent Style", "Editor Font Family": "Czcionka",
"Spaces": "Spaces", "Snippet Default Language": "Domyślny język snippetów kodu",
"Tabs": "Tabs", "Editor Indent Style": "Rodzaj wcięć",
"Switch to Preview": "Switch to Preview", "Spaces": "Spacje",
"When Editor Blurred": "When Editor Blurred", "Tabs": "Tabulatory",
"When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click", "Switch to Preview": "Przełącz na podgląd",
"On Right Click": "On Right Click", "When Editor Blurred": "Gdy edytor jest w tle",
"Editor Keymap": "Editor Keymap", "When Editor Blurred, Edit On Double Click": "Gdy edytor jest w tle, edytuj za pomocą podwójnego kliknięcia",
"default": "default", "On Right Click": "Kliknięcie prawego przycisku myszy",
"Editor Keymap": "Układ klawiszy edytora",
"default": "domyślny",
"vim": "vim", "vim": "vim",
"emacs": "emacs", "emacs": "emacs",
"⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap", "⚠️ Please restart boostnote after you change the keymap": "⚠️ Musisz zrestartować Boostnote po zmianie ustawień klawiszy",
"Show line numbers in the editor": "Show line numbers in the editor", "Show line numbers in the editor": "Pokazuj numery lini w edytorze",
"Allow editor to scroll past the last line": "Allow editor to scroll past the last line", "Allow editor to scroll past the last line": "Pozwalaj edytorowi na przewijanie poza końcową lin",
"Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", "Bring in web page title when pasting URL on editor": "Wprowadź tytuł wklejanej strony WWW do edytora",
"Preview": "Preview", "Preview": "Podgląd",
"Preview Font Size": "Preview Font Size", "Preview Font Size": "Rozmiar czcionki",
"Preview Font Family": "Preview Font Family", "Enable smart quotes": "Włącz inteligentne cytowanie",
"Code block Theme": "Code block Theme", "Render newlines in Markdown paragraphs as <br>": "Dodawaj nowe linie w notatce jako znacznik <br>",
"Allow preview to scroll past the last line": "Allow preview to scroll past the last line", "Preview Font Family": "Czcionka",
"Show line numbers for preview code blocks": "Show line numbers for preview code blocks", "Code Block Theme": "Styl bloku kodu",
"LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", "Allow preview to scroll past the last line": "Pozwalaj podglądowi na przewijanie poza końcową linię",
"LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", "Show line numbers for preview code blocks": "Pokazuj numery lini dla podglądu bloków kodu",
"LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", "LaTeX Inline Open Delimiter": "Otwarcie liniowego ogranicznika LaTeX",
"LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", "LaTeX Inline Close Delimiter": "Zamknięcie liniowego ogranicznika LaTeX",
"PlantUML Server": "PlantUML Server", "LaTeX Block Open Delimiter": "Otwarcie blokowego ogranicznika LaTeX",
"Community": "Community", "LaTeX Block Close Delimiter": "Zamknięcie blokowego ogranicznika LaTeX",
"Subscribe to Newsletter": "Subscribe to Newsletter", "PlantUML Server": "Serwer PlantUML",
"Community": "Społeczność",
"Subscribe to Newsletter": "Zapisz się do Newslettera",
"GitHub": "GitHub", "GitHub": "GitHub",
"Blog": "Blog", "Blog": "Blog",
"Facebook Group": "Facebook Group", "Facebook Group": "Grupa na Facebooku",
"Twitter": "Twitter", "Twitter": "Twitter",
"About": "About", "About": "O nas",
"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.", "An open source note-taking app made for programmers just like you.": "Aplikacja open-source do przechowywania notatek, stworzona dla programistów takich jak Ty.",
"Website": "Website", "Website": "Strona WWW",
"Development": "Development", "Development": "Development",
" : Development configurations for Boostnote.": " : Development configurations for Boostnote.", " : Development configurations for Boostnote.": " : Development configurations for Boostnote.",
"Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO",
"License: GPL v3": "License: GPL v3", "License: GPL v3": "Licencja: GPL v3",
"Analytics": "Analytics", "Analytics": "Statystyki",
"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.", "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 zbiera anonimowe dane wyłącznie w celu poprawy działania aplikacji, lecz nigdy nie pobiera prywatnych danych z Twoich notatek.",
"You can see how it works on ": "You can see how it works on ", "You can see how it works on ": "Możesz zobaczyć jak to działa na platformie",
"You can choose to enable or disable this option.": "You can choose to enable or disable this option.", "You can choose to enable or disable this option.": "Możesz włączyć lub wyłączyć zbieranie danych tutaj:",
"Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", "Enable analytics to help improve Boostnote": "Zbieraj dane by pomóc w ulepszaniu Boostnote",
"Crowdfunding": "Crowdfunding", "Crowdfunding": "Crowdfunding",
"Dear everyone,": "Dear everyone,", "Dear Boostnote users,": "Droga społeczności,",
"Thank you for using Boostnote!": "Thank you for using Boostnote!", "Thank you for using Boostnote!": "Dziękujemy za używanie Boostnote!",
"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.", "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote jest używany w około 200 krajach i regionach przez wspaniałą społeczność programistów.",
"To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", "To support our growing userbase, and satisfy community expectations,": "Chcielibyśmy poświęcić więcej czasu na rozwój naszego projektu",
"we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", "we would like to invest more time and resources in this project.": "aby popularność i satysfakcja naszej społeczności ciągle wzrastała.",
"If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", "If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "Jeśli podoba Ci się naszy projekt i lubisz go używać, możesz wspomóc nasz przez OpenCollective!",
"Thanks,": "Thanks,", "Thanks,": "Dzięki,",
"Boostnote maintainers": "Boostnote maintainers", "The Boostnote Team": "Kontrybutorzy Boostnote",
"Support via OpenCollective": "Support via OpenCollective", "Support via OpenCollective": "Wspomóż przez OpenCollective",
"Language": "Language", "Language": "Język",
"English": "English", "English": "Angielski",
"German": "German", "German": "Niemiecki",
"French": "French", "French": "Francuski",
"Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", "Show \"Saved to Clipboard\" notification when copying": "Pokazuj \"Skopiowano do schowka\" podczas kopiowania",
"All Notes": "All Notes", "All Notes": "Notatki",
"Starred": "Starred", "Starred": "Oznaczone",
"Are you sure to ": "Are you sure to ", "Are you sure to ": "Czy na pewno chcesz ",
" delete": " delete", " delete": " usunąc",
"this folder?": "this folder?", "this folder?": "ten folder?",
"Confirm": "Confirm", "Confirm": "Potwierdź",
"Cancel": "Cancel", "Cancel": "Anuluj",
"Markdown Note": "Markdown Note", "Markdown Note": "Notatka 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.", "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "Ten format pozwala na tworzenie dokumentów tekstowych, list zadań, bloków kodu, czy bloków Latex.",
"Snippet Note": "Snippet Note", "Snippet Note": "Snippet Kodu",
"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.", "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "Ten format zezwala na tworzenia snippetów kodu. Kilka snippetów można zgrupować w jedną notatkę.",
"Tab to switch format": "Tab to switch format", "Tab to switch format": "Tabulator by zmienić format",
"Updated": "Updated", "Updated": "Ostatnio aktualizowane",
"Created": "Created", "Created": "Data utworzenia",
"Alphabetically": "Alphabetically", "Alphabetically": "Alfabetycznie",
"Default View": "Default View", "Default View": "Widok domyślny",
"Compressed View": "Compressed View", "Compressed View": "Widok skompresowany",
"Search": "Search", "Search": "Szukaj",
"Blog Type": "Blog Type", "Blog Type": "Typ bloga",
"Blog Address": "Blog Address", "Blog Address": "Adres bloga",
"Save": "Save", "Save": "Zapisz",
"Auth": "Auth", "Auth": "Autoryzacja",
"Authentication Method": "Authentication Method", "Authentication Method": "Metoda Autoryzacji",
"JWT": "JWT", "JWT": "JWT",
"USER": "USER", "USER": "Użutkownik",
"Token": "Token", "Token": "Token",
"Storage": "Storage", "Storage": "Storage",
"Hotkeys": "Hotkeys", "Hotkeys": "Skróty klawiszowe",
"Show/Hide Boostnote": "Show/Hide Boostnote", "Show/Hide Boostnote": "Pokaż/Ukryj Boostnote",
"Restore": "Restore", "Restore": "Przywróć",
"Permanent Delete": "Permanent Delete", "Permanent Delete": "Usuń trwale",
"Confirm note deletion": "Confirm note deletion", "Confirm note deletion": "Potwierdź usunięcie notatki",
"This will permanently remove this note.": "This will permanently remove this note.", "This will permanently remove this note.": "Spodowoduje to trwałe usunięcie notatki",
"Successfully applied!": "Successfully applied!", "Successfully applied!": "Sukces!",
"Albanian": "Albanian", "Albanian": "Albański",
"Chinese (zh-CN)": "Chinese (zh-CN)", "Chinese (zh-CN)": "Chiński (zh-CN)",
"Chinese (zh-TW)": "Chinese (zh-TW)", "Chinese (zh-TW)": "Chiński (zh-TW)",
"Danish": "Danish", "Danish": "Duński",
"Japanese": "Japanese", "Japanese": "Japoński",
"Korean": "Korean", "Korean": "Koreański",
"Norwegian": "Norwegian", "Norwegian": "Norweski",
"Polish": "Polish", "Polish": "Polski",
"Portuguese": "Portuguese", "Portuguese": "Portugalski",
"Spanish": "Spanish", "Spanish": "Hiszpański",
"You have to save!": "You have to save!", "Unsaved Changes!": "Musisz zapisać!",
"Russian": "Russian", "Russian": "Rosyjski",
"Editor Rulers": "Editor Rulers", "Editor Rulers": "Margines",
"Enable": "Enable", "Enable": "Włącz",
"Disable": "Disable", "Disable": "Wyłącz",
"Sanitization": "Sanitization", "Sanitization": "Sanitization",
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", "Only allow secure html tags (recommended)": "Zezwól tylko na bezpieczne tagi HTML (zalecane)",
"Allow styles": "Allow styles", "Allow styles": "Zezwól na style",
"Allow dangerous html tags": "Allow dangerous html tags", "Allow dangerous html tags": "Zezwól na niebezpieczne tagi HTML",
"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.", "Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Konwertuje tekstowe strzałki na znaki. ⚠ Wpłynie to na używanie komentarzy HTML w Twojej notatce.",
"⚠ 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! ⚠", "⚠ 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! ⚠": "⚠ Wkleiłes link odnoszący się do załącznika, ktory nie może zostać znaleziony. Wklejanie linków do załączników jest możliwe tylko gdy notatka i załącznik są w tym samym folderze. Używaj opcji 'Przeciągaj i upuść' załącznik! ⚠",
"Disabled": "Disabled" "Star": "Oznacz",
"Fullscreen": "Pełen ekran",
"Add tag...": "Dodaj tag...",
"Disabled": "Disabled"
} }

View File

@@ -20,7 +20,7 @@
".html": ".html", ".html": ".html",
"Print": "Imprimir", "Print": "Imprimir",
"Your preferences for Boostnote": "Suas preferências para o Boostnote", "Your preferences for Boostnote": "Suas preferências para o Boostnote",
"Storages": "Armazenamentos", "Storage Locations": "Armazenamentos",
"Add Storage Location": "Adicionar Local de Armazenamento", "Add Storage Location": "Adicionar Local de Armazenamento",
"Add Folder": "Adicionar Pasta", "Add Folder": "Adicionar Pasta",
"Open Storage folder": "Abrir Local de Armazenamento", "Open Storage folder": "Abrir Local de Armazenamento",
@@ -55,7 +55,7 @@
"Preview": "Pré-Visualização", "Preview": "Pré-Visualização",
"Preview Font Size": "Tamanho da Fonte da Pré-Visualização", "Preview Font Size": "Tamanho da Fonte da Pré-Visualização",
"Preview Font Family": "Família da Fonte da Pré-Visualização", "Preview Font Family": "Família da Fonte da Pré-Visualização",
"Code block Theme": "Tema do Bloco de Código", "Code Block Theme": "Tema do Bloco de Código",
"Allow preview to scroll past the last line": "Permitir à pré-visualização rolar além da última linha", "Allow preview to scroll past the last line": "Permitir à pré-visualização rolar além da última linha",
"Show line numbers for preview code blocks": "Mostrar os números das linhas na pré-visualização dos blocos de código", "Show line numbers for preview code blocks": "Mostrar os números das linhas na pré-visualização dos blocos de código",
"LaTeX Inline Open Delimiter": "Delimitador em Linha Aberto do LaTeX", "LaTeX Inline Open Delimiter": "Delimitador em Linha Aberto do LaTeX",
@@ -83,14 +83,14 @@
"You can choose to enable or disable this option.": "Você pode optar por ativar ou desativar essa opção.", "You can choose to enable or disable this option.": "Você pode optar por ativar ou desativar essa opção.",
"Enable analytics to help improve Boostnote": "Ativar técnicas analíticas para ajudar a melhorar o Boostnote", "Enable analytics to help improve Boostnote": "Ativar técnicas analíticas para ajudar a melhorar o Boostnote",
"Crowdfunding": "Financiamento Coletivo", "Crowdfunding": "Financiamento Coletivo",
"Dear everyone,": "Caros(as),", "Dear Boostnote users,": "Caros(as),",
"Thank you for using Boostnote!": "Obrigado por usar o Boostnote!", "Thank you for using Boostnote!": "Obrigado por usar o Boostnote!",
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "O Boostnote é usado em cerca de 200 países e regiões diferentes por uma incrível comunidade de desenvolvedores.", "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "O Boostnote é usado em cerca de 200 países e regiões diferentes por uma incrível comunidade de desenvolvedores.",
"To continue supporting this growth, and to satisfy community expectations,": "Para continuar apoiando o crescimento e satisfazer as expectativas da comunidade,", "To support our growing userbase, and satisfy community expectations,": "Para continuar apoiando o crescimento e satisfazer as expectativas da comunidade,",
"we would like to invest more time and resources in this project.": "gostaríamos de investir mais tempo e recursos neste projeto.", "we would like to invest more time and resources in this project.": "gostaríamos de investir mais tempo e recursos neste projeto.",
"If you like this project and see its potential, you can help by supporting us on OpenCollective!": "Se você gosta deste projeto e vê o seu potencial, você pode nos ajudar apoiando-nos no OpenCollective!", "If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "Se você gosta deste projeto e vê o seu potencial, você pode nos ajudar apoiando-nos no OpenCollective!",
"Thanks,": "Obrigado,", "Thanks,": "Obrigado,",
"Boostnote maintainers": "Mantenedores do Boostnote", "The Boostnote Team": "Mantenedores do Boostnote",
"Support via OpenCollective": "Suporte via OpenCollective", "Support via OpenCollective": "Suporte via OpenCollective",
"Language": "Idioma", "Language": "Idioma",
"English": "Inglês", "English": "Inglês",
@@ -141,7 +141,7 @@
"Polish": "Polonês", "Polish": "Polonês",
"Portuguese": "Português (pt-BR)", "Portuguese": "Português (pt-BR)",
"Spanish": "Espanhol", "Spanish": "Espanhol",
"You have to save!": "Você precisa salvar!", "Unsaved Changes!": "Você precisa salvar!",
"Russian": "Russo", "Russian": "Russo",
"Editor Rulers": "Réguas do Editor", "Editor Rulers": "Réguas do Editor",
"Enable": "Habilitado", "Enable": "Habilitado",

View File

@@ -20,7 +20,7 @@
".html": ".html", ".html": ".html",
"Print": "Print", "Print": "Print",
"Your preferences for Boostnote": "Your preferences for Boostnote", "Your preferences for Boostnote": "Your preferences for Boostnote",
"Storages": "Storages", "Storage Locations": "Storage Locations",
"Add Storage Location": "Add Storage Location", "Add Storage Location": "Add Storage Location",
"Add Folder": "Add Folder", "Add Folder": "Add Folder",
"Open Storage folder": "Open Storage folder", "Open Storage folder": "Open Storage folder",
@@ -55,7 +55,7 @@
"Preview": "Preview", "Preview": "Preview",
"Preview Font Size": "Preview Font Size", "Preview Font Size": "Preview Font Size",
"Preview Font Family": "Preview Font Family", "Preview Font Family": "Preview Font Family",
"Code block Theme": "Code block Theme", "Code Block Theme": "Code Block Theme",
"Allow preview to scroll past the last line": "Allow preview to scroll past the last line", "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", "Show line numbers for preview code blocks": "Show line numbers for preview code blocks",
"LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter",
@@ -83,14 +83,14 @@
"You can choose to enable or disable this option.": "You can choose to enable or disable this option.", "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", "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote",
"Crowdfunding": "Crowdfunding", "Crowdfunding": "Crowdfunding",
"Dear everyone,": "Dear everyone,", "Dear Boostnote users,": "Dear Boostnote users,",
"Thank you for using Boostnote!": "Thank you for using Boostnote!", "Thank you for using Boostnote!": "Thank you for using Boostnote!",
"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.", "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.",
"To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", "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.", "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 like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", "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,", "Thanks,": "Thanks,",
"Boostnote maintainers": "Boostnote maintainers", "The Boostnote Team": "The Boostnote Team",
"Support via OpenCollective": "Support via OpenCollective", "Support via OpenCollective": "Support via OpenCollective",
"Language": "Language", "Language": "Language",
"English": "English", "English": "English",
@@ -141,7 +141,7 @@
"Polish": "Polish", "Polish": "Polish",
"Portuguese": "Portuguese", "Portuguese": "Portuguese",
"Spanish": "Spanish", "Spanish": "Spanish",
"You have to save!": "You have to save!", "Unsaved Changes!": "Unsaved Changes!",
"Russian": "Russian", "Russian": "Russian",
"Editor Rulers": "Editor Rulers", "Editor Rulers": "Editor Rulers",
"Enable": "Enable", "Enable": "Enable",

View File

@@ -20,7 +20,7 @@
".html": ".html", ".html": ".html",
"Print": "Print", "Print": "Print",
"Your preferences for Boostnote": "Настройки Boostnote", "Your preferences for Boostnote": "Настройки Boostnote",
"Storages": "Хранилища", "Storage Locations": "Хранилища",
"Add Storage Location": "Добавить хранилище", "Add Storage Location": "Добавить хранилище",
"Add Folder": "Добавить папку", "Add Folder": "Добавить папку",
"Open Storage folder": "Открыть хранилище", "Open Storage folder": "Открыть хранилище",
@@ -55,7 +55,7 @@
"Preview": "Preview", "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": "Символ начала inline записи в LaTeX", "LaTeX Inline Open Delimiter": "Символ начала inline записи в LaTeX",
@@ -82,14 +82,14 @@
"You can choose to enable or disable this option.": "Вы можете отказаться от передачи анонимной информации разработчикам.", "You can choose to enable or disable this option.": "Вы можете отказаться от передачи анонимной информации разработчикам.",
"Enable analytics to help improve Boostnote": "Отправлять анонимные данные, чтобы сделать Boostnote еще лучше", "Enable analytics to help improve Boostnote": "Отправлять анонимные данные, чтобы сделать Boostnote еще лучше",
"Crowdfunding": "Краудфандинг", "Crowdfunding": "Краудфандинг",
"Dear everyone,": "Привет,", "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 используется в 200 странах и регионов дружным сообществом разработчиков.", "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote используется в 200 странах и регионов дружным сообществом разработчиков.",
"To continue supporting this growth, and to 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 like this project and see its potential, you can help by supporting us on OpenCollective!": "Если вам нравится Boostnote и его сообщество, вы можете профинансировать проект на OpenCollective!", "If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "Если вам нравится Boostnote и его сообщество, вы можете профинансировать проект на OpenCollective!",
"Thanks,": "Спасибо,", "Thanks,": "Спасибо,",
"Boostnote maintainers": "разработчики Boostnote", "The Boostnote Team": "разработчики Boostnote",
"Support via OpenCollective": "Старница проекта на OpenCollective", "Support via OpenCollective": "Старница проекта на OpenCollective",
"Language": "Язык", "Language": "Язык",
"English": "Английский", "English": "Английский",
@@ -140,7 +140,7 @@
"Polish": "Польский", "Polish": "Польский",
"Portuguese": "Португальский", "Portuguese": "Португальский",
"Spanish": "Испанский", "Spanish": "Испанский",
"You have to save!": "Нужно сохранить!", "Unsaved Changes!": "Нужно сохранить!",
"UserName": "Имя пользователя", "UserName": "Имя пользователя",
"Password": "Пароль", "Password": "Пароль",
"Russian": "Русский", "Russian": "Русский",

View File

@@ -20,7 +20,7 @@
".html": ".html", ".html": ".html",
"Print": "Print", "Print": "Print",
"Your preferences for Boostnote": "Your preferences for Boostnote", "Your preferences for Boostnote": "Your preferences for Boostnote",
"Storages": "Storages", "Storage Locations": "Storage Locations",
"Add Storage Location": "Add Storage Location", "Add Storage Location": "Add Storage Location",
"Add Folder": "Add Folder", "Add Folder": "Add Folder",
"Open Storage folder": "Open Storage folder", "Open Storage folder": "Open Storage folder",
@@ -55,7 +55,7 @@
"Preview": "Preview", "Preview": "Preview",
"Preview Font Size": "Preview Font Size", "Preview Font Size": "Preview Font Size",
"Preview Font Family": "Preview Font Family", "Preview Font Family": "Preview Font Family",
"Code block Theme": "Code block Theme", "Code Block Theme": "Code Block Theme",
"Allow preview to scroll past the last line": "Allow preview to scroll past the last line", "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", "Show line numbers for preview code blocks": "Show line numbers for preview code blocks",
"LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter",
@@ -82,14 +82,14 @@
"You can choose to enable or disable this option.": "You can choose to enable or disable this option.", "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", "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote",
"Crowdfunding": "Crowdfunding", "Crowdfunding": "Crowdfunding",
"Dear everyone,": "Dear everyone,", "Dear Boostnote users,": "Dear Boostnote users,",
"Thank you for using Boostnote!": "Thank you for using Boostnote!", "Thank you for using Boostnote!": "Thank you for using Boostnote!",
"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.", "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.",
"To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", "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.", "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 like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", "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,", "Thanks,": "Thanks,",
"Boostnote maintainers": "Boostnote maintainers", "The Boostnote Team": "The Boostnote Team",
"Support via OpenCollective": "Support via OpenCollective", "Support via OpenCollective": "Support via OpenCollective",
"Language": "Language", "Language": "Language",
"English": "English", "English": "English",
@@ -140,7 +140,7 @@
"Polish": "Polish", "Polish": "Polish",
"Portuguese": "Portuguese", "Portuguese": "Portuguese",
"Spanish": "Spanish", "Spanish": "Spanish",
"You have to save!": "You have to save!", "Unsaved Changes!": "Unsaved Changes!",
"Russian": "Russian", "Russian": "Russian",
"Editor Rulers": "Editor Rulers", "Editor Rulers": "Editor Rulers",
"Enable": "Enable", "Enable": "Enable",

View File

@@ -20,7 +20,7 @@
".html": ".html", ".html": ".html",
"Print": "Yazdır", "Print": "Yazdır",
"Your preferences for Boostnote": "Boostnote tercihleriniz", "Your preferences for Boostnote": "Boostnote tercihleriniz",
"Storages": "Saklama Alanları", "Storage Locations": "Saklama Alanları",
"Add Storage Location": "Saklama Yeri Ekle", "Add Storage Location": "Saklama Yeri Ekle",
"Add Folder": "Dosya Ekle", "Add Folder": "Dosya Ekle",
"Open Storage folder": "Saklama Alanı Dosyasını Aç", "Open Storage folder": "Saklama Alanı Dosyasını Aç",
@@ -55,7 +55,7 @@
"Preview": "Önizleme", "Preview": "Önizleme",
"Preview Font Size": "Yazı Büyüklüğünü Önizle", "Preview Font Size": "Yazı Büyüklüğünü Önizle",
"Preview Font Family": "Yazı Tipini Önizle", "Preview Font Family": "Yazı Tipini Önizle",
"Code block Theme": "Kod bloğu Teması", "Code Block Theme": "Kod bloğu Teması",
"Allow preview to scroll past the last line": "Önizlemenin son satırı geçmesine izin ver", "Allow preview to scroll past the last line": "Önizlemenin son satırı geçmesine izin ver",
"Show line numbers for preview code blocks": "Kod bloklarının önizlemesinde satır numaralarını göster", "Show line numbers for preview code blocks": "Kod bloklarının önizlemesinde satır numaralarını göster",
"LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter",
@@ -82,14 +82,14 @@
"You can choose to enable or disable this option.": "Bu seçeneği etkinleştirmeyi veya devre dışı bırakmayı seçebilirsiniz.", "You can choose to enable or disable this option.": "Bu seçeneği etkinleştirmeyi veya devre dışı bırakmayı seçebilirsiniz.",
"Enable analytics to help improve Boostnote": "Boostnote'un geliştirilmesine katkıda bulunmak için analizleri etkinleştirin", "Enable analytics to help improve Boostnote": "Boostnote'un geliştirilmesine katkıda bulunmak için analizleri etkinleştirin",
"Crowdfunding": "Kitle Fonlaması", "Crowdfunding": "Kitle Fonlaması",
"Dear everyone,": "Sevgili herkes,", "Dear Boostnote users,": "Sevgili herkes,",
"Thank you for using Boostnote!": "Boostnote'u kullandığınız için teşekkürler!", "Thank you for using Boostnote!": "Boostnote'u kullandığınız için teşekkürler!",
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote, 200 farklı ülke ve bölgede, harika bir geliştirici topluluğu tarafından kullanılmaktadır.", "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote, 200 farklı ülke ve bölgede, harika bir geliştirici topluluğu tarafından kullanılmaktadır.",
"To continue supporting this growth, and to satisfy community expectations,": "Bu büyümeyi desteklemeye devam etmek ve topluluk beklentilerini karşılamak için,", "To support our growing userbase, and satisfy community expectations,": "Bu büyümeyi desteklemeye devam etmek ve topluluk beklentilerini karşılamak için,",
"we would like to invest more time and resources in this project.": "bu projeye daha fazla zaman ve kaynak yatırmak istiyoruz.", "we would like to invest more time and resources in this project.": "bu projeye daha fazla zaman ve kaynak yatırmak istiyoruz.",
"If you like this project and see its potential, you can help by supporting us on OpenCollective!": "Bu projeyi beğeniyor ve potansiyel görüyorsanız, OpenCollective üzerinden bizi destekleyerek katkıda bulunabilirsiniz!", "If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "Bu projeyi beğeniyor ve potansiyel görüyorsanız, OpenCollective üzerinden bizi destekleyerek katkıda bulunabilirsiniz!",
"Thanks,": "Teşekkürler,", "Thanks,": "Teşekkürler,",
"Boostnote maintainers": "Boostnote'un bakımını yapanlar", "The Boostnote Team": "Boostnote'un bakımını yapanlar",
"Support via OpenCollective": "OpenCollective aracılığıyla destekle", "Support via OpenCollective": "OpenCollective aracılığıyla destekle",
"Language": "Dil", "Language": "Dil",
"English": "İngilizce", "English": "İngilizce",
@@ -140,7 +140,7 @@
"Polish": "Lehçe", "Polish": "Lehçe",
"Portuguese": "Portekizce", "Portuguese": "Portekizce",
"Spanish": "İspanyolca", "Spanish": "İspanyolca",
"You have to save!": "Kaydetmelisiniz!", "Unsaved Changes!": "Kaydetmelisiniz!",
"UserName": "KullanıcıAdı", "UserName": "KullanıcıAdı",
"Password": "Şifre", "Password": "Şifre",
"Russian": "Rusça", "Russian": "Rusça",

Some files were not shown because too many files have changed in this diff Show More