mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 01:36:22 +00:00
Merge branch 'master' into crossplatform_fullscreen_shortcuts
This commit is contained in:
2
.babelrc
2
.babelrc
@@ -5,7 +5,7 @@
|
|||||||
"presets": ["react-hmre"]
|
"presets": ["react-hmre"]
|
||||||
},
|
},
|
||||||
"test": {
|
"test": {
|
||||||
"presets": ["react", "es2015"],
|
"presets": ["env" ,"react", "es2015"],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
[ "babel-plugin-webpack-alias", { "config": "${PWD}/webpack.config.js" } ]
|
[ "babel-plugin-webpack-alias", { "config": "${PWD}/webpack.config.js" } ]
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
"lineNumber": true
|
"lineNumber": true
|
||||||
},
|
},
|
||||||
"sortBy": "UPDATED_AT",
|
"sortBy": "UPDATED_AT",
|
||||||
|
"sortTagsBy": "ALPHABETICAL",
|
||||||
"ui": {
|
"ui": {
|
||||||
"defaultNote": "ALWAYS_ASK",
|
"defaultNote": "ALWAYS_ASK",
|
||||||
"disableDirectWrite": false,
|
"disableDirectWrite": false,
|
||||||
|
|||||||
@@ -1,10 +1,25 @@
|
|||||||
|
# Current behavior
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Please paste some **screenshots** with the **developer tool** open (console tab) when you report a bug.
|
Please paste some **screenshots** with the **developer tool** open (console tab) when you report a bug.
|
||||||
|
|
||||||
If your issue is regarding boostnote mobile, move to https://github.com/BoostIO/boostnote-mobile.
|
If your issue is regarding boostnote mobile, move to https://github.com/BoostIO/boostnote-mobile.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
# Expected behavior
|
||||||
|
|
||||||
|
# Steps to reproduce
|
||||||
|
|
||||||
|
1.
|
||||||
|
2.
|
||||||
|
3.
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
|
||||||
|
- Version :
|
||||||
|
- OS Version and name :
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Love Boostnote? Please consider supporting us via OpenCollective:
|
Love Boostnote? Please consider supporting us via OpenCollective:
|
||||||
👉 https://opencollective.com/boostnoteio
|
👉 https://opencollective.com/boostnoteio
|
||||||
-->
|
-->
|
||||||
7
__mocks__/electron.js
Normal file
7
__mocks__/electron.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
module.exports = {
|
||||||
|
require: jest.genMockFunction(),
|
||||||
|
match: jest.genMockFunction(),
|
||||||
|
app: jest.genMockFunction(),
|
||||||
|
remote: jest.genMockFunction(),
|
||||||
|
dialog: jest.genMockFunction()
|
||||||
|
}
|
||||||
@@ -109,6 +109,8 @@ export default class CodeEditor extends React.Component {
|
|||||||
scrollPastEnd: this.props.scrollPastEnd,
|
scrollPastEnd: this.props.scrollPastEnd,
|
||||||
inputStyle: 'textarea',
|
inputStyle: 'textarea',
|
||||||
dragDrop: false,
|
dragDrop: false,
|
||||||
|
foldGutter: true,
|
||||||
|
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
|
||||||
autoCloseBrackets: true,
|
autoCloseBrackets: true,
|
||||||
extraKeys: {
|
extraKeys: {
|
||||||
Tab: function (cm) {
|
Tab: function (cm) {
|
||||||
@@ -275,11 +277,16 @@ export default class CodeEditor extends React.Component {
|
|||||||
|
|
||||||
handleDropImage (e) {
|
handleDropImage (e) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const imagePath = e.dataTransfer.files[0].path
|
const ValidImageTypes = ['image/gif', 'image/jpeg', 'image/png']
|
||||||
const filename = path.basename(imagePath)
|
|
||||||
|
|
||||||
copyImage(imagePath, this.props.storageKey).then((imagePath) => {
|
const file = e.dataTransfer.files[0]
|
||||||
const imageMd = `})`
|
const filePath = file.path
|
||||||
|
const filename = path.basename(filePath)
|
||||||
|
const fileType = file['type']
|
||||||
|
|
||||||
|
copyImage(filePath, this.props.storageKey).then((imagePath) => {
|
||||||
|
var showPreview = ValidImageTypes.indexOf(fileType) > 0
|
||||||
|
const imageMd = `${showPreview ? '!' : ''}[${filename}](${path.join('/:storage', imagePath)})`
|
||||||
this.insertImageMd(imageMd)
|
this.insertImageMd(imageMd)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import htmlTextHelper from 'browser/lib/htmlTextHelper'
|
|||||||
import copy from 'copy-to-clipboard'
|
import copy from 'copy-to-clipboard'
|
||||||
import mdurl from 'mdurl'
|
import mdurl from 'mdurl'
|
||||||
import exportNote from 'browser/main/lib/dataApi/exportNote'
|
import exportNote from 'browser/main/lib/dataApi/exportNote'
|
||||||
|
import {escapeHtmlCharacters} from 'browser/lib/utils'
|
||||||
|
|
||||||
const { remote } = require('electron')
|
const { remote } = require('electron')
|
||||||
const { app } = remote
|
const { app } = remote
|
||||||
@@ -208,7 +209,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
const {fontFamily, fontSize, codeBlockFontFamily, lineNumber, codeBlockTheme} = this.getStyleParams()
|
const {fontFamily, fontSize, codeBlockFontFamily, lineNumber, codeBlockTheme} = this.getStyleParams()
|
||||||
|
|
||||||
const inlineStyles = buildStyle(fontFamily, fontSize, codeBlockFontFamily, lineNumber, codeBlockTheme, lineNumber)
|
const inlineStyles = buildStyle(fontFamily, fontSize, codeBlockFontFamily, lineNumber, codeBlockTheme, lineNumber)
|
||||||
const body = this.markdown.render(noteContent)
|
const body = this.markdown.render(escapeHtmlCharacters(noteContent))
|
||||||
const files = [this.GetCodeThemeLink(codeBlockTheme), ...CSS_FILES]
|
const files = [this.GetCodeThemeLink(codeBlockTheme), ...CSS_FILES]
|
||||||
|
|
||||||
files.forEach((file) => {
|
files.forEach((file) => {
|
||||||
@@ -394,6 +395,9 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
|
|
||||||
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('a'), (el) => {
|
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('a'), (el) => {
|
||||||
this.fixDecodedURI(el)
|
this.fixDecodedURI(el)
|
||||||
|
el.href = this.markdown.normalizeLinkText(el.href)
|
||||||
|
if (!/\/:storage/.test(el.href)) return
|
||||||
|
el.href = `file:///${this.markdown.normalizeLinkText(path.join(storagePath, 'images', path.basename(el.href)))}`
|
||||||
el.addEventListener('click', this.anchorClickHandler)
|
el.addEventListener('click', this.anchorClickHandler)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import CSSModules from 'browser/lib/CSSModules'
|
|||||||
* @param {Array} storgaeList
|
* @param {Array} storgaeList
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const StorageList = ({storageList}) => (
|
const StorageList = ({storageList, isFolded}) => (
|
||||||
<div styleName='storageList'>
|
<div styleName={isFolded ? 'storageList-folded' : 'storageList'}>
|
||||||
{storageList.length > 0 ? storageList : (
|
{storageList.length > 0 ? storageList : (
|
||||||
<div styleName='storgaeList-empty'>No storage mount.</div>
|
<div styleName='storgaeList-empty'>No storage mount.</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
top 180px
|
top 180px
|
||||||
overflow-y auto
|
overflow-y auto
|
||||||
|
|
||||||
|
.storageList-folded
|
||||||
|
@extend .storageList
|
||||||
|
width 44px
|
||||||
|
|
||||||
.storageList-empty
|
.storageList-empty
|
||||||
padding 0 10px
|
padding 0 10px
|
||||||
margin-top 15px
|
margin-top 15px
|
||||||
|
|||||||
23
browser/lib/confirmDeleteNote.js
Normal file
23
browser/lib/confirmDeleteNote.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import electron from 'electron'
|
||||||
|
import i18n from 'browser/lib/i18n'
|
||||||
|
const { remote } = electron
|
||||||
|
const { dialog } = remote
|
||||||
|
|
||||||
|
export function confirmDeleteNote (confirmDeletion, permanent) {
|
||||||
|
if (confirmDeletion || permanent) {
|
||||||
|
const alertConfig = {
|
||||||
|
ype: 'warning',
|
||||||
|
message: i18n.__('Confirm note deletion'),
|
||||||
|
detail: i18n.__('This will permanently remove this note.'),
|
||||||
|
buttons: [i18n.__('Confirm'), i18n.__('Cancel')]
|
||||||
|
}
|
||||||
|
|
||||||
|
const dialogButtonIndex = dialog.showMessageBox(
|
||||||
|
remote.getCurrentWindow(), alertConfig
|
||||||
|
)
|
||||||
|
|
||||||
|
return dialogButtonIndex === 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -1,8 +1,15 @@
|
|||||||
|
const path = require('path')
|
||||||
|
const { remote } = require('electron')
|
||||||
|
const { app } = remote
|
||||||
|
|
||||||
// load package for localization
|
// load package for localization
|
||||||
const i18n = new (require('i18n-2'))({
|
const i18n = new (require('i18n-2'))({
|
||||||
// setup some locales - other locales default to the first locale
|
// setup some locales - other locales default to the first locale
|
||||||
locales: ['en', 'sq', 'zh-CN', 'zh-TW', 'da', 'fr', 'de', 'hu', 'ja', 'ko', 'no', 'pl', 'pt', 'es-ES'],
|
locales: [ 'da', 'de', 'en', 'es-ES', 'fr', 'hu', 'ja', 'ko', 'pl', 'pt-BR', 'pt-PT', 'ru', 'sq', 'zh-CN', 'zh-TW' ],
|
||||||
extension: '.json',
|
extension: '.json',
|
||||||
|
directory: process.env.NODE_ENV === 'production'
|
||||||
|
? path.join(app.getAppPath(), './locales')
|
||||||
|
: path.resolve('./locales'),
|
||||||
devMode: false
|
devMode: false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -4,39 +4,28 @@ export default function searchFromNotes (notes, search) {
|
|||||||
if (search.trim().length === 0) return []
|
if (search.trim().length === 0) return []
|
||||||
const searchBlocks = search.split(' ').filter(block => { return block !== '' })
|
const searchBlocks = search.split(' ').filter(block => { return block !== '' })
|
||||||
|
|
||||||
let foundNotes = findByWord(notes, searchBlocks[0])
|
let foundNotes = notes
|
||||||
searchBlocks.forEach((block) => {
|
searchBlocks.forEach((block) => {
|
||||||
foundNotes = findByWord(foundNotes, block)
|
foundNotes = findByWordOrTag(foundNotes, block)
|
||||||
if (block.match(/^#.+/)) {
|
|
||||||
foundNotes = foundNotes.concat(findByTag(notes, block))
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
return foundNotes
|
return foundNotes
|
||||||
}
|
}
|
||||||
|
|
||||||
function findByTag (notes, block) {
|
function findByWordOrTag (notes, block) {
|
||||||
const tag = block.match(/#(.+)/)[1]
|
let tag = block
|
||||||
const regExp = new RegExp(_.escapeRegExp(tag), 'i')
|
if (tag.match(/^#.+/)) {
|
||||||
|
tag = tag.match(/#(.+)/)[1]
|
||||||
|
}
|
||||||
|
const tagRegExp = new RegExp(_.escapeRegExp(tag), 'i')
|
||||||
|
const wordRegExp = new RegExp(_.escapeRegExp(block), 'i')
|
||||||
return notes.filter((note) => {
|
return notes.filter((note) => {
|
||||||
if (!_.isArray(note.tags)) return false
|
if (_.isArray(note.tags) && note.tags.some((_tag) => _tag.match(tagRegExp))) {
|
||||||
return note.tags.some((_tag) => {
|
|
||||||
return _tag.match(regExp)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function findByWord (notes, block) {
|
|
||||||
const regExp = new RegExp(_.escapeRegExp(block), 'i')
|
|
||||||
return notes.filter((note) => {
|
|
||||||
if (_.isArray(note.tags) && note.tags.some((_tag) => {
|
|
||||||
return _tag.match(regExp)
|
|
||||||
})) {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if (note.type === 'SNIPPET_NOTE') {
|
if (note.type === 'SNIPPET_NOTE') {
|
||||||
return note.description.match(regExp)
|
return note.description.match(wordRegExp)
|
||||||
} else if (note.type === 'MARKDOWN_NOTE') {
|
} else if (note.type === 'MARKDOWN_NOTE') {
|
||||||
return note.content.match(regExp)
|
return note.content.match(wordRegExp)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,6 +6,55 @@ export function lastFindInArray (array, callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export function escapeHtmlCharacters (text) {
|
||||||
lastFindInArray
|
const matchHtmlRegExp = /["'&<>]/
|
||||||
|
const str = '' + text
|
||||||
|
const match = matchHtmlRegExp.exec(str)
|
||||||
|
|
||||||
|
if (!match) {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
let escape
|
||||||
|
let html = ''
|
||||||
|
let index = 0
|
||||||
|
let lastIndex = 0
|
||||||
|
|
||||||
|
for (index = match.index; index < str.length; index++) {
|
||||||
|
switch (str.charCodeAt(index)) {
|
||||||
|
case 34: // "
|
||||||
|
escape = '"'
|
||||||
|
break
|
||||||
|
case 38: // &
|
||||||
|
escape = '&'
|
||||||
|
break
|
||||||
|
case 39: // '
|
||||||
|
escape = '''
|
||||||
|
break
|
||||||
|
case 60: // <
|
||||||
|
escape = '<'
|
||||||
|
break
|
||||||
|
case 62: // >
|
||||||
|
escape = '>'
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastIndex !== index) {
|
||||||
|
html += str.substring(lastIndex, index)
|
||||||
|
}
|
||||||
|
|
||||||
|
lastIndex = index + 1
|
||||||
|
html += escape
|
||||||
|
}
|
||||||
|
|
||||||
|
return lastIndex !== index
|
||||||
|
? html + str.substring(lastIndex, index)
|
||||||
|
: html
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
lastFindInArray,
|
||||||
|
escapeHtmlCharacters
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import InfoPanelTrashed from './InfoPanelTrashed'
|
|||||||
import { formatDate } from 'browser/lib/date-formatter'
|
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'
|
||||||
|
|
||||||
class MarkdownNoteDetail extends React.Component {
|
class MarkdownNoteDetail extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
@@ -181,10 +182,10 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
handleTrashButtonClick (e) {
|
handleTrashButtonClick (e) {
|
||||||
const { note } = this.state
|
const { note } = this.state
|
||||||
const { isTrashed } = note
|
const { isTrashed } = note
|
||||||
const { confirmDeletion } = this.props
|
const { confirmDeletion } = this.props.config.ui
|
||||||
|
|
||||||
if (isTrashed) {
|
if (isTrashed) {
|
||||||
if (confirmDeletion(true)) {
|
if (confirmDeleteNote(confirmDeletion, true)) {
|
||||||
const {note, dispatch} = this.props
|
const {note, dispatch} = this.props
|
||||||
dataApi
|
dataApi
|
||||||
.deleteNote(note.storage, note.key)
|
.deleteNote(note.storage, note.key)
|
||||||
@@ -201,7 +202,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
.then(() => ee.emit('list:next'))
|
.then(() => ee.emit('list:next'))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (confirmDeletion()) {
|
if (confirmDeleteNote(confirmDeletion, false)) {
|
||||||
note.isTrashed = true
|
note.isTrashed = true
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -437,8 +438,7 @@ MarkdownNoteDetail.propTypes = {
|
|||||||
style: PropTypes.shape({
|
style: PropTypes.shape({
|
||||||
left: PropTypes.number
|
left: PropTypes.number
|
||||||
}),
|
}),
|
||||||
ignorePreviewPointerEvents: PropTypes.bool,
|
ignorePreviewPointerEvents: PropTypes.bool
|
||||||
confirmDeletion: PropTypes.bool.isRequired
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CSSModules(MarkdownNoteDetail, styles)
|
export default CSSModules(MarkdownNoteDetail, styles)
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import InfoPanel from './InfoPanel'
|
|||||||
import InfoPanelTrashed from './InfoPanelTrashed'
|
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'
|
||||||
|
|
||||||
function pass (name) {
|
function pass (name) {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
@@ -197,10 +198,10 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
handleTrashButtonClick (e) {
|
handleTrashButtonClick (e) {
|
||||||
const { note } = this.state
|
const { note } = this.state
|
||||||
const { isTrashed } = note
|
const { isTrashed } = note
|
||||||
const { confirmDeletion } = this.props
|
const { confirmDeletion } = this.props.config.ui
|
||||||
|
|
||||||
if (isTrashed) {
|
if (isTrashed) {
|
||||||
if (confirmDeletion(true)) {
|
if (confirmDeleteNote(confirmDeletion, true)) {
|
||||||
const {note, dispatch} = this.props
|
const {note, dispatch} = this.props
|
||||||
dataApi
|
dataApi
|
||||||
.deleteNote(note.storage, note.key)
|
.deleteNote(note.storage, note.key)
|
||||||
@@ -217,7 +218,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
.then(() => ee.emit('list:next'))
|
.then(() => ee.emit('list:next'))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (confirmDeletion()) {
|
if (confirmDeleteNote(confirmDeletion, false)) {
|
||||||
note.isTrashed = true
|
note.isTrashed = true
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -883,8 +884,7 @@ SnippetNoteDetail.propTypes = {
|
|||||||
style: PropTypes.shape({
|
style: PropTypes.shape({
|
||||||
left: PropTypes.number
|
left: PropTypes.number
|
||||||
}),
|
}),
|
||||||
ignorePreviewPointerEvents: PropTypes.bool,
|
ignorePreviewPointerEvents: PropTypes.bool
|
||||||
confirmDeletion: PropTypes.bool.isRequired
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CSSModules(SnippetNoteDetail, styles)
|
export default CSSModules(SnippetNoteDetail, styles)
|
||||||
|
|||||||
@@ -33,26 +33,6 @@ class Detail extends React.Component {
|
|||||||
ee.off('detail:delete', this.deleteHandler)
|
ee.off('detail:delete', this.deleteHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmDeletion (permanent) {
|
|
||||||
if (this.props.config.ui.confirmDeletion || permanent) {
|
|
||||||
const electron = require('electron')
|
|
||||||
const { remote } = electron
|
|
||||||
const { dialog } = remote
|
|
||||||
|
|
||||||
const alertConfig = {
|
|
||||||
type: 'warning',
|
|
||||||
message: i18n.__('Confirm note deletion'),
|
|
||||||
detail: i18n.__('This will permanently remove this note.'),
|
|
||||||
buttons: [i18n.__('Confirm'), i18n.__('Cancel')]
|
|
||||||
}
|
|
||||||
|
|
||||||
const dialogueButtonIndex = dialog.showMessageBox(remote.getCurrentWindow(), alertConfig)
|
|
||||||
return dialogueButtonIndex === 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { location, data, config } = this.props
|
const { location, data, config } = this.props
|
||||||
let note = null
|
let note = null
|
||||||
@@ -82,7 +62,6 @@ class Detail extends React.Component {
|
|||||||
<SnippetNoteDetail
|
<SnippetNoteDetail
|
||||||
note={note}
|
note={note}
|
||||||
config={config}
|
config={config}
|
||||||
confirmDeletion={(permanent) => this.confirmDeletion(permanent)}
|
|
||||||
ref='root'
|
ref='root'
|
||||||
{..._.pick(this.props, [
|
{..._.pick(this.props, [
|
||||||
'dispatch',
|
'dispatch',
|
||||||
@@ -99,7 +78,6 @@ class Detail extends React.Component {
|
|||||||
<MarkdownNoteDetail
|
<MarkdownNoteDetail
|
||||||
note={note}
|
note={note}
|
||||||
config={config}
|
config={config}
|
||||||
confirmDeletion={(permanent) => this.confirmDeletion(permanent)}
|
|
||||||
ref='root'
|
ref='root'
|
||||||
{..._.pick(this.props, [
|
{..._.pick(this.props, [
|
||||||
'dispatch',
|
'dispatch',
|
||||||
|
|||||||
@@ -140,43 +140,37 @@ class Main extends React.Component {
|
|||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
const { dispatch, config } = this.props
|
const { dispatch, config } = this.props
|
||||||
|
|
||||||
if (config.ui.theme === 'dark') {
|
const supportedThemes = [
|
||||||
document.body.setAttribute('data-theme', 'dark')
|
'dark',
|
||||||
} else if (config.ui.theme === 'white') {
|
'white',
|
||||||
document.body.setAttribute('data-theme', 'white')
|
'solarized-dark'
|
||||||
} else if (config.ui.theme === 'solarized-dark') {
|
]
|
||||||
document.body.setAttribute('data-theme', 'solarized-dark')
|
|
||||||
|
if (supportedThemes.indexOf(config.ui.theme) !== -1) {
|
||||||
|
document.body.setAttribute('data-theme', config.ui.theme)
|
||||||
} else {
|
} else {
|
||||||
document.body.setAttribute('data-theme', 'default')
|
document.body.setAttribute('data-theme', 'default')
|
||||||
}
|
}
|
||||||
if (config.ui.language === 'sq') {
|
|
||||||
i18n.setLocale('sq')
|
const supportedLanguages = [
|
||||||
} else if (config.ui.language === 'zh-CN') {
|
'sq',
|
||||||
i18n.setLocale('zh-CN')
|
'zh-CN',
|
||||||
} else if (config.ui.language === 'zh-TW') {
|
'zh-TW',
|
||||||
i18n.setLocale('zh-TW')
|
'da',
|
||||||
} else if (config.ui.language === 'da') {
|
'fr',
|
||||||
i18n.setLocale('da')
|
'de',
|
||||||
} else if (config.ui.language === 'fr') {
|
'hu',
|
||||||
i18n.setLocale('fr')
|
'ja',
|
||||||
} else if (config.ui.language === 'de') {
|
'ko',
|
||||||
i18n.setLocale('de')
|
'no',
|
||||||
} else if (config.ui.language === 'hu') {
|
'pl',
|
||||||
i18n.setLocale('hu')
|
'pt',
|
||||||
} else if (config.ui.language === 'ja') {
|
'ru',
|
||||||
i18n.setLocale('ja')
|
'es-ES'
|
||||||
} else if (config.ui.language === 'ko') {
|
]
|
||||||
i18n.setLocale('ko')
|
|
||||||
} else if (config.ui.language === 'no') {
|
if (supportedLanguages.indexOf(config.ui.language) !== -1) {
|
||||||
i18n.setLocale('no')
|
i18n.setLocale(config.ui.language)
|
||||||
} else if (config.ui.language === 'pl') {
|
|
||||||
i18n.setLocale('pl')
|
|
||||||
} else if (config.ui.language === 'pt') {
|
|
||||||
i18n.setLocale('pt')
|
|
||||||
} else if (config.ui.language === 'ru') {
|
|
||||||
i18n.setLocale('ru')
|
|
||||||
} else if (config.ui.language === 'es-ES') {
|
|
||||||
i18n.setLocale('es-ES')
|
|
||||||
} else {
|
} else {
|
||||||
i18n.setLocale('en')
|
i18n.setLocale('en')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import copy from 'copy-to-clipboard'
|
|||||||
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
||||||
import Markdown from '../../lib/markdown'
|
import Markdown from '../../lib/markdown'
|
||||||
import i18n from 'browser/lib/i18n'
|
import i18n from 'browser/lib/i18n'
|
||||||
|
import { confirmDeleteNote } from 'browser/lib/confirmDeleteNote'
|
||||||
|
|
||||||
const { remote } = require('electron')
|
const { remote } = require('electron')
|
||||||
const { Menu, MenuItem, dialog } = remote
|
const { Menu, MenuItem, dialog } = remote
|
||||||
@@ -326,8 +327,10 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (location.pathname.match(/\/searched/)) {
|
if (location.pathname.match(/\/searched/)) {
|
||||||
const searchInputText = document.getElementsByClassName('searchInput')[0].value
|
const searchInputText = params.searchword
|
||||||
if (searchInputText === '') {
|
const allNotes = data.noteMap.map((note) => note)
|
||||||
|
this.contextNotes = allNotes
|
||||||
|
if (searchInputText === undefined || searchInputText === '') {
|
||||||
return this.sortByPin(this.contextNotes)
|
return this.sortByPin(this.contextNotes)
|
||||||
}
|
}
|
||||||
return searchFromNotes(this.contextNotes, searchInputText)
|
return searchFromNotes(this.contextNotes, searchInputText)
|
||||||
@@ -481,50 +484,53 @@ class NoteList extends React.Component {
|
|||||||
const openBlogLabel = i18n.__('Open Blog')
|
const openBlogLabel = i18n.__('Open Blog')
|
||||||
|
|
||||||
const menu = new Menu()
|
const menu = new Menu()
|
||||||
if (!location.pathname.match(/\/starred|\/trash/)) {
|
|
||||||
menu.append(new MenuItem({
|
|
||||||
label: pinLabel,
|
|
||||||
click: this.pinToTop
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (location.pathname.match(/\/trash/)) {
|
if (location.pathname.match(/\/trash/)) {
|
||||||
menu.append(new MenuItem({
|
menu.append(new MenuItem({
|
||||||
label: restoreNote,
|
label: restoreNote,
|
||||||
click: this.restoreNote
|
click: this.restoreNote
|
||||||
}))
|
}))
|
||||||
}
|
menu.append(new MenuItem({
|
||||||
|
label: deleteLabel,
|
||||||
menu.append(new MenuItem({
|
click: this.deleteNote
|
||||||
label: deleteLabel,
|
}))
|
||||||
click: this.deleteNote
|
} else {
|
||||||
}))
|
if (!location.pathname.match(/\/starred/)) {
|
||||||
menu.append(new MenuItem({
|
|
||||||
label: cloneNote,
|
|
||||||
click: this.cloneNote.bind(this)
|
|
||||||
}))
|
|
||||||
menu.append(new MenuItem({
|
|
||||||
label: copyNoteLink,
|
|
||||||
click: this.copyNoteLink(note)
|
|
||||||
}))
|
|
||||||
if (note.type === 'MARKDOWN_NOTE') {
|
|
||||||
if (note.blog && note.blog.blogLink && note.blog.blogId) {
|
|
||||||
menu.append(new MenuItem({
|
menu.append(new MenuItem({
|
||||||
label: updateLabel,
|
label: pinLabel,
|
||||||
click: this.publishMarkdown.bind(this)
|
click: this.pinToTop
|
||||||
}))
|
|
||||||
menu.append(new MenuItem({
|
|
||||||
label: openBlogLabel,
|
|
||||||
click: () => this.openBlog.bind(this)(note)
|
|
||||||
}))
|
|
||||||
} else {
|
|
||||||
menu.append(new MenuItem({
|
|
||||||
label: publishLabel,
|
|
||||||
click: this.publishMarkdown.bind(this)
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
menu.append(new MenuItem({
|
||||||
|
label: deleteLabel,
|
||||||
|
click: this.deleteNote
|
||||||
|
}))
|
||||||
|
menu.append(new MenuItem({
|
||||||
|
label: cloneNote,
|
||||||
|
click: this.cloneNote.bind(this)
|
||||||
|
}))
|
||||||
|
menu.append(new MenuItem({
|
||||||
|
label: copyNoteLink,
|
||||||
|
click: this.copyNoteLink(note)
|
||||||
|
}))
|
||||||
|
if (note.type === 'MARKDOWN_NOTE') {
|
||||||
|
if (note.blog && note.blog.blogLink && note.blog.blogId) {
|
||||||
|
menu.append(new MenuItem({
|
||||||
|
label: updateLabel,
|
||||||
|
click: this.publishMarkdown.bind(this)
|
||||||
|
}))
|
||||||
|
menu.append(new MenuItem({
|
||||||
|
label: openBlogLabel,
|
||||||
|
click: () => this.openBlog.bind(this)(note)
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
menu.append(new MenuItem({
|
||||||
|
label: publishLabel,
|
||||||
|
click: this.publishMarkdown.bind(this)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.popup()
|
menu.popup()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -580,16 +586,11 @@ class NoteList extends React.Component {
|
|||||||
const notes = this.notes.map((note) => Object.assign({}, note))
|
const notes = this.notes.map((note) => Object.assign({}, note))
|
||||||
const selectedNotes = findNotesByKeys(notes, selectedNoteKeys)
|
const selectedNotes = findNotesByKeys(notes, selectedNoteKeys)
|
||||||
const firstNote = selectedNotes[0]
|
const firstNote = selectedNotes[0]
|
||||||
|
const { confirmDeletion } = this.props.config.ui
|
||||||
|
|
||||||
if (firstNote.isTrashed) {
|
if (firstNote.isTrashed) {
|
||||||
const noteExp = selectedNotes.length > 1 ? 'notes' : 'note'
|
if (!confirmDeleteNote(confirmDeletion, true)) return
|
||||||
const dialogueButtonIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
|
|
||||||
type: 'warning',
|
|
||||||
message: i18n.__('Confirm note deletion'),
|
|
||||||
detail: `This will permanently remove ${selectedNotes.length} ${noteExp}.`,
|
|
||||||
buttons: [i18n.__('Confirm'), i18n.__('Cancel')]
|
|
||||||
})
|
|
||||||
if (dialogueButtonIndex === 1) return
|
|
||||||
Promise.all(
|
Promise.all(
|
||||||
selectedNotes.map((note) => {
|
selectedNotes.map((note) => {
|
||||||
return dataApi
|
return dataApi
|
||||||
@@ -610,6 +611,8 @@ class NoteList extends React.Component {
|
|||||||
})
|
})
|
||||||
console.log('Notes were all deleted')
|
console.log('Notes were all deleted')
|
||||||
} else {
|
} else {
|
||||||
|
if (!confirmDeleteNote(confirmDeletion, false)) return
|
||||||
|
|
||||||
Promise.all(
|
Promise.all(
|
||||||
selectedNotes.map((note) => {
|
selectedNotes.map((note) => {
|
||||||
note.isTrashed = true
|
note.isTrashed = true
|
||||||
|
|||||||
@@ -30,11 +30,33 @@
|
|||||||
display flex
|
display flex
|
||||||
flex-direction column
|
flex-direction column
|
||||||
|
|
||||||
.tag-title
|
.tag-control
|
||||||
padding-left 15px
|
display flex
|
||||||
padding-bottom 13px
|
height 30px
|
||||||
p
|
line-height 25px
|
||||||
color $ui-button-default-color
|
overflow hidden
|
||||||
|
.tag-control-title
|
||||||
|
padding-left 15px
|
||||||
|
padding-bottom 13px
|
||||||
|
flex 1
|
||||||
|
p
|
||||||
|
color $ui-button-default-color
|
||||||
|
.tag-control-sortTagsBy
|
||||||
|
user-select none
|
||||||
|
font-size 12px
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
margin-left 12px
|
||||||
|
margin-right 12px
|
||||||
|
.tag-control-sortTagsBy-select
|
||||||
|
appearance: none;
|
||||||
|
margin-left 5px
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
padding 0
|
||||||
|
border none
|
||||||
|
background-color transparent
|
||||||
|
outline none
|
||||||
|
cursor pointer
|
||||||
|
font-size 12px
|
||||||
|
|
||||||
.tagList
|
.tagList
|
||||||
overflow-y auto
|
overflow-y auto
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ class SideNav extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SideNavComponent (isFolded, storageList) {
|
SideNavComponent (isFolded, storageList) {
|
||||||
const { location, data } = this.props
|
const { location, data, config } = this.props
|
||||||
|
|
||||||
const isHomeActive = !!location.pathname.match(/^\/home$/)
|
const isHomeActive = !!location.pathname.match(/^\/home$/)
|
||||||
const isStarredActive = !!location.pathname.match(/^\/starred$/)
|
const isStarredActive = !!location.pathname.match(/^\/starred$/)
|
||||||
@@ -108,15 +108,30 @@ class SideNav extends React.Component {
|
|||||||
handleFilterButtonContextMenu={this.handleFilterButtonContextMenu.bind(this)}
|
handleFilterButtonContextMenu={this.handleFilterButtonContextMenu.bind(this)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<StorageList storageList={storageList} />
|
<StorageList storageList={storageList} isFolded={isFolded} />
|
||||||
<NavToggleButton isFolded={isFolded} handleToggleButtonClick={this.handleToggleButtonClick.bind(this)} />
|
<NavToggleButton isFolded={isFolded} handleToggleButtonClick={this.handleToggleButtonClick.bind(this)} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
component = (
|
component = (
|
||||||
<div styleName='tabBody'>
|
<div styleName='tabBody'>
|
||||||
<div styleName='tag-title'>
|
<div styleName='tag-control'>
|
||||||
<p>{i18n.__('Tags')}</p>
|
<div styleName='tag-control-title'>
|
||||||
|
<p>{i18n.__('Tags')}</p>
|
||||||
|
</div>
|
||||||
|
<div styleName='tag-control-sortTagsBy'>
|
||||||
|
<i className='fa fa-angle-down' />
|
||||||
|
<select styleName='tag-control-sortTagsBy-select'
|
||||||
|
title={i18n.__('Select filter mode')}
|
||||||
|
value={config.sortTagsBy}
|
||||||
|
onChange={(e) => this.handleSortTagsByChange(e)}
|
||||||
|
>
|
||||||
|
<option title='Sort alphabetically'
|
||||||
|
value='ALPHABETICAL'>{i18n.__('Alphabetically')}</option>
|
||||||
|
<option title='Sort by update time'
|
||||||
|
value='COUNTER'>{i18n.__('Counter')}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div styleName='tagList'>
|
<div styleName='tagList'>
|
||||||
{this.tagListComponent(data)}
|
{this.tagListComponent(data)}
|
||||||
@@ -129,17 +144,21 @@ class SideNav extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tagListComponent () {
|
tagListComponent () {
|
||||||
const { data, location } = this.props
|
const { data, location, config } = this.props
|
||||||
const tagList = _.sortBy(data.tagNoteMap.map((tag, name) => {
|
let tagList = _.sortBy(data.tagNoteMap.map(
|
||||||
return { name, size: tag.size }
|
(tag, name) => ({name, size: tag.size})),
|
||||||
}), ['name'])
|
['name']
|
||||||
|
)
|
||||||
|
if (config.sortTagsBy === 'COUNTER') {
|
||||||
|
tagList = _.sortBy(tagList, item => (0 - item.size))
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
tagList.map(tag => {
|
tagList.map(tag => {
|
||||||
return (
|
return (
|
||||||
<TagListItem
|
<TagListItem
|
||||||
name={tag.name}
|
name={tag.name}
|
||||||
handleClickTagListItem={this.handleClickTagListItem.bind(this)}
|
handleClickTagListItem={this.handleClickTagListItem.bind(this)}
|
||||||
isActive={this.getTagActive(location.pathname, tag)}
|
isActive={this.getTagActive(location.pathname, tag.name)}
|
||||||
key={tag.name}
|
key={tag.name}
|
||||||
count={tag.size}
|
count={tag.size}
|
||||||
/>
|
/>
|
||||||
@@ -159,6 +178,20 @@ class SideNav extends React.Component {
|
|||||||
router.push(`/tags/${name}`)
|
router.push(`/tags/${name}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleSortTagsByChange (e) {
|
||||||
|
const { dispatch } = this.props
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
sortTagsBy: e.target.value
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigManager.set(config)
|
||||||
|
dispatch({
|
||||||
|
type: 'SET_CONFIG',
|
||||||
|
config
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
emptyTrash (entries) {
|
emptyTrash (entries) {
|
||||||
const { dispatch } = this.props
|
const { dispatch } = this.props
|
||||||
const deletionPromises = entries.map((note) => {
|
const deletionPromises = entries.map((note) => {
|
||||||
|
|||||||
@@ -28,6 +28,14 @@ class TopBar extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
|
const { params } = this.props
|
||||||
|
const searchWord = params.searchword
|
||||||
|
if (searchWord !== undefined) {
|
||||||
|
this.setState({
|
||||||
|
search: searchWord,
|
||||||
|
isSearching: true
|
||||||
|
})
|
||||||
|
}
|
||||||
ee.on('top:focus-search', this.focusSearchHandler)
|
ee.on('top:focus-search', this.focusSearchHandler)
|
||||||
ee.on('code:init', this.codeInitHandler)
|
ee.on('code:init', this.codeInitHandler)
|
||||||
}
|
}
|
||||||
@@ -97,9 +105,10 @@ class TopBar extends React.Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
isConfirmTranslation: true
|
isConfirmTranslation: true
|
||||||
})
|
})
|
||||||
router.push('/searched')
|
const keyword = this.refs.searchInput.value
|
||||||
|
router.push(`/searched/${encodeURIComponent(keyword)}`)
|
||||||
this.setState({
|
this.setState({
|
||||||
search: this.refs.searchInput.value
|
search: keyword
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,7 +117,7 @@ class TopBar extends React.Component {
|
|||||||
const { router } = this.context
|
const { router } = this.context
|
||||||
const keyword = this.refs.searchInput.value
|
const keyword = this.refs.searchInput.value
|
||||||
if (this.state.isAlphabet || this.state.isConfirmTranslation) {
|
if (this.state.isAlphabet || this.state.isConfirmTranslation) {
|
||||||
router.push('/searched')
|
router.push(`/searched/${encodeURIComponent(keyword)}`)
|
||||||
} else {
|
} else {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,6 +108,21 @@ body[data-theme="dark"]
|
|||||||
background #B1D7FE
|
background #B1D7FE
|
||||||
::selection
|
::selection
|
||||||
background #B1D7FE
|
background #B1D7FE
|
||||||
|
.CodeMirror-foldmarker
|
||||||
|
font-family: arial
|
||||||
|
|
||||||
|
.CodeMirror-foldgutter
|
||||||
|
width: .7em
|
||||||
|
|
||||||
|
.CodeMirror-foldgutter-open,
|
||||||
|
.CodeMirror-foldgutter-folded
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
|
.CodeMirror-foldgutter-open:after
|
||||||
|
content: "\25BE"
|
||||||
|
|
||||||
|
.CodeMirror-foldgutter-folded:after
|
||||||
|
content: "\25B8"
|
||||||
|
|
||||||
.sortableItemHelper
|
.sortableItemHelper
|
||||||
z-index modalZIndex + 5
|
z-index modalZIndex + 5
|
||||||
|
|||||||
@@ -24,6 +24,45 @@ document.addEventListener('dragover', function (e) {
|
|||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// prevent menu from popup when alt pressed
|
||||||
|
// but still able to toggle menu when only alt is pressed
|
||||||
|
let isAltPressing = false
|
||||||
|
let isAltWithMouse = false
|
||||||
|
let isAltWithOtherKey = false
|
||||||
|
let isOtherKey = false
|
||||||
|
|
||||||
|
document.addEventListener('keydown', function (e) {
|
||||||
|
if (e.key === 'Alt') {
|
||||||
|
isAltPressing = true
|
||||||
|
if (isOtherKey) {
|
||||||
|
isAltWithOtherKey = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isAltPressing) {
|
||||||
|
isAltWithOtherKey = true
|
||||||
|
}
|
||||||
|
isOtherKey = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
document.addEventListener('mousedown', function (e) {
|
||||||
|
if (isAltPressing) {
|
||||||
|
isAltWithMouse = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
document.addEventListener('keyup', function (e) {
|
||||||
|
if (e.key === 'Alt') {
|
||||||
|
if (isAltWithMouse || isAltWithOtherKey) {
|
||||||
|
e.preventDefault()
|
||||||
|
}
|
||||||
|
isAltWithMouse = false
|
||||||
|
isAltWithOtherKey = false
|
||||||
|
isAltPressing = false
|
||||||
|
isOtherKey = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
document.addEventListener('click', function (e) {
|
document.addEventListener('click', function (e) {
|
||||||
const className = e.target.className
|
const className = e.target.className
|
||||||
if (!className && typeof (className) !== 'string') return
|
if (!className && typeof (className) !== 'string') return
|
||||||
@@ -64,7 +103,9 @@ ReactDOM.render((
|
|||||||
<IndexRedirect to='/home' />
|
<IndexRedirect to='/home' />
|
||||||
<Route path='home' />
|
<Route path='home' />
|
||||||
<Route path='starred' />
|
<Route path='starred' />
|
||||||
<Route path='searched' />
|
<Route path='searched'>
|
||||||
|
<Route path=':searchword' />
|
||||||
|
</Route>
|
||||||
<Route path='trashed' />
|
<Route path='trashed' />
|
||||||
<Route path='alltags' />
|
<Route path='alltags' />
|
||||||
<Route path='tags'>
|
<Route path='tags'>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export const DEFAULT_CONFIG = {
|
|||||||
listWidth: 280,
|
listWidth: 280,
|
||||||
navWidth: 200,
|
navWidth: 200,
|
||||||
sortBy: 'UPDATED_AT', // 'CREATED_AT', 'UPDATED_AT', 'APLHABETICAL'
|
sortBy: 'UPDATED_AT', // 'CREATED_AT', 'UPDATED_AT', 'APLHABETICAL'
|
||||||
|
sortTagsBy: 'ALPHABETICAL', // 'ALPHABETICAL', 'COUNTER'
|
||||||
listStyle: 'DEFAULT', // 'DEFAULT', 'SMALL'
|
listStyle: 'DEFAULT', // 'DEFAULT', 'SMALL'
|
||||||
amaEnabled: true,
|
amaEnabled: true,
|
||||||
hotkey: {
|
hotkey: {
|
||||||
@@ -138,37 +139,7 @@ function set (updates) {
|
|||||||
document.body.setAttribute('data-theme', 'default')
|
document.body.setAttribute('data-theme', 'default')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newConfig.ui.language === 'sq') {
|
i18n.setLocale(newConfig.ui.language)
|
||||||
i18n.setLocale('sq')
|
|
||||||
} else if (newConfig.ui.language === 'zh-CN') {
|
|
||||||
i18n.setLocale('zh-CN')
|
|
||||||
} else if (newConfig.ui.language === 'zh-TW') {
|
|
||||||
i18n.setLocale('zh-TW')
|
|
||||||
} else if (newConfig.ui.language === 'da') {
|
|
||||||
i18n.setLocale('da')
|
|
||||||
} else if (newConfig.ui.language === 'fr') {
|
|
||||||
i18n.setLocale('fr')
|
|
||||||
} else if (newConfig.ui.language === 'de') {
|
|
||||||
i18n.setLocale('de')
|
|
||||||
} else if (newConfig.ui.language === 'hu') {
|
|
||||||
i18n.setLocale('hu')
|
|
||||||
} else if (newConfig.ui.language === 'ja') {
|
|
||||||
i18n.setLocale('ja')
|
|
||||||
} else if (newConfig.ui.language === 'ko') {
|
|
||||||
i18n.setLocale('ko')
|
|
||||||
} else if (newConfig.ui.language === 'no') {
|
|
||||||
i18n.setLocale('no')
|
|
||||||
} else if (newConfig.ui.language === 'pl') {
|
|
||||||
i18n.setLocale('pl')
|
|
||||||
} else if (newConfig.ui.language === 'pt') {
|
|
||||||
i18n.setLocale('pt')
|
|
||||||
} else if (newConfig.ui.language === 'ru') {
|
|
||||||
i18n.setLocale('ru')
|
|
||||||
} else if (newConfig.ui.language === 'es-ES') {
|
|
||||||
i18n.setLocale('es-ES')
|
|
||||||
} else {
|
|
||||||
i18n.setLocale('en')
|
|
||||||
}
|
|
||||||
|
|
||||||
let editorTheme = document.getElementById('editorTheme')
|
let editorTheme = document.getElementById('editorTheme')
|
||||||
if (editorTheme == null) {
|
if (editorTheme == null) {
|
||||||
|
|||||||
@@ -27,9 +27,12 @@ function resolveStorageNotes (storage) {
|
|||||||
data.storage = storage.key
|
data.storage = storage.key
|
||||||
return data
|
return data
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(notePath)
|
console.error(`error on note path: ${notePath}, error: ${err}`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.filter(function filterOnlyNoteObject (noteObj) {
|
||||||
|
return typeof noteObj === 'object'
|
||||||
|
})
|
||||||
|
|
||||||
return Promise.resolve(notes)
|
return Promise.resolve(notes)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,9 +194,10 @@ class UiTab extends React.Component {
|
|||||||
<option value='ko'>{i18n.__('Korean')}</option>
|
<option value='ko'>{i18n.__('Korean')}</option>
|
||||||
<option value='no'>{i18n.__('Norwegian')}</option>
|
<option value='no'>{i18n.__('Norwegian')}</option>
|
||||||
<option value='pl'>{i18n.__('Polish')}</option>
|
<option value='pl'>{i18n.__('Polish')}</option>
|
||||||
<option value='pt'>{i18n.__('Portuguese')}</option>
|
<option value='pt-BR'>{i18n.__('Portuguese (Brazil)')}</option>
|
||||||
|
<option value='pt-PT'>{i18n.__('Portuguese (Portugal)')}</option>
|
||||||
<option value='ru'>{i18n.__('Russian')}</option>
|
<option value='ru'>{i18n.__('Russian')}</option>
|
||||||
<option value='es'>{i18n.__('Spanish')}</option>
|
<option value='es-ES'>{i18n.__('Spanish')}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -85,6 +85,7 @@
|
|||||||
<script src="../extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js"></script>
|
<script src="../extra_scripts/boost/boostNewLineIndentContinueMarkdownList.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/search/search.js"></script>
|
<script src="../node_modules/codemirror/addon/search/search.js"></script>
|
||||||
<script src="../node_modules/codemirror/addon/search/searchcursor.js"></script>
|
<script src="../node_modules/codemirror/addon/search/searchcursor.js"></script>
|
||||||
@@ -92,6 +93,11 @@
|
|||||||
<script src="../node_modules/codemirror/addon/scroll/scrollpastend.js"></script>
|
<script src="../node_modules/codemirror/addon/scroll/scrollpastend.js"></script>
|
||||||
<script src="../node_modules/codemirror/addon/search/matchesonscrollbar.js"></script>
|
<script src="../node_modules/codemirror/addon/search/matchesonscrollbar.js"></script>
|
||||||
<script src="../node_modules/codemirror/addon/search/jump-to-line.js"></script>
|
<script src="../node_modules/codemirror/addon/search/jump-to-line.js"></script>
|
||||||
|
|
||||||
|
<script src="../node_modules/codemirror/addon/fold/brace-fold.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/fold/foldgutter.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/fold/foldcode.js"></script>
|
||||||
|
|
||||||
<script src="../node_modules/codemirror/addon/dialog/dialog.js"></script>
|
<script src="../node_modules/codemirror/addon/dialog/dialog.js"></script>
|
||||||
<script src="../node_modules/codemirror/addon/display/rulers.js"></script>
|
<script src="../node_modules/codemirror/addon/display/rulers.js"></script>
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,7 @@
|
|||||||
"Updated": "Updated",
|
"Updated": "Updated",
|
||||||
"Created": "Created",
|
"Created": "Created",
|
||||||
"Alphabetically": "Alphabetically",
|
"Alphabetically": "Alphabetically",
|
||||||
|
"Counter": "Counter",
|
||||||
"Default View": "Default View",
|
"Default View": "Default View",
|
||||||
"Compressed View": "Compressed View",
|
"Compressed View": "Compressed View",
|
||||||
"Search": "Search",
|
"Search": "Search",
|
||||||
|
|||||||
@@ -111,6 +111,7 @@
|
|||||||
"Updated": "Módosítás",
|
"Updated": "Módosítás",
|
||||||
"Created": "Létrehozás",
|
"Created": "Létrehozás",
|
||||||
"Alphabetically": "Ábécé sorrendben",
|
"Alphabetically": "Ábécé sorrendben",
|
||||||
|
"Counter": "Számláló",
|
||||||
"Default View": "Alapértelmezett Nézet",
|
"Default View": "Alapértelmezett Nézet",
|
||||||
"Compressed View": "Tömörített Nézet",
|
"Compressed View": "Tömörített Nézet",
|
||||||
"Search": "Keresés",
|
"Search": "Keresés",
|
||||||
|
|||||||
232
locales/zh-CN.json
Normal file → Executable file
232
locales/zh-CN.json
Normal file → Executable file
@@ -1,138 +1,138 @@
|
|||||||
{
|
{
|
||||||
"Notes": "Notes",
|
"Notes": "笔记",
|
||||||
"Tags": "Tags",
|
"Tags": "标签",
|
||||||
"Preferences": "Preferences",
|
"Preferences": "首选项",
|
||||||
"Make a note": "Make a note",
|
"Make a note": "新建笔记",
|
||||||
"Ctrl": "Ctrl",
|
"Ctrl": "Ctrl",
|
||||||
"Ctrl(^)": "Ctrl",
|
"Ctrl(^)": "Ctrl",
|
||||||
"to create a new note": "to create a new note",
|
"to create a new note": "新建笔记",
|
||||||
"Toggle Mode": "Toggle Mode",
|
"Toggle Mode": "切换模式",
|
||||||
"Trash": "Trash",
|
"Trash": "废纸篓",
|
||||||
"MODIFICATION DATE": "MODIFICATION DATE",
|
"MODIFICATION DATE": "更改时间",
|
||||||
"Words": "Words",
|
"Words": "单词",
|
||||||
"Letters": "Letters",
|
"Letters": "字数",
|
||||||
"STORAGE": "STORAGE",
|
"STORAGE": "本地存储",
|
||||||
"FOLDER": "FOLDER",
|
"FOLDER": "文件夹",
|
||||||
"CREATION DATE": "CREATION DATE",
|
"CREATION DATE": "创建时间",
|
||||||
"NOTE LINK": "NOTE LINK",
|
"NOTE LINK": "笔记链接",
|
||||||
".md": ".md",
|
".md": ".md",
|
||||||
".txt": ".txt",
|
".txt": ".txt",
|
||||||
".html": ".html",
|
".html": ".html",
|
||||||
"Print": "Print",
|
"Print": "打印",
|
||||||
"Your preferences for Boostnote": "Your preferences for Boostnote",
|
"Your preferences for Boostnote": "个性设置",
|
||||||
"Storages": "Storages",
|
"Storages": "本地存储",
|
||||||
"Add Storage Location": "Add Storage Location",
|
"Add Storage Location": "添加一个本地存储位置",
|
||||||
"Add Folder": "Add Folder",
|
"Add Folder": "新建文件夹",
|
||||||
"Open Storage folder": "Open Storage folder",
|
"Open Storage folder": "打开本地存储位置",
|
||||||
"Unlink": "Unlink",
|
"Unlink": "取消链接",
|
||||||
"Edit": "Edit",
|
"Edit": "编辑",
|
||||||
"Delete": "Delete",
|
"Delete": "删除",
|
||||||
"Interface": "Interface",
|
"Interface": "界面",
|
||||||
"Interface Theme": "Interface Theme",
|
"Interface Theme": "主题",
|
||||||
"Default": "Default",
|
"Default": "默认",
|
||||||
"White": "White",
|
"White": "White",
|
||||||
"Solarized Dark": "Solarized Dark",
|
"Solarized Dark": "Solarized Dark",
|
||||||
"Dark": "Dark",
|
"Dark": "Dark",
|
||||||
"Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes",
|
"Show a confirmation dialog when deleting notes": "删除笔记的时候,显示确认框",
|
||||||
"Editor Theme": "Editor Theme",
|
"Editor Theme": "编辑器主题",
|
||||||
"Editor Font Size": "Editor Font Size",
|
"Editor Font Size": "编辑器字号",
|
||||||
"Editor Font Family": "Editor Font Family",
|
"Editor Font Family": "编辑器字体",
|
||||||
"Editor Indent Style": "Editor Indent Style",
|
"Editor Indent Style": "缩进风格",
|
||||||
"Spaces": "Spaces",
|
"Spaces": "空格",
|
||||||
"Tabs": "Tabs",
|
"Tabs": "Tabs",
|
||||||
"Switch to Preview": "Switch to Preview",
|
"Switch to Preview": "快速切换到预览界面",
|
||||||
"When Editor Blurred": "When Editor Blurred",
|
"When Editor Blurred": "当编辑器失去焦点的时候,切换到预览界面",
|
||||||
"When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click",
|
"When Editor Blurred, Edit On Double Click": "当编辑器失去焦点的时候预览,双击切换到编辑界面",
|
||||||
"On Right Click": "On Right Click",
|
"On Right Click": "右键点击切换两个界面",
|
||||||
"Editor Keymap": "Editor Keymap",
|
"Editor Keymap": "编辑器 Keymap",
|
||||||
"default": "default",
|
"default": "默认",
|
||||||
"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": "⚠️ 设置好快捷键后,记得重启boostnote",
|
||||||
"Show line numbers in the editor": "Show line numbers in the editor",
|
"Show line numbers in the editor": "在编辑器中显示行号",
|
||||||
"Allow editor to scroll past the last line": "Allow editor to scroll past the last line",
|
"Allow editor to scroll past the last line": "允许编辑器滚动到最后一行",
|
||||||
"Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor",
|
"Bring in web page title when pasting URL on editor": "粘贴网页链接的时候,显示为网页标题",
|
||||||
"Preview": "Preview",
|
"Preview": "预览器",
|
||||||
"Preview Font Size": "Preview Font Size",
|
"Preview Font Size": "预览器字号",
|
||||||
"Preview Font Family": "Preview Font Family",
|
"Preview Font Family": "预览器字体",
|
||||||
"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": "允许预览器滚动到最后一行",
|
||||||
"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 单行开头分隔符",
|
||||||
"LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter",
|
"LaTeX Inline Close Delimiter": "LaTeX 单行结尾分隔符",
|
||||||
"LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter",
|
"LaTeX Block Open Delimiter": "LaTeX 多行开头分隔符",
|
||||||
"LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter",
|
"LaTeX Block Close Delimiter": "LaTeX 多行结尾分隔符",
|
||||||
"Community": "Community",
|
"Community": "社区",
|
||||||
"Subscribe to Newsletter": "Subscribe to Newsletter",
|
"Subscribe to Newsletter": "订阅邮件",
|
||||||
"GitHub": "GitHub",
|
"GitHub": "GitHub",
|
||||||
"Blog": "Blog",
|
"Blog": "博客",
|
||||||
"Facebook Group": "Facebook Group",
|
"Facebook Group": "Facebook Group",
|
||||||
"Twitter": "Twitter",
|
"Twitter": "Twitter",
|
||||||
"About": "About",
|
"About": "关于",
|
||||||
"Boostnote": "Boostnote",
|
"Boostnote": "Boostnote",
|
||||||
"An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.",
|
"An open source note-taking app made for programmers just like you.": "一款专门为程序员朋友量身打造的开源笔记",
|
||||||
"Website": "Website",
|
"Website": "官网",
|
||||||
"Development": "Development",
|
"Development": "开发",
|
||||||
" : Development configurations for Boostnote.": " : Development configurations for Boostnote.",
|
" : Development configurations for Boostnote.": " : 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": "License: GPL v3",
|
||||||
"Analytics": "Analytics",
|
"Analytics": "分析",
|
||||||
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "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 收集匿名数据只为了提升软件使用体验,绝对不收集任何个人信息(包括笔记内容)",
|
||||||
"You can see how it works on ": "You can see how it works on ",
|
"You can see how it works on ": "你可以看看它的源码是如何运作的 ",
|
||||||
"You can choose to enable or disable this option.": "You can choose to enable or disable this option.",
|
"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": "允许对数据进行分析,帮助我们改进Boostnote",
|
||||||
"Crowdfunding": "Crowdfunding",
|
"Crowdfunding": "众筹",
|
||||||
"Dear everyone,": "Dear everyone,",
|
"Dear everyone,": "亲爱的用户:",
|
||||||
"Thank you for using Boostnote!": "Thank you for using Boostnote!",
|
"Thank you for using Boostnote!": "谢谢你使用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.": "大约有200个不同的国家和地区的优秀开发者们都在使用Boostnote!",
|
||||||
"To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,",
|
"To continue supporting this growth, and to 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.": "我们非常愿意投入更多的时间和资源到这个项目中。",
|
||||||
"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 like this project and see its potential, you can help by supporting us on OpenCollective!": "如果你喜欢这款软件并且看好它的潜力, 请在OpenCollective上支持我们!",
|
||||||
"Thanks,": "Thanks,",
|
"Thanks,": "十分感谢!",
|
||||||
"Boostnote maintainers": "Boostnote maintainers",
|
"Boostnote maintainers": "Boostnote的维护人员",
|
||||||
"Support via OpenCollective": "Support via OpenCollective",
|
"Support via OpenCollective": "在OpenCollective上支持我们",
|
||||||
"Language": "Language",
|
"Language": "语言",
|
||||||
"English": "English",
|
"English": "English",
|
||||||
"German": "German",
|
"German": "German",
|
||||||
"French": "French",
|
"French": "French",
|
||||||
"Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying",
|
"Show \"Saved to Clipboard\" notification when copying": "复制的时候,显示 \"已复制\" 提示",
|
||||||
"All Notes": "All Notes",
|
"All Notes": "所有笔记",
|
||||||
"Starred": "Starred",
|
"Starred": "星标收藏",
|
||||||
"Are you sure to ": "Are you sure to ",
|
"Are you sure to ": "你确定要",
|
||||||
" delete": " delete",
|
" delete": " 删除",
|
||||||
"this folder?": "this folder?",
|
"this folder?": "这个文件夹?",
|
||||||
"Confirm": "Confirm",
|
"Confirm": "确认",
|
||||||
"Cancel": "Cancel",
|
"Cancel": "取消",
|
||||||
"Markdown Note": "Markdown Note",
|
"Markdown Note": "Markdown笔记",
|
||||||
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.",
|
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "创建文档,清单,代码块甚至是Latex格式文档",
|
||||||
"Snippet Note": "Snippet Note",
|
"Snippet 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.",
|
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "创建代码片段,支持多种语法代码片段",
|
||||||
"Tab to switch format": "Tab to switch format",
|
"Tab to switch format": "使用Tab键切换格式",
|
||||||
"Updated": "Updated",
|
"Updated": "更新时间",
|
||||||
"Created": "Created",
|
"Created": "创建时间",
|
||||||
"Alphabetically": "Alphabetically",
|
"Alphabetically": "A~Z排序",
|
||||||
"Default View": "Default View",
|
"Default View": "默认视图",
|
||||||
"Compressed View": "Compressed View",
|
"Compressed View": "列表视图",
|
||||||
"Search": "Search",
|
"Search": "搜索",
|
||||||
"Blog Type": "Blog Type",
|
"Blog Type": "博客类型",
|
||||||
"Blog Address": "Blog Address",
|
"Blog Address": "博客地址",
|
||||||
"Save": "Save",
|
"Save": "保存",
|
||||||
"Auth": "Auth",
|
"Auth": "Auth",
|
||||||
"Authentication Method": "Authentication Method",
|
"Authentication Method": "认证方法",
|
||||||
"JWT": "JWT",
|
"JWT": "JWT",
|
||||||
"USER": "USER",
|
"USER": "USER",
|
||||||
"Token": "Token",
|
"Token": "Token",
|
||||||
"Storage": "Storage",
|
"Storage": "本地存储",
|
||||||
"Hotkeys": "Hotkeys",
|
"Hotkeys": "快捷键",
|
||||||
"Show/Hide Boostnote": "Show/Hide Boostnote",
|
"Show/Hide Boostnote": "显示/隐藏 Boostnote",
|
||||||
"Restore": "Restore",
|
"Restore": "恢复",
|
||||||
"Permanent Delete": "Permanent Delete",
|
"Permanent Delete": "永久删除",
|
||||||
"Confirm note deletion": "Confirm note deletion",
|
"Confirm note deletion": "确认删除笔记",
|
||||||
"This will permanently remove this note.": "This will permanently remove this note.",
|
"This will permanently remove this note.": "永久地删除这条笔记",
|
||||||
"Successfully applied!": "Successfully applied!",
|
"Successfully applied!": "设置成功",
|
||||||
"Albanian": "Albanian",
|
"Albanian": "Albanian",
|
||||||
"Chinese (zh-CN)": "Chinese (zh-CN)",
|
"Chinese (zh-CN)": "简体中文",
|
||||||
"Chinese (zh-TW)": "Chinese (zh-TW)",
|
"Chinese (zh-TW)": "繁體中文",
|
||||||
"Danish": "Danish",
|
"Danish": "Danish",
|
||||||
"Japanese": "Japanese",
|
"Japanese": "Japanese",
|
||||||
"Korean": "Korean",
|
"Korean": "Korean",
|
||||||
@@ -140,13 +140,13 @@
|
|||||||
"Polish": "Polish",
|
"Polish": "Polish",
|
||||||
"Portuguese": "Portuguese",
|
"Portuguese": "Portuguese",
|
||||||
"Spanish": "Spanish",
|
"Spanish": "Spanish",
|
||||||
"You have to save!": "You have to save!",
|
"You have to save!": "你必须保存一下!",
|
||||||
"Russian": "Russian",
|
"Russian": "Russian",
|
||||||
"Editor Rulers": "Editor Rulers",
|
"Editor Rulers": "Editor Rulers",
|
||||||
"Enable": "Enable",
|
"Enable": "开启",
|
||||||
"Disable": "Disable",
|
"Disable": "关闭",
|
||||||
"Sanitization": "Sanitization",
|
"Sanitization": "代码处理",
|
||||||
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
|
"Only allow secure html tags (recommended)": "只允许安全的html标签(推荐)",
|
||||||
"Allow styles": "Allow styles",
|
"Allow styles": "允许样式",
|
||||||
"Allow dangerous html tags": "Allow dangerous html tags"
|
"Allow dangerous html tags": "允许危险的html标签"
|
||||||
}
|
}
|
||||||
|
|||||||
232
locales/zh-TW.json
Normal file → Executable file
232
locales/zh-TW.json
Normal file → Executable file
@@ -1,138 +1,138 @@
|
|||||||
{
|
{
|
||||||
"Notes": "Notes",
|
"Notes": "筆記",
|
||||||
"Tags": "Tags",
|
"Tags": "標籤",
|
||||||
"Preferences": "Preferences",
|
"Preferences": "首選項",
|
||||||
"Make a note": "Make a note",
|
"Make a note": "新建筆記",
|
||||||
"Ctrl": "Ctrl",
|
"Ctrl": "Ctrl",
|
||||||
"Ctrl(^)": "Ctrl",
|
"Ctrl(^)": "Ctrl",
|
||||||
"to create a new note": "to create a new note",
|
"to create a new note": "新建筆記",
|
||||||
"Toggle Mode": "Toggle Mode",
|
"Toggle Mode": "切換模式",
|
||||||
"Trash": "Trash",
|
"Trash": "廢紙簍",
|
||||||
"MODIFICATION DATE": "MODIFICATION DATE",
|
"MODIFICATION DATE": "更改時間",
|
||||||
"Words": "Words",
|
"Words": "單詞",
|
||||||
"Letters": "Letters",
|
"Letters": "字數",
|
||||||
"STORAGE": "STORAGE",
|
"STORAGE": "本地儲存",
|
||||||
"FOLDER": "FOLDER",
|
"FOLDER": "資料夾",
|
||||||
"CREATION DATE": "CREATION DATE",
|
"CREATION DATE": "創建時間",
|
||||||
"NOTE LINK": "NOTE LINK",
|
"NOTE LINK": "筆記鏈接",
|
||||||
".md": ".md",
|
".md": ".md",
|
||||||
".txt": ".txt",
|
".txt": ".txt",
|
||||||
".html": ".html",
|
".html": ".html",
|
||||||
"Print": "Print",
|
"Print": "列印",
|
||||||
"Your preferences for Boostnote": "Your preferences for Boostnote",
|
"Your preferences for Boostnote": "個性設置",
|
||||||
"Storages": "Storages",
|
"Storages": "本地儲存",
|
||||||
"Add Storage Location": "Add Storage Location",
|
"Add Storage Location": "添加一個本地儲存位置",
|
||||||
"Add Folder": "Add Folder",
|
"Add Folder": "新建資料夾",
|
||||||
"Open Storage folder": "Open Storage folder",
|
"Open Storage folder": "打開一個本地儲存位置",
|
||||||
"Unlink": "Unlink",
|
"Unlink": "取消鏈接",
|
||||||
"Edit": "Edit",
|
"Edit": "編輯",
|
||||||
"Delete": "Delete",
|
"Delete": "刪除",
|
||||||
"Interface": "Interface",
|
"Interface": "界面",
|
||||||
"Interface Theme": "Interface Theme",
|
"Interface Theme": "主題",
|
||||||
"Default": "Default",
|
"Default": "默認",
|
||||||
"White": "White",
|
"White": "White",
|
||||||
"Solarized Dark": "Solarized Dark",
|
"Solarized Dark": "Solarized Dark",
|
||||||
"Dark": "Dark",
|
"Dark": "Dark",
|
||||||
"Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes",
|
"Show a confirmation dialog when deleting notes": "刪除筆記的時候,顯示確認框",
|
||||||
"Editor Theme": "Editor Theme",
|
"Editor Theme": "編輯器主題",
|
||||||
"Editor Font Size": "Editor Font Size",
|
"Editor Font Size": "編輯器字型大小",
|
||||||
"Editor Font Family": "Editor Font Family",
|
"Editor Font Family": "編輯器字體",
|
||||||
"Editor Indent Style": "Editor Indent Style",
|
"Editor Indent Style": "縮進風格",
|
||||||
"Spaces": "Spaces",
|
"Spaces": "空格",
|
||||||
"Tabs": "Tabs",
|
"Tabs": "Tabs",
|
||||||
"Switch to Preview": "Switch to Preview",
|
"Switch to Preview": "快速切換到預覽界面",
|
||||||
"When Editor Blurred": "When Editor Blurred",
|
"When Editor Blurred": "當編輯器失去焦點的時候,切換到預覽界面",
|
||||||
"When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click",
|
"When Editor Blurred, Edit On Double Click": "當編輯器失去焦點的時候預覽,雙擊切換到編輯界面",
|
||||||
"On Right Click": "On Right Click",
|
"On Right Click": "右鍵點擊切換兩個界面",
|
||||||
"Editor Keymap": "Editor Keymap",
|
"Editor Keymap": "編輯器 Keymap",
|
||||||
"default": "default",
|
"default": "默認",
|
||||||
"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": "⚠️ 設置好快捷鍵後,記得重啟设置好快捷键后,记得重启boostnote",
|
||||||
"Show line numbers in the editor": "Show line numbers in the editor",
|
"Show line numbers in the editor": "在編輯器中顯示行號",
|
||||||
"Allow editor to scroll past the last line": "Allow editor to scroll past the last line",
|
"Allow editor to scroll past the last line": "允許編輯器滾動到最後一行",
|
||||||
"Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor",
|
"Bring in web page title when pasting URL on editor": "粘貼網頁鏈接的時候,顯示為網頁標題",
|
||||||
"Preview": "Preview",
|
"Preview": "預覽器",
|
||||||
"Preview Font Size": "Preview Font Size",
|
"Preview Font Size": "預覽器字型大小",
|
||||||
"Preview Font Family": "Preview Font Family",
|
"Preview Font Family": "預覽器字體",
|
||||||
"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": "允許預覽器滾動到最後一行",
|
||||||
"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 單行開頭分隔符",
|
||||||
"LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter",
|
"LaTeX Inline Close Delimiter": "LaTeX 單行結尾分隔符",
|
||||||
"LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter",
|
"LaTeX Block Open Delimiter": "LaTeX 多行開頭分隔符",
|
||||||
"LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter",
|
"LaTeX Block Close Delimiter": "LaTeX 多行結尾分隔符",
|
||||||
"Community": "Community",
|
"Community": "社區",
|
||||||
"Subscribe to Newsletter": "Subscribe to Newsletter",
|
"Subscribe to Newsletter": "訂閱郵件",
|
||||||
"GitHub": "GitHub",
|
"GitHub": "GitHub",
|
||||||
"Blog": "Blog",
|
"Blog": "部落格",
|
||||||
"Facebook Group": "Facebook Group",
|
"Facebook Group": "Facebook Group",
|
||||||
"Twitter": "Twitter",
|
"Twitter": "Twitter",
|
||||||
"About": "About",
|
"About": "關於",
|
||||||
"Boostnote": "Boostnote",
|
"Boostnote": "Boostnote",
|
||||||
"An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.",
|
"An open source note-taking app made for programmers just like you.": "一款專門為程式員朋友量身打造的開源筆記",
|
||||||
"Website": "Website",
|
"Website": "官網",
|
||||||
"Development": "Development",
|
"Development": "開發",
|
||||||
" : Development configurations for Boostnote.": " : Development configurations for Boostnote.",
|
" : Development configurations for Boostnote.": " : 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": "License: GPL v3",
|
||||||
"Analytics": "Analytics",
|
"Analytics": "分析",
|
||||||
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "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 收集匿名數據只為了提升軟體使用體驗,絕對不收集任何個人信息(包括筆記內容)",
|
||||||
"You can see how it works on ": "You can see how it works on ",
|
"You can see how it works on ": "你可以看看它的源碼是如何運作的 ",
|
||||||
"You can choose to enable or disable this option.": "You can choose to enable or disable this option.",
|
"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": "允許對數據進行分析,幫助我們改進Boostnote",
|
||||||
"Crowdfunding": "Crowdfunding",
|
"Crowdfunding": "眾籌",
|
||||||
"Dear everyone,": "Dear everyone,",
|
"Dear everyone,": "親愛的用戶:",
|
||||||
"Thank you for using Boostnote!": "Thank you for using Boostnote!",
|
"Thank you for using Boostnote!": "謝謝你使用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.": "大約有200個不同的國家和地區的優秀開發者們都在使用Boostnote!",
|
||||||
"To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,",
|
"To continue supporting this growth, and to 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.": "我們非常願意投入更多的時間和資源到這個專案中。",
|
||||||
"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 like this project and see its potential, you can help by supporting us on OpenCollective!": "如果你喜歡這款軟體並且看好它的潛力, 請在OpenCollective上支持我們!",
|
||||||
"Thanks,": "Thanks,",
|
"Thanks,": "十分感謝!",
|
||||||
"Boostnote maintainers": "Boostnote maintainers",
|
"Boostnote maintainers": "Boostnote的維護人員",
|
||||||
"Support via OpenCollective": "Support via OpenCollective",
|
"Support via OpenCollective": "在OpenCollective上支持我們",
|
||||||
"Language": "Language",
|
"Language": "語言",
|
||||||
"English": "English",
|
"English": "English",
|
||||||
"German": "German",
|
"German": "German",
|
||||||
"French": "French",
|
"French": "French",
|
||||||
"Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying",
|
"Show \"Saved to Clipboard\" notification when copying": "複製的時候,顯示 \"已複製\" 提示",
|
||||||
"All Notes": "All Notes",
|
"All Notes": "所有筆記",
|
||||||
"Starred": "Starred",
|
"Starred": "星標收藏",
|
||||||
"Are you sure to ": "Are you sure to ",
|
"Are you sure to ": "你確定要 ",
|
||||||
" delete": " delete",
|
" delete": " 刪除",
|
||||||
"this folder?": "this folder?",
|
"this folder?": "這個資料夾嗎?",
|
||||||
"Confirm": "Confirm",
|
"Confirm": "確認",
|
||||||
"Cancel": "Cancel",
|
"Cancel": "取消",
|
||||||
"Markdown Note": "Markdown Note",
|
"Markdown Note": "Markdown筆記",
|
||||||
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.",
|
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "創建文檔,清單,代碼塊甚至是Latex格式文檔",
|
||||||
"Snippet Note": "Snippet Note",
|
"Snippet 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.",
|
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "創建代碼片段,支持多種語法代碼片段",
|
||||||
"Tab to switch format": "Tab to switch format",
|
"Tab to switch format": "使用Tab鍵切換格式",
|
||||||
"Updated": "Updated",
|
"Updated": "更新時間",
|
||||||
"Created": "Created",
|
"Created": "創建時間",
|
||||||
"Alphabetically": "Alphabetically",
|
"Alphabetically": "A~Z排序",
|
||||||
"Default View": "Default View",
|
"Default View": "默認視圖",
|
||||||
"Compressed View": "Compressed View",
|
"Compressed View": "列表視圖",
|
||||||
"Search": "Search",
|
"Search": "搜索",
|
||||||
"Blog Type": "Blog Type",
|
"Blog Type": "部落格類型",
|
||||||
"Blog Address": "Blog Address",
|
"Blog Address": "部落格地址",
|
||||||
"Save": "Save",
|
"Save": "保存",
|
||||||
"Auth": "Auth",
|
"Auth": "Auth",
|
||||||
"Authentication Method": "Authentication Method",
|
"Authentication Method": "認證方法",
|
||||||
"JWT": "JWT",
|
"JWT": "JWT",
|
||||||
"USER": "USER",
|
"USER": "USER",
|
||||||
"Token": "Token",
|
"Token": "Token",
|
||||||
"Storage": "Storage",
|
"Storage": "本地儲存",
|
||||||
"Hotkeys": "Hotkeys",
|
"Hotkeys": "快捷鍵",
|
||||||
"Show/Hide Boostnote": "Show/Hide Boostnote",
|
"Show/Hide Boostnote": "顯示/隱藏 Boostnote",
|
||||||
"Restore": "Restore",
|
"Restore": "恢復",
|
||||||
"Permanent Delete": "Permanent Delete",
|
"Permanent Delete": "永久刪除",
|
||||||
"Confirm note deletion": "Confirm note deletion",
|
"Confirm note deletion": "確認刪除筆記",
|
||||||
"This will permanently remove this note.": "This will permanently remove this note.",
|
"This will permanently remove this note.": "永久地刪除這條筆記",
|
||||||
"Successfully applied!": "Successfully applied!",
|
"Successfully applied!": "設置成功",
|
||||||
"Albanian": "Albanian",
|
"Albanian": "Albanian",
|
||||||
"Chinese (zh-CN)": "Chinese (zh-CN)",
|
"Chinese (zh-CN)": "简体中文",
|
||||||
"Chinese (zh-TW)": "Chinese (zh-TW)",
|
"Chinese (zh-TW)": "繁體中文",
|
||||||
"Danish": "Danish",
|
"Danish": "Danish",
|
||||||
"Japanese": "Japanese",
|
"Japanese": "Japanese",
|
||||||
"Korean": "Korean",
|
"Korean": "Korean",
|
||||||
@@ -140,13 +140,13 @@
|
|||||||
"Polish": "Polish",
|
"Polish": "Polish",
|
||||||
"Portuguese": "Portuguese",
|
"Portuguese": "Portuguese",
|
||||||
"Spanish": "Spanish",
|
"Spanish": "Spanish",
|
||||||
"You have to save!": "You have to save!",
|
"You have to save!": "你必須儲存一下!",
|
||||||
"Russian": "Russian",
|
"Russian": "Russian",
|
||||||
"Editor Rulers": "Editor Rulers",
|
"Editor Rulers": "Editor Rulers",
|
||||||
"Enable": "Enable",
|
"Enable": "開啟",
|
||||||
"Disable": "Disable",
|
"Disable": "關閉",
|
||||||
"Sanitization": "Sanitization",
|
"Sanitization": "代碼處理",
|
||||||
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
|
"Only allow secure html tags (recommended)": "只允許安全的html標籤(推薦)",
|
||||||
"Allow styles": "Allow styles",
|
"Allow styles": "允許樣式",
|
||||||
"Allow dangerous html tags": "Allow dangerous html tags"
|
"Allow dangerous html tags": "允許危險的html標籤"
|
||||||
}
|
}
|
||||||
|
|||||||
21
package.json
21
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "boost",
|
"name": "boost",
|
||||||
"productName": "Boostnote",
|
"productName": "Boostnote",
|
||||||
"version": "0.11.3",
|
"version": "0.11.4",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"description": "Boostnote",
|
"description": "Boostnote",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
"webpack": "webpack-dev-server --hot --inline --config webpack.config.js",
|
"webpack": "webpack-dev-server --hot --inline --config webpack.config.js",
|
||||||
"compile": "grunt compile",
|
"compile": "grunt compile",
|
||||||
"test": "PWD=$(pwd) NODE_ENV=test ava --serial",
|
"test": "PWD=$(pwd) NODE_ENV=test ava --serial",
|
||||||
|
"jest": "jest",
|
||||||
"fix": "npm run lint --fix",
|
"fix": "npm run lint --fix",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"dev-start": "concurrently --kill-others \"npm run webpack\" \"npm run hot\""
|
"dev-start": "concurrently --kill-others \"npm run webpack\" \"npm run hot\""
|
||||||
@@ -96,11 +97,13 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"ava": "^0.25.0",
|
"ava": "^0.25.0",
|
||||||
"babel-core": "^6.14.0",
|
"babel-core": "^6.14.0",
|
||||||
|
"babel-jest": "^22.4.3",
|
||||||
"babel-loader": "^6.2.0",
|
"babel-loader": "^6.2.0",
|
||||||
"babel-plugin-react-transform": "^2.0.0",
|
"babel-plugin-react-transform": "^2.0.0",
|
||||||
"babel-plugin-webpack-alias": "^2.1.1",
|
"babel-plugin-webpack-alias": "^2.1.1",
|
||||||
|
"babel-preset-env": "^1.6.1",
|
||||||
"babel-preset-es2015": "^6.3.13",
|
"babel-preset-es2015": "^6.3.13",
|
||||||
"babel-preset-react": "^6.3.13",
|
"babel-preset-react": "^6.24.1",
|
||||||
"babel-preset-react-hmre": "^1.0.1",
|
"babel-preset-react-hmre": "^1.0.1",
|
||||||
"babel-register": "^6.11.6",
|
"babel-register": "^6.11.6",
|
||||||
"browser-env": "^3.2.5",
|
"browser-env": "^3.2.5",
|
||||||
@@ -120,6 +123,9 @@
|
|||||||
"grunt": "^0.4.5",
|
"grunt": "^0.4.5",
|
||||||
"grunt-electron-installer": "2.1.0",
|
"grunt-electron-installer": "2.1.0",
|
||||||
"history": "^1.17.0",
|
"history": "^1.17.0",
|
||||||
|
"identity-obj-proxy": "^3.0.0",
|
||||||
|
"jest": "^22.4.3",
|
||||||
|
"jest-localstorage-mock": "^2.2.0",
|
||||||
"jsdom": "^9.4.2",
|
"jsdom": "^9.4.2",
|
||||||
"json-loader": "^0.5.4",
|
"json-loader": "^0.5.4",
|
||||||
"merge-stream": "^1.0.0",
|
"merge-stream": "^1.0.0",
|
||||||
@@ -130,6 +136,7 @@
|
|||||||
"react-input-autosize": "^1.1.0",
|
"react-input-autosize": "^1.1.0",
|
||||||
"react-router": "^2.4.0",
|
"react-router": "^2.4.0",
|
||||||
"react-router-redux": "^4.0.4",
|
"react-router-redux": "^4.0.4",
|
||||||
|
"react-test-renderer": "^15.6.2",
|
||||||
"standard": "^8.4.0",
|
"standard": "^8.4.0",
|
||||||
"style-loader": "^0.12.4",
|
"style-loader": "^0.12.4",
|
||||||
"stylus": "^0.52.4",
|
"stylus": "^0.52.4",
|
||||||
@@ -152,5 +159,15 @@
|
|||||||
"./tests/helpers/setup-electron-mock.js"
|
"./tests/helpers/setup-electron-mock.js"
|
||||||
],
|
],
|
||||||
"babel": "inherit"
|
"babel": "inherit"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"moduleNameMapper": {
|
||||||
|
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
|
||||||
|
"\\.(css|less|styl)$": "identity-obj-proxy"
|
||||||
|
},
|
||||||
|
"setupFiles": [
|
||||||
|
"<rootDir>/tests/jest.js",
|
||||||
|
"jest-localstorage-mock"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
tests/components/TagListItem.snapshot.test.js
Normal file
9
tests/components/TagListItem.snapshot.test.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import renderer from 'react-test-renderer'
|
||||||
|
import TagListItem from 'browser/components/TagListItem'
|
||||||
|
|
||||||
|
it('TagListItem renders correctly', () => {
|
||||||
|
const tagListItem = renderer.create(<TagListItem name='Test' handleClickTagListItem={jest.fn()} />)
|
||||||
|
|
||||||
|
expect(tagListItem.toJSON()).toMatchSnapshot()
|
||||||
|
})
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`TagListItem renders correctly 1`] = `
|
||||||
|
<button
|
||||||
|
className="tagList-item"
|
||||||
|
onClick={[Function]}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="tagList-item-name"
|
||||||
|
>
|
||||||
|
# Test
|
||||||
|
<span
|
||||||
|
className="tagList-item-count"
|
||||||
|
>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
`;
|
||||||
12
tests/jest.js
Normal file
12
tests/jest.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// Here you can mock the libraries connected through direct insertion <script src="" >
|
||||||
|
global.Raphael = {
|
||||||
|
setWindow: jest.fn(),
|
||||||
|
registerFont: jest.fn(),
|
||||||
|
fn: function () {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
global._ = {
|
||||||
|
extend: jest.genMockFunction()
|
||||||
|
}
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
"lineNumber": true
|
"lineNumber": true
|
||||||
},
|
},
|
||||||
"sortBy": "UPDATED_AT",
|
"sortBy": "UPDATED_AT",
|
||||||
|
"sortTagsBy": "ALPHABETICAL",
|
||||||
"ui": {
|
"ui": {
|
||||||
"defaultNote": "ALWAYS_ASK",
|
"defaultNote": "ALWAYS_ASK",
|
||||||
"disableDirectWrite": false,
|
"disableDirectWrite": false,
|
||||||
|
|||||||
@@ -20,18 +20,25 @@ test.before(t => {
|
|||||||
notes = [note1, note2, note3]
|
notes = [note1, note2, note3]
|
||||||
})
|
})
|
||||||
|
|
||||||
test('it can find notes by tags or words', t => {
|
test('it can find notes by tags and words', t => {
|
||||||
// [input, expected content (Array)]
|
// [input, expected content (Array)]
|
||||||
const testCases = [
|
const testWithTags = [
|
||||||
['#tag1', [note1.content, note2.content, note3.content]],
|
['#tag1', [note1.content, note2.content, note3.content]],
|
||||||
['#tag1 #tag2', [note2.content]],
|
['#tag1 #tag2', [note2.content]],
|
||||||
|
['#tag2 #tag1', [note2.content]],
|
||||||
['#tag1 #tag2 #tag3', []],
|
['#tag1 #tag2 #tag3', []],
|
||||||
['content1', [note1.content, note2.content]],
|
['content1', [note1.content, note2.content]],
|
||||||
['content1 content2', [note2.content]],
|
['content1 content2', [note2.content]],
|
||||||
['content1 content2 content3', []],
|
['content1 content2 content3', []],
|
||||||
['#content4', [note3.content]]
|
['#content4', [note3.content]],
|
||||||
|
['#tag2 content1', [note2.content]],
|
||||||
|
['content1 #tag2', [note2.content]]
|
||||||
]
|
]
|
||||||
|
const testWithTagsWithoutHash = testWithTags.map(function (testCase) {
|
||||||
|
return [testCase[0].replace(/#/g, ''), testCase[1]]
|
||||||
|
})
|
||||||
|
|
||||||
|
const testCases = testWithTags.concat(testWithTagsWithoutHash)
|
||||||
testCases.forEach((testCase) => {
|
testCases.forEach((testCase) => {
|
||||||
const [input, expectedContents] = testCase
|
const [input, expectedContents] = testCase
|
||||||
const results = searchFromNotes(notes, input)
|
const results = searchFromNotes(notes, input)
|
||||||
|
|||||||
Reference in New Issue
Block a user