{this.SideNavComponent(isFolded, storageList)}
+ {colorPicker}
)
}
diff --git a/browser/main/TopBar/index.js b/browser/main/TopBar/index.js
index a5687ecb..91256daf 100644
--- a/browser/main/TopBar/index.js
+++ b/browser/main/TopBar/index.js
@@ -6,6 +6,7 @@ import _ from 'lodash'
import ee from 'browser/main/lib/eventEmitter'
import NewNoteButton from 'browser/main/NewNoteButton'
import i18n from 'browser/lib/i18n'
+import debounce from 'lodash/debounce'
class TopBar extends React.Component {
constructor (props) {
@@ -25,6 +26,10 @@ class TopBar extends React.Component {
}
this.codeInitHandler = this.handleCodeInit.bind(this)
+
+ this.updateKeyword = debounce(this.updateKeyword, 1000 / 60, {
+ maxWait: 1000 / 8
+ })
}
componentDidMount () {
@@ -94,7 +99,6 @@ class TopBar extends React.Component {
}
handleKeyUp (e) {
- const { router } = this.context
// reset states
this.setState({
isConfirmTranslation: false
@@ -106,21 +110,21 @@ class TopBar extends React.Component {
isConfirmTranslation: true
})
const keyword = this.refs.searchInput.value
- router.push(`/searched/${encodeURIComponent(keyword)}`)
- this.setState({
- search: keyword
- })
+ this.updateKeyword(keyword)
}
}
handleSearchChange (e) {
- const { router } = this.context
- const keyword = this.refs.searchInput.value
if (this.state.isAlphabet || this.state.isConfirmTranslation) {
- router.push(`/searched/${encodeURIComponent(keyword)}`)
+ const keyword = this.refs.searchInput.value
+ this.updateKeyword(keyword)
} else {
e.preventDefault()
}
+ }
+
+ updateKeyword (keyword) {
+ this.context.router.push(`/searched/${encodeURIComponent(keyword)}`)
this.setState({
search: keyword
})
diff --git a/browser/main/global.styl b/browser/main/global.styl
index e04060c2..d864993d 100644
--- a/browser/main/global.styl
+++ b/browser/main/global.styl
@@ -97,6 +97,7 @@ modalBackColor = white
body[data-theme="dark"]
+ background-color $ui-dark-backgroundColor
::-webkit-scrollbar-thumb
background-color rgba(0, 0, 0, 0.3)
.ModalBase
@@ -148,6 +149,7 @@ body[data-theme="dark"]
z-index modalZIndex + 5
body[data-theme="solarized-dark"]
+ background-color $ui-solarized-dark-backgroundColor
::-webkit-scrollbar-thumb
background-color rgba(0, 0, 0, 0.3)
.ModalBase
@@ -157,6 +159,7 @@ body[data-theme="solarized-dark"]
color: $ui-solarized-dark-text-color
body[data-theme="monokai"]
+ background-color $ui-monokai-backgroundColor
::-webkit-scrollbar-thumb
background-color rgba(0, 0, 0, 0.3)
.ModalBase
@@ -166,6 +169,7 @@ body[data-theme="monokai"]
color: $ui-monokai-text-color
body[data-theme="dracula"]
+ background-color $ui-dracula-backgroundColor
::-webkit-scrollbar-thumb
background-color rgba(0, 0, 0, 0.3)
.ModalBase
diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js
index d6b04d9b..5558b3bd 100644
--- a/browser/main/lib/ConfigManager.js
+++ b/browser/main/lib/ConfigManager.js
@@ -25,25 +25,31 @@ export const DEFAULT_CONFIG = {
hotkey: {
toggleMain: OSX ? 'Command + Alt + L' : 'Super + Alt + E',
toggleMode: OSX ? 'Command + Alt + M' : 'Ctrl + M',
- deleteNote: OSX ? 'Command + Shift + Backspace' : 'Ctrl + Shift + Backspace'
+ deleteNote: OSX ? 'Command + Shift + Backspace' : 'Ctrl + Shift + Backspace',
+ pasteSmartly: OSX ? 'Command + Shift + V' : 'Ctrl + Shift + V',
+ toggleMenuBar: 'Alt'
},
ui: {
language: 'en',
theme: 'default',
showCopyNotification: true,
disableDirectWrite: false,
- defaultNote: 'ALWAYS_ASK' // 'ALWAYS_ASK', 'SNIPPET_NOTE', 'MARKDOWN_NOTE'
+ defaultNote: 'ALWAYS_ASK', // 'ALWAYS_ASK', 'SNIPPET_NOTE', 'MARKDOWN_NOTE'
+ showMenuBar: false
},
editor: {
theme: 'base16-light',
keyMap: 'sublime',
fontSize: '14',
- fontFamily: win ? 'Segoe UI' : 'Monaco, Consolas',
+ fontFamily: win ? 'Consolas' : 'Monaco',
indentType: 'space',
indentSize: '2',
enableRulers: false,
rulers: [80, 120],
displayLineNumbers: true,
+ matchingPairs: '()[]{}\'\'""$$**``',
+ matchingTriples: '```"""\'\'\'',
+ explodingPairs: '[]{}``$$',
switchPreview: 'BLUR', // 'BLUR', 'DBL_CLICK', 'RIGHTCLICK'
delfaultStatus: 'PREVIEW', // 'PREVIEW', 'CODE'
scrollPastEnd: false,
@@ -52,7 +58,8 @@ export const DEFAULT_CONFIG = {
enableTableEditor: false,
enableFrontMatterTitle: true,
frontMatterTitleField: 'title',
- spellcheck: false
+ spellcheck: false,
+ enableSmartPaste: false
},
preview: {
fontSize: '14',
@@ -81,7 +88,8 @@ export const DEFAULT_CONFIG = {
token: '',
username: '',
password: ''
- }
+ },
+ coloredTags: {}
}
function validate (config) {
@@ -203,7 +211,7 @@ function assignConfigValues (originalConfig, rcConfig) {
function rewriteHotkey (config) {
const keys = [...Object.keys(config.hotkey)]
keys.forEach(key => {
- config.hotkey[key] = config.hotkey[key].replace(/Cmd/g, 'Command')
+ config.hotkey[key] = config.hotkey[key].replace(/Cmd\s/g, 'Command ')
config.hotkey[key] = config.hotkey[key].replace(/Opt\s/g, 'Option ')
})
return config
diff --git a/browser/main/lib/dataApi/attachmentManagement.js b/browser/main/lib/dataApi/attachmentManagement.js
index 56af58ed..5206e9ea 100644
--- a/browser/main/lib/dataApi/attachmentManagement.js
+++ b/browser/main/lib/dataApi/attachmentManagement.js
@@ -241,7 +241,15 @@ function migrateAttachments (markdownContent, storagePath, noteKey) {
* @returns {String} postprocessed HTML in which all :storage references are mapped to the actual paths.
*/
function fixLocalURLS (renderedHTML, storagePath) {
- return renderedHTML.replace(new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER + '.*?"', 'g'), function (match) {
+ /*
+ A :storage reference is like `:storage/3b6f8bd6-4edd-4b15-96e0-eadc4475b564/f939b2c3.jpg`.
+
+ - `STORAGE_FOLDER_PLACEHOLDER` will match `:storage`
+ - `(?:(?:\\\/|%5C)[-.\\w]+)+` will match `/3b6f8bd6-4edd-4b15-96e0-eadc4475b564/f939b2c3.jpg`
+ - `(?:\\\/|%5C)[-.\\w]+` will either match `/3b6f8bd6-4edd-4b15-96e0-eadc4475b564` or `/f939b2c3.jpg`
+ - `(?:\\\/|%5C)` match the path seperator. `\\\/` for posix systems and `%5C` for windows.
+ */
+ return renderedHTML.replace(new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER + '(?:(?:\\\/|%5C)[-.\\w]+)+', 'g'), function (match) {
var encodedPathSeparators = new RegExp(mdurl.encode(path.win32.sep) + '|' + mdurl.encode(path.posix.sep), 'g')
return match.replace(encodedPathSeparators, path.sep).replace(new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER, 'g'), 'file:///' + path.join(storagePath, DESTINATION_FOLDER))
})
@@ -270,7 +278,7 @@ function handleAttachmentDrop (codeEditor, storageKey, noteKey, dropEvent) {
let promise
if (dropEvent.dataTransfer.files.length > 0) {
promise = Promise.all(Array.from(dropEvent.dataTransfer.files).map(file => {
- if (file['type'].startsWith('image')) {
+ if (file['type'].startsWith('image') && !file['type'].endsWith('gif')) {
return fixRotate(file)
.then(data => copyAttachment({type: 'base64', data: data, sourceFilePath: file.path}, storageKey, noteKey)
.then(fileName => ({
@@ -330,7 +338,7 @@ function handleAttachmentDrop (codeEditor, storageKey, noteKey, dropEvent) {
* @param {String} noteKey Key of the current note
* @param {DataTransferItem} dataTransferItem Part of the past-event
*/
-function handlePastImageEvent (codeEditor, storageKey, noteKey, dataTransferItem) {
+function handlePasteImageEvent (codeEditor, storageKey, noteKey, dataTransferItem) {
if (!codeEditor) {
throw new Error('codeEditor has to be given')
}
@@ -367,6 +375,44 @@ function handlePastImageEvent (codeEditor, storageKey, noteKey, dataTransferItem
reader.readAsDataURL(blob)
}
+/**
+ * @description Creates a new file in the storage folder belonging to the current note and inserts the correct markdown code
+ * @param {CodeEditor} codeEditor Markdown editor. Its insertAttachmentMd() method will be called to include the markdown code
+ * @param {String} storageKey Key of the current storage
+ * @param {String} noteKey Key of the current note
+ * @param {NativeImage} image The native image
+ */
+function handlePasteNativeImage (codeEditor, storageKey, noteKey, image) {
+ if (!codeEditor) {
+ throw new Error('codeEditor has to be given')
+ }
+ if (!storageKey) {
+ throw new Error('storageKey has to be given')
+ }
+
+ if (!noteKey) {
+ throw new Error('noteKey has to be given')
+ }
+ if (!image) {
+ throw new Error('image has to be given')
+ }
+
+ const targetStorage = findStorage.findStorage(storageKey)
+ const destinationDir = path.join(targetStorage.path, DESTINATION_FOLDER, noteKey)
+
+ createAttachmentDestinationFolder(targetStorage.path, noteKey)
+
+ const imageName = `${uniqueSlug()}.png`
+ const imagePath = path.join(destinationDir, imageName)
+
+ const binaryData = image.toPNG()
+ fs.writeFileSync(imagePath, binaryData, 'binary')
+
+ const imageReferencePath = path.join(STORAGE_FOLDER_PLACEHOLDER, noteKey, imageName)
+ const imageMd = generateAttachmentMarkdown(imageName, imageReferencePath, true)
+ codeEditor.insertAttachmentMd(imageMd)
+}
+
/**
* @description Returns all attachment paths of the given markdown
* @param {String} markdownContent content in which the attachment paths should be found
@@ -434,7 +480,14 @@ function replaceNoteKeyWithNewNoteKey (noteContent, oldNoteKey, newNoteKey) {
* @returns {String} Input without the references
*/
function removeStorageAndNoteReferences (input, noteKey) {
- return input.replace(new RegExp(mdurl.encode(path.sep), 'g'), path.sep).replace(new RegExp(STORAGE_FOLDER_PLACEHOLDER + '(' + escapeStringRegexp(path.sep) + noteKey + ')?', 'g'), DESTINATION_FOLDER)
+ return input.replace(new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER + '.*?("|])', 'g'), function (match) {
+ const temp = match
+ .replace(new RegExp(mdurl.encode(path.win32.sep), 'g'), path.sep)
+ .replace(new RegExp(mdurl.encode(path.posix.sep), 'g'), path.sep)
+ .replace(new RegExp(escapeStringRegexp(path.win32.sep), 'g'), path.sep)
+ .replace(new RegExp(escapeStringRegexp(path.posix.sep), 'g'), path.sep)
+ return temp.replace(new RegExp(STORAGE_FOLDER_PLACEHOLDER + '(' + escapeStringRegexp(path.sep) + noteKey + ')?', 'g'), DESTINATION_FOLDER)
+ })
}
/**
@@ -589,7 +642,8 @@ module.exports = {
fixLocalURLS,
generateAttachmentMarkdown,
handleAttachmentDrop,
- handlePastImageEvent,
+ handlePasteImageEvent,
+ handlePasteNativeImage,
getAttachmentsInMarkdownContent,
getAbsolutePathsOfAttachmentsInContent,
removeStorageAndNoteReferences,
diff --git a/browser/main/lib/dataApi/copyFile.js b/browser/main/lib/dataApi/copyFile.js
index 2dc66309..6f23aae2 100755
--- a/browser/main/lib/dataApi/copyFile.js
+++ b/browser/main/lib/dataApi/copyFile.js
@@ -16,7 +16,7 @@ function copyFile (srcPath, dstPath) {
const dstFolder = path.dirname(dstPath)
if (!fs.existsSync(dstFolder)) fs.mkdirSync(dstFolder)
- const input = fs.createReadStream(srcPath)
+ const input = fs.createReadStream(decodeURI(srcPath))
const output = fs.createWriteStream(dstPath)
output.on('error', reject)
diff --git a/browser/main/lib/dataApi/createNote.js b/browser/main/lib/dataApi/createNote.js
index e5d44489..5bfa2457 100644
--- a/browser/main/lib/dataApi/createNote.js
+++ b/browser/main/lib/dataApi/createNote.js
@@ -16,6 +16,7 @@ function validateInput (input) {
switch (input.type) {
case 'MARKDOWN_NOTE':
if (!_.isString(input.content)) input.content = ''
+ if (!_.isArray(input.linesHighlighted)) input.linesHighlighted = []
break
case 'SNIPPET_NOTE':
if (!_.isString(input.description)) input.description = ''
@@ -23,7 +24,8 @@ function validateInput (input) {
input.snippets = [{
name: '',
mode: 'text',
- content: ''
+ content: '',
+ linesHighlighted: []
}]
}
break
diff --git a/browser/main/lib/dataApi/createSnippet.js b/browser/main/lib/dataApi/createSnippet.js
index 5d189217..2e585c9f 100644
--- a/browser/main/lib/dataApi/createSnippet.js
+++ b/browser/main/lib/dataApi/createSnippet.js
@@ -9,7 +9,8 @@ function createSnippet (snippetFile) {
id: crypto.randomBytes(16).toString('hex'),
name: 'Unnamed snippet',
prefix: [],
- content: ''
+ content: '',
+ linesHighlighted: []
}
fetchSnippet(null, snippetFile).then((snippets) => {
snippets.push(newSnippet)
diff --git a/browser/main/lib/dataApi/exportFolder.js b/browser/main/lib/dataApi/exportFolder.js
index 3e998f15..771f77dc 100644
--- a/browser/main/lib/dataApi/exportFolder.js
+++ b/browser/main/lib/dataApi/exportFolder.js
@@ -1,9 +1,9 @@
import { findStorage } from 'browser/lib/findStorage'
import resolveStorageData from './resolveStorageData'
import resolveStorageNotes from './resolveStorageNotes'
+import exportNote from './exportNote'
import filenamify from 'filenamify'
import * as path from 'path'
-import * as fs from 'fs'
/**
* @param {String} storageKey
@@ -45,9 +45,9 @@ function exportFolder (storageKey, folderKey, fileType, exportDir) {
notes
.filter(note => note.folder === folderKey && note.isTrashed === false && note.type === 'MARKDOWN_NOTE')
- .forEach(snippet => {
- const notePath = path.join(exportDir, `${filenamify(snippet.title, {replacement: '_'})}.${fileType}`)
- fs.writeFileSync(notePath, snippet.content)
+ .forEach(note => {
+ const notePath = path.join(exportDir, `${filenamify(note.title, {replacement: '_'})}.${fileType}`)
+ exportNote(note.key, storage.path, note.content, notePath, null)
})
return {
diff --git a/browser/main/lib/dataApi/exportNote.js b/browser/main/lib/dataApi/exportNote.js
index e4fec5f4..b358e548 100755
--- a/browser/main/lib/dataApi/exportNote.js
+++ b/browser/main/lib/dataApi/exportNote.js
@@ -4,27 +4,43 @@ import { findStorage } from 'browser/lib/findStorage'
const fs = require('fs')
const path = require('path')
+const attachmentManagement = require('./attachmentManagement')
+
/**
- * Export note together with images
+ * Export note together with attachments
*
- * If images is stored in the storage, creates 'images' subfolder in target directory
- * and copies images to it. Changes links to images in the content of the note
+ * If attachments are stored in the storage, creates 'attachments' subfolder in target directory
+ * and copies attachments to it. Changes links to images in the content of the note
*
+ * @param {String} nodeKey key of the node that should be exported
* @param {String} storageKey or storage path
* @param {String} noteContent Content to export
* @param {String} targetPath Path to exported file
* @param {function} outputFormatter
* @return {Promise.<*[]>}
*/
-function exportNote (storageKey, noteContent, targetPath, outputFormatter) {
+function exportNote (nodeKey, storageKey, noteContent, targetPath, outputFormatter) {
const storagePath = path.isAbsolute(storageKey) ? storageKey : findStorage(storageKey).path
const exportTasks = []
if (!storagePath) {
throw new Error('Storage path is not found')
}
+ const attachmentsAbsolutePaths = attachmentManagement.getAbsolutePathsOfAttachmentsInContent(
+ noteContent,
+ storagePath
+ )
+ attachmentsAbsolutePaths.forEach(attachment => {
+ exportTasks.push({
+ src: attachment,
+ dst: attachmentManagement.DESTINATION_FOLDER
+ })
+ })
- let exportedData = noteContent
+ let exportedData = attachmentManagement.removeStorageAndNoteReferences(
+ noteContent,
+ nodeKey
+ )
if (outputFormatter) {
exportedData = outputFormatter(exportedData, exportTasks)
diff --git a/browser/main/lib/dataApi/init.js b/browser/main/lib/dataApi/init.js
index 7f81e90b..0dbcc182 100644
--- a/browser/main/lib/dataApi/init.js
+++ b/browser/main/lib/dataApi/init.js
@@ -4,6 +4,7 @@ const resolveStorageData = require('./resolveStorageData')
const resolveStorageNotes = require('./resolveStorageNotes')
const consts = require('browser/lib/consts')
const path = require('path')
+const fs = require('fs')
const CSON = require('@rokt33r/season')
/**
* @return {Object} all storages and notes
@@ -19,11 +20,14 @@ const CSON = require('@rokt33r/season')
* 2. legacy
* 3. empty directory
*/
+
function init () {
const fetchStorages = function () {
let rawStorages
try {
rawStorages = JSON.parse(window.localStorage.getItem('storages'))
+ // Remove storages who's location is inaccesible.
+ rawStorages = rawStorages.filter(storage => fs.existsSync(storage.path))
if (!_.isArray(rawStorages)) throw new Error('Cached data is not valid.')
} catch (e) {
console.warn('Failed to parse cached data from localStorage', e)
@@ -36,6 +40,7 @@ function init () {
const fetchNotes = function (storages) {
const findNotesFromEachStorage = storages
+ .filter(storage => fs.existsSync(storage.path))
.map((storage) => {
return resolveStorageNotes(storage)
.then((notes) => {
@@ -51,7 +56,11 @@ function init () {
}
})
if (unknownCount > 0) {
- CSON.writeFileSync(path.join(storage.path, 'boostnote.json'), _.pick(storage, ['folders', 'version']))
+ try {
+ CSON.writeFileSync(path.join(storage.path, 'boostnote.json'), _.pick(storage, ['folders', 'version']))
+ } catch (e) {
+ console.log('Error writting boostnote.json: ' + e + ' from init.js')
+ }
}
return notes
})
diff --git a/browser/main/lib/dataApi/migrateFromV5Storage.js b/browser/main/lib/dataApi/migrateFromV5Storage.js
index b11e66e9..78d78746 100644
--- a/browser/main/lib/dataApi/migrateFromV5Storage.js
+++ b/browser/main/lib/dataApi/migrateFromV5Storage.js
@@ -69,7 +69,8 @@ function importAll (storage, data) {
isStarred: false,
title: article.title,
content: '# ' + article.title + '\n\n' + article.content,
- key: noteKey
+ key: noteKey,
+ linesHighlighted: article.linesHighlighted
}
notes.push(newNote)
} else {
@@ -87,7 +88,8 @@ function importAll (storage, data) {
snippets: [{
name: article.mode,
mode: article.mode,
- content: article.content
+ content: article.content,
+ linesHighlighted: article.linesHighlighted
}]
}
notes.push(newNote)
diff --git a/browser/main/lib/dataApi/updateNote.js b/browser/main/lib/dataApi/updateNote.js
index 147fbc06..ce9fabcf 100644
--- a/browser/main/lib/dataApi/updateNote.js
+++ b/browser/main/lib/dataApi/updateNote.js
@@ -39,6 +39,9 @@ function validateInput (input) {
if (input.content != null) {
if (!_.isString(input.content)) validatedInput.content = ''
else validatedInput.content = input.content
+
+ if (!_.isArray(input.linesHighlighted)) validatedInput.linesHighlighted = []
+ else validatedInput.linesHighlighted = input.linesHighlighted
}
return validatedInput
case 'SNIPPET_NOTE':
@@ -51,7 +54,8 @@ function validateInput (input) {
validatedInput.snippets = [{
name: '',
mode: 'text',
- content: ''
+ content: '',
+ linesHighlighted: []
}]
} else {
validatedInput.snippets = input.snippets
@@ -96,12 +100,14 @@ function updateNote (storageKey, noteKey, input) {
snippets: [{
name: '',
mode: 'text',
- content: ''
+ content: '',
+ linesHighlighted: []
}]
}
: {
type: 'MARKDOWN_NOTE',
- content: ''
+ content: '',
+ linesHighlighted: []
}
noteData.title = ''
if (storage.folders.length === 0) throw new Error('Failed to restore note: No folder exists.')
diff --git a/browser/main/lib/dataApi/updateSnippet.js b/browser/main/lib/dataApi/updateSnippet.js
index f2310b8e..f132d83f 100644
--- a/browser/main/lib/dataApi/updateSnippet.js
+++ b/browser/main/lib/dataApi/updateSnippet.js
@@ -12,7 +12,8 @@ function updateSnippet (snippet, snippetFile) {
if (
currentSnippet.name === snippet.name &&
currentSnippet.prefix === snippet.prefix &&
- currentSnippet.content === snippet.content
+ currentSnippet.content === snippet.content &&
+ currentSnippet.linesHighlighted === snippet.linesHighlighted
) {
// if everything is the same then don't write to disk
resolve(snippets)
@@ -20,6 +21,7 @@ function updateSnippet (snippet, snippetFile) {
currentSnippet.name = snippet.name
currentSnippet.prefix = snippet.prefix
currentSnippet.content = snippet.content
+ currentSnippet.linesHighlighted = (snippet.linesHighlighted)
fs.writeFile(snippetFile || consts.SNIPPET_FILE, JSON.stringify(snippets, null, 4), (err) => {
if (err) reject(err)
resolve(snippets)
diff --git a/browser/main/lib/shortcut.js b/browser/main/lib/shortcut.js
index 93e33c9b..3165606a 100644
--- a/browser/main/lib/shortcut.js
+++ b/browser/main/lib/shortcut.js
@@ -6,5 +6,8 @@ module.exports = {
},
'deleteNote': () => {
ee.emit('hotkey:deletenote')
+ },
+ 'toggleMenuBar': () => {
+ ee.emit('menubar:togglemenubar')
}
}
diff --git a/browser/main/modals/PreferencesModal/Crowdfunding.js b/browser/main/modals/PreferencesModal/Crowdfunding.js
index f6389cd8..f94ee5ca 100644
--- a/browser/main/modals/PreferencesModal/Crowdfunding.js
+++ b/browser/main/modals/PreferencesModal/Crowdfunding.js
@@ -34,7 +34,7 @@ class Crowdfunding extends React.Component {
{i18n.__('We thought that it will be nice if we can pay reward for our contributors.')}
{i18n.__('### We believe Meritocracy')}
-
{i18n.__('We think developers who has skill and did great things must be rewarded properly.')}
+
{i18n.__('We think developers who have skills and do great things must be rewarded properly.')}
{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.')}
{i18n.__('It sometimes looks like exploitation.')}
{i18n.__('We’ve realized IssueHunt could enhance sustainability of open-source ecosystem.')}
@@ -590,6 +660,7 @@ class UiTab extends React.Component {
/>
+
{i18n.__('Code Block Theme')}
diff --git a/browser/styles/Detail/TagSelect.styl b/browser/styles/Detail/TagSelect.styl
index 17e9f993..8900422c 100644
--- a/browser/styles/Detail/TagSelect.styl
+++ b/browser/styles/Detail/TagSelect.styl
@@ -4,8 +4,10 @@
border none
background-color transparent
outline none
- padding 0 4px
+ padding 2px 4px
+ margin 0px 2px 2px
font-size 13px
+ height 23px
ul
position fixed
diff --git a/browser/styles/index.styl b/browser/styles/index.styl
index 56cb0eab..b9f9c41e 100644
--- a/browser/styles/index.styl
+++ b/browser/styles/index.styl
@@ -240,10 +240,8 @@ navWhiteButtonColor()
&:hover
background-color alpha($ui-button--active-backgroundColor, 20%)
transition 0.15s
- color $ui-text-color
&:active, &:active:hover
background-color $ui-button--active-backgroundColor
- color $ui-text-color
transition 0.15s
// UI Button
diff --git a/docs/build.md b/docs/build.md
index f2b3e5ac..095f8628 100644
--- a/docs/build.md
+++ b/docs/build.md
@@ -1,10 +1,11 @@
# Build
-This page is also available in [Japanese](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/build.md), [Korean](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/build.md), [Russain](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/build.md), [Simplified Chinese](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/build.md), [French](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/build.md) and [German](https://github.com/BoostIO/Boostnote/blob/master/docs/de/build.md).
+
+This page is also available in [Japanese](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/build.md), [Korean](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/build.md), [Russain](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/build.md), [Simplified Chinese](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/build.md), [French](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/build.md), [Portuguese](https://github.com/BoostIO/Boostnote/blob/master/docs/pt_BR/build.md) and [German](https://github.com/BoostIO/Boostnote/blob/master/docs/de/build.md).
## Environments
-* npm: 6.x
-* node: 8.x
+- npm: 6.x
+- node: 8.x
## Development
@@ -24,10 +25,40 @@ $ yarn run dev
```
> ### Notice
+>
> There are some cases where you have to refresh the app manually.
+>
> 1. When editing a constructor method of a component
> 2. When adding a new css class (similar to 1: the CSS class is re-written by each component. This process occurs at the Constructor method.)
+## Accessing code used in Pull Requests
+Visit the page for the pull request and look at the end of the url for the PR number
+
+https://github.com/BoostIO/Boostnote/pull/2794
+
+In the following, replace \ with that number (no brackets).
+For the above url, you would replace \ with 2794
+
+_If you do not have a local copy of the master branch yet_
+```
+git clone https://github.com/BoostIO/Boostnote.git
+cd Boostnote
+git fetch origin pull//head:
+git checkout
+```
+
+_If you already have the master branch_
+```
+git fetch origin pull//head:
+git checkout
+```
+
+_To compile and run the code_
+```
+yarn
+yarn run dev
+```
+
## Deploy
We use Grunt to automate deployment.
@@ -51,7 +82,6 @@ Distribution packages are created by exec `grunt build` on Linux platform (e.g.
After installing the supported version of `node` and `npm`, install build dependency packages.
-
Ubuntu/Debian:
```
diff --git a/docs/de/build.md b/docs/de/build.md
index a3d8e274..65f2b8c3 100644
--- a/docs/de/build.md
+++ b/docs/de/build.md
@@ -1,10 +1,11 @@
# Build
-Diese Seite ist auch verfügbar in [Japanisch](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/build.md), [Koreanisch](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/build.md), [Russisch](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/build.md), [Vereinfachtem Chinesisch](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/build.md), [Französisch](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/build.md) und [Deutsch](https://github.com/BoostIO/Boostnote/blob/master/docs/de/build.md).
+
+Diese Seite ist auch verfügbar in [Japanisch](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/build.md), [Koreanisch](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/build.md), [Russisch](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/build.md), [Vereinfachtem Chinesisch](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/build.md), [Französisch](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/build.md), [Portugiesisch](https://github.com/BoostIO/Boostnote/blob/master/docs/pt_BR/build.md) und [Deutsch](https://github.com/BoostIO/Boostnote/blob/master/docs/de/build.md).
## Umgebungen
-* npm: 6.x
-* node: 8.x
+- npm: 6.x
+- node: 8.x
## Entwicklung
@@ -24,7 +25,9 @@ $ yarn run dev
```
> ### Notiz
+>
> Es gibt einige Fälle bei denen die App manuell zu refreshen ist.
+>
> 1. Wenn eine "constructor method" einer Komponente manuell editiert wird.
> 2. Wenn eine neue CSS Klasse ergänzt wird (ähnlich wie 1: die CSS Klasse wird von jeder Komponenete neu geschrieben. Dieser Prozess passiert in der "Constructor method".)
@@ -51,7 +54,6 @@ Distributions Pakete können mittels `grunt build` auf Linux Plattformen (e.g. U
Nach der Installation der supporteten Version von `node` and `npm`, installiere auch build dependency packages.
-
Ubuntu/Debian:
```
diff --git a/docs/de/debug.md b/docs/de/debug.md
index 6c3de3dc..a22ad98b 100644
--- a/docs/de/debug.md
+++ b/docs/de/debug.md
@@ -1,9 +1,8 @@
# How to debug Boostnote (Electron app)
-Diese Seite ist auch verfügbar in [Japanisch](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/debug.md), [Koreanisch](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/debug.md), [Russisch](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/debug.md), [Vereinfachtem Chinesisch](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/debug.md), [Französisch](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/debug.md) und [Deutsch](https://github.com/BoostIO/Boostnote/blob/master/docs/de/debug.md).
+Diese Seite ist auch verfügbar in [Japanisch](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/debug.md), [Koreanisch](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/debug.md), [Russisch](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/debug.md), [Vereinfachtem Chinesisch](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/debug.md), [Französisch](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/debug.md), [Portugiesisch](https://github.com/BoostIO/Boostnote/blob/master/docs/pt_BR/debug.md) und [Deutsch](https://github.com/BoostIO/Boostnote/blob/master/docs/de/debug.md).
-
-Boostnote ist eine Electron App und basiert auf Chromium.
+Boostnote ist eine Electron App und basiert auf Chromium.
Zum Entwicklen verwendest du am Besten die `Developer Tools` von Google Chrome verwenden. Diese kannst du ganz einfach im unter dem Menüpunkt `View` mit `Toggle Developer Tools` aktivieren:
@@ -13,10 +12,9 @@ Die Anzeige der `Developer Tools` sieht in etwa so aus:

-
## Debugging
-Fehlermeldungen werden in der Regel in der `console` ausgegeben, die du über den gleichnamigen Reiter der `Developer Tools` anzeigen lassen kannst. Zum Debuggen kannst du beispielsweise über den `debugger` Haltepunkte im Code setzen.
+Fehlermeldungen werden in der Regel in der `console` ausgegeben, die du über den gleichnamigen Reiter der `Developer Tools` anzeigen lassen kannst. Zum Debuggen kannst du beispielsweise über den `debugger` Haltepunkte im Code setzen.

@@ -24,8 +22,8 @@ Du kannst aber natürlich auch die Art von Debugging verwenden mit der du am bes
## Referenz
-* [Official document of Google Chrome about debugging](https://developer.chrome.com/devtools)
+- [Official document of Google Chrome about debugging](https://developer.chrome.com/devtools)
---
-Special thanks: Translated by [gino909](https://github.com/gino909), [mdeuerlein](https://github.com/mdeuerlein)
+Special thanks: Translated by [gino909](https://github.com/gino909), [mdeuerlein](https://github.com/mdeuerlein)
diff --git a/docs/debug.md b/docs/debug.md
index a84a6bba..4cd8b361 100644
--- a/docs/debug.md
+++ b/docs/debug.md
@@ -1,8 +1,9 @@
# How to debug Boostnote (Electron app)
-This page is also available in [Japanese](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/debug.md), [Korean](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/debug.md), [Russain](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/debug.md), [Simplified Chinese](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/debug.md), [French](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/debug.md) and [German](https://github.com/BoostIO/Boostnote/blob/master/docs/de/debug.md).
+This page is also available in [Japanese](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/debug.md), [Korean](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/debug.md), [Russain](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/debug.md), [Simplified Chinese](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/debug.md), [French](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/debug.md), [Portuguese](https://github.com/BoostIO/Boostnote/blob/master/docs/pt_BR/debug.md) and [German](https://github.com/BoostIO/Boostnote/blob/master/docs/de/debug.md).
## Debug with Google Chrome developer Tools
+
Boostnote is an Electron app so it's based on Chromium; developers can use `Developer Tools` just like Google Chrome.
You can toggle the `Developer Tools` like this:
@@ -14,6 +15,7 @@ The `Developer Tools` will look like this:
When errors occur, the error messages are displayed at the `console`.
### Debugging
+
For example, you can use the `debugger` to set a breakpoint in the code like this:

@@ -21,16 +23,18 @@ For example, you can use the `debugger` to set a breakpoint in the code like thi
This is just an illustrative example, you should find a way to debug which fits your style.
### References
-* [Official document of Google Chrome about debugging](https://developer.chrome.com/devtools)
+
+- [Official document of Google Chrome about debugging](https://developer.chrome.com/devtools)
## Debug with Visual Studio Code
-1. Install **[Debugger for Chrome](https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome "Install Debugger for Chrome")** plugin for Visual Studio Code. Then restart it.
+1. Install **[Debugger for Chrome](https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome 'Install Debugger for Chrome')** plugin for Visual Studio Code. Then restart it.
2. Pressing **Shift+Command+B** or running **Run Build Task** from the global **Terminal** menu, then pick the task named **Build Boostnote**. Or run `yarn run watch` from the terminal.
3. When above task is running, open **Debug view** in **Activity Bar** on the side of VS Code or use shortcut **Shift+Command+D**.
4. Select the configuration named **Boostnote All** from the **Debug configuration**, then click the green arrow button or press **F5** to start debugging.
5. Now you should find **Boostnote** is running. You will see two processes running, one named **Boostnote Main** and the other named **Boostnote Renderer**. Now you can set **debug breakpoints** in vscode. If you find your **breakpoints** is unverified, you need to switch to the appropriate process between **Boostnote Renderer** and **Boostnote Main**.
- ### References
- * [Electron application debugging](https://electronjs.org/docs/tutorial/application-debugging)
- * [Debugger for Chrome](https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome)
\ No newline at end of file
+ ### References
+
+ - [Electron application debugging](https://electronjs.org/docs/tutorial/application-debugging)
+ - [Debugger for Chrome](https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome)
diff --git a/docs/fr/build.md b/docs/fr/build.md
index e66a11aa..7628a3e1 100644
--- a/docs/fr/build.md
+++ b/docs/fr/build.md
@@ -1,10 +1,11 @@
# Build
-Cette page est également disponible en [Anglais](https://github.com/BoostIO/Boostnote/blob/master/docs/build.md), [Japonais](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/build.md), [Coréen](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/build.md), [Russe](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/build.md), [Chinois Simplifié](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/build.md) et en [Allemand](https://github.com/BoostIO/Boostnote/blob/master/docs/de/build.md)
+
+Cette page est également disponible en [Anglais](https://github.com/BoostIO/Boostnote/blob/master/docs/build.md), [Japonais](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/build.md), [Coréen](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/build.md), [Russe](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/build.md), [Chinois Simplifié](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/build.md), [Portugais](https://github.com/BoostIO/Boostnote/blob/master/docs/pt_BR/build.md) et en [Allemand](https://github.com/BoostIO/Boostnote/blob/master/docs/de/build.md)
## Environnements
-* npm: 6.x
-* node: 8.x
+- npm: 6.x
+- node: 8.x
## Développement
@@ -16,6 +17,7 @@ Installez les paquets requis à l'aide de `yarn`.
```
$ yarn
```
+
Build et start
```
@@ -23,7 +25,9 @@ $ yarn run dev
```
> ### Notice
+>
> Il y a certains cas où vous voudrez relancer l'application manuellement.
+>
> 1. Quand vous éditez la méthode constructeur dans un composant
> 2. Quand vous ajoutez une nouvelle classe css. (Comme pour 1: la classe est réécrite pour chaque composant. Le process intervient dans la méthode constructeur)
@@ -37,6 +41,7 @@ Nous avons donc préparé un script séparé qui va rendre un fichier exécutabl
```
grunt pre-build
```
+
Vous trouverez l'exécutable dans le dossier `dist`.
Note : l'auto updater ne marchera pas car l'application n'est pas signée.
@@ -50,7 +55,6 @@ Les paquets sont créés en exécutant `grunt build` sur une plateforme Linux (e
Après avoir installé la version supportée de `node` et de `npm`, installer les paquets de builds.
-
Ubuntu/Debian:
```
diff --git a/docs/pt_BR/build.md b/docs/pt_BR/build.md
new file mode 100644
index 00000000..ad539996
--- /dev/null
+++ b/docs/pt_BR/build.md
@@ -0,0 +1,75 @@
+# Build
+
+Esta página também está disponível em [Japônes](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/build.md), [Coreano](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/build.md), [Russo](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/build.md), [Chinês simplificado](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/build.md), [Francês](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/build.md) e [Alemão](https://github.com/BoostIO/Boostnote/blob/master/docs/de/build.md).
+
+## Ambiente
+
+- npm: 6.x
+- node: 8.x
+
+## Desenvolvimento
+
+Nós usamos o Webpack HMR para desenvolver o Boostnote.
+Ao executar os seguintes comandos no diretório raiz do projeto, o Boostnote será iniciado com as configurações padrão.
+
+Instala os pacotes necessários usando o yarn.
+
+```
+$ yarn
+```
+
+Gerar e iniciar.
+
+```
+$ yarn run dev
+```
+
+> ### Notice
+>
+> Existe alguns casos onde você precisa atualizar o app manualmente.
+>
+> 1. Quando editar um método construtor de um componente
+> 2. Quando adicionar uma nova classe de css (similiar ao 1: a classe do css é reescrita por cada componente. Esse processo ocorre através do método construtor)
+
+## Deploy
+
+Nós usamos o Grunt para automatizar o desenvolvimento.
+Você pode gerar o programa usando `grunt`. Contudo, nós não recomendamos isso porque a tarefa padrão inclui _codedesign_ e _authenticode_.
+
+Então nós preparamos um _script_ separado, o qual somente cria um executável.
+
+```
+grunt pre-build
+```
+
+Você irá encontrar o executável na pasta `dist`. Nota: o atualizador automático não funciona porque o app não está certificado.
+
+Se você achar isto necessário, você pode usar o _codesign_ ou o _authenticode_ com esse executável.
+
+## Faça seus próprios pacotes de distribuição (deb, rpm)
+
+Pacotes de distribuição são gerados através do comando `grunt build` em plataforma Linux (e.g. Ubuntu, Fedora).
+
+> Nota: você pode criar `.deb` e `.rpm` em um mesmo ambiente.
+
+Depois de instalar uma versão suportada do `node` e do `npm`, deve-se instalar as dependências para gerar os pacotes.
+
+Ubuntu/Debian:
+
+```
+$ sudo apt-get install -y rpm fakeroot
+```
+
+Fedora:
+
+```
+$ sudo dnf install -y dpkg dpkg-dev rpm-build fakeroot
+```
+
+Então execute `grunt build`.
+
+```
+$ grunt build
+```
+
+Você vai encontrar o `.deb` e o `.rpm` na pasta`dist`.
diff --git a/docs/pt_BR/debug.md b/docs/pt_BR/debug.md
new file mode 100644
index 00000000..3de15741
--- /dev/null
+++ b/docs/pt_BR/debug.md
@@ -0,0 +1,40 @@
+# Como debugar Boostnote (app Electron)
+
+Esta página também está disponível em [Japônes](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/debug.md), [Coreano](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/debug.md), [Russo](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/debug.md), [Chinês simplificado](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/debug.md), [Francês](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/debug.md) e [Alemão](https://github.com/BoostIO/Boostnote/blob/master/docs/de/debug.md).
+
+## Debugar com o Google Chrome developer Tools
+
+Boostnote é um app Electron, por isso ele é baseado no Chromium; desenvolvedores podem usar o `Developer Tools` igual no Google Chrome.
+
+Você pode habilitar e desabilitar o `Developer Tools` assim:
+
+
+O `Developer Tools` deve parecer assim:
+
+
+Quando erros acontecem, eles são apresentados na aba `console`.
+
+### Debugando
+
+Por exemplo, você pode usar o `debugger` para adicionar um _breakpoint_ (ponto de parada) no código dessa forma:
+
+
+
+Isso é só um exemplo ilustrativo, mas você deve encontrar um jeito de debugar que encaixe no seu estilo.
+
+### Referências
+
+- [Documentação do Google Chrome sobre como debugar](https://developer.chrome.com/devtools)
+
+## Debugar com o Visual Studio Code (VS Code)
+
+1. Instale o plugin **[Debugger for Chrome](https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome 'Instale o pacote Debugger for Chrome')** para Visual Studio Code. Então reinicie-o.
+2. Pressione **Shift+Command+B** ou execute **Run Build Task** do menu global **Terminal**, então seleciona a task **Build Boostnote**. Ou execute `yarn run watch` no terminal.
+3. Quando a task acima estiver rodando, abra o **Debug view** na **Activity Bar** no lado do seu VS Code ou use o atalho **Shift+Command+D**.
+4. Selecione a configuração **Boostnote All** no **Debug configuration**, então clique na seta verde ou aperte **F5** para começar a debugar.
+5. Agora você deve encontrar seu **Boostnote** rodando. Você vai ver dois processos rodando, um com nome de **Boostnote Main** e outro com nome de **Boostnote Renderer**. Agora você pode adicionar os **debug breakpoints** no vscode. Se os seus **breakpoints** não forem alertados você pode precisar altenrar entre os processos **Boostnote Renderer** e **Boostnote Main**.
+
+### Referências
+
+- [Debugando uma aplicação Electron](https://electronjs.org/docs/tutorial/application-debugging)
+- [Debugger for Chrome](https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome)
diff --git a/docs/zh_TW/build.md b/docs/zh_TW/build.md
index 65b086ac..151f946d 100644
--- a/docs/zh_TW/build.md
+++ b/docs/zh_TW/build.md
@@ -1,10 +1,11 @@
# 編譯
-此文件還提供下列的語言 [日文](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/build.md), [韓文](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/build.md), [俄文](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/build.md), [簡體中文](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/build.md), [法文](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/build.md) and [德文](https://github.com/BoostIO/Boostnote/blob/master/docs/de/build.md).
+
+此文件還提供下列的語言 [日文](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/build.md), [韓文](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/build.md), [俄文](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/build.md), [簡體中文](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/build.md), [法文](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/build.md), [葡萄牙](https://github.com/BoostIO/Boostnote/blob/master/docs/pt_BR/build.md) and [德文](https://github.com/BoostIO/Boostnote/blob/master/docs/de/build.md).
## 環境
-* npm: 6.x
-* node: 8.x
+- npm: 6.x
+- node: 8.x
## 開發
@@ -25,7 +26,9 @@ $ yarn run dev
```
> ### Notice
+>
> There are some cases where you have to refresh the app manually.
+>
> 1. When editing a constructor method of a component
> 2. When adding a new css class (similar to 1: the CSS class is re-written by each component. This process occurs at the Constructor method.)
@@ -52,7 +55,6 @@ Distribution packages are created by exec `grunt build` on Linux platform (e.g.
After installing the supported version of `node` and `npm`, install build dependency packages.
-
Ubuntu/Debian:
```
diff --git a/extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js b/extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js
index aa766f6e..bc03e920 100644
--- a/extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js
+++ b/extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js
@@ -44,9 +44,46 @@
? match[2].replace('x', ' ')
: (parseInt(match[3], 10) + 1) + match[4]
replacements[i] = '\n' + indent + bullet + after
+
+ if (bullet) incrementRemainingMarkdownListNumbers(cm, pos)
}
}
-
cm.replaceSelections(replacements)
}
+ // Auto-updating Markdown list numbers when a new item is added to the
+ // middle of a list
+ function incrementRemainingMarkdownListNumbers(cm, pos) {
+ var startLine = pos.line, lookAhead = 0, skipCount = 0
+ var startItem = listRE.exec(cm.getLine(startLine)), startIndent = startItem[1]
+
+ do {
+ lookAhead += 1
+ var nextLineNumber = startLine + lookAhead
+ var nextLine = cm.getLine(nextLineNumber), nextItem = listRE.exec(nextLine)
+
+ if (nextItem) {
+ var nextIndent = nextItem[1]
+ var newNumber = (parseInt(startItem[3], 10) + lookAhead - skipCount)
+ var nextNumber = (parseInt(nextItem[3], 10)), itemNumber = nextNumber
+
+ if (startIndent === nextIndent && !isNaN(nextNumber)) {
+ if (newNumber === nextNumber) itemNumber = nextNumber + 1
+ if (newNumber > nextNumber) itemNumber = newNumber + 1
+ cm.replaceRange(
+ nextLine.replace(listRE, nextIndent + itemNumber + nextItem[4] + nextItem[5]),
+ {
+ line: nextLineNumber, ch: 0
+ }, {
+ line: nextLineNumber, ch: nextLine.length
+ })
+ } else {
+ if (startIndent.length > nextIndent.length) return
+ // This doesn't run if the next line immediatley indents, as it is
+ // not clear of the users intention (new indented item or same level)
+ if ((startIndent.length < nextIndent.length) && (lookAhead === 1)) return
+ skipCount += 1
+ }
+ }
+ } while (nextItem)
+ }
})
diff --git a/lib/ipcServer.js b/lib/ipcServer.js
index 487a9a63..42e229d3 100644
--- a/lib/ipcServer.js
+++ b/lib/ipcServer.js
@@ -32,6 +32,7 @@ ipcMain.on('config-renew', (e, payload) => {
globalShortcut.unregisterAll()
var { config } = payload
+ mainWindow.setMenuBarVisibility(config.ui.showMenuBar)
var errors = []
try {
globalShortcut.register(config.hotkey.toggleMain, toggleMainWindow)
diff --git a/lib/main-app.js b/lib/main-app.js
index f25d07d2..88e44294 100644
--- a/lib/main-app.js
+++ b/lib/main-app.js
@@ -3,6 +3,7 @@ const app = electron.app
const Menu = electron.Menu
const ipc = electron.ipcMain
const GhReleases = require('electron-gh-releases')
+const isDev = process.env.NODE_ENV !== 'production'
// electron.crashReporter.start()
var ipcServer = null
@@ -35,6 +36,10 @@ const updater = new GhReleases(ghReleasesOpts)
// Check for updates
// `status` returns true if there is a new update available
function checkUpdate () {
+ if (isDev) { // Prevents app from attempting to update when in dev mode.
+ console.log('Updates are disabled in Development mode, see main-app.js')
+ return true
+ }
if (process.platform === 'linux' || isUpdateReady) {
return true
}
@@ -94,12 +99,12 @@ app.on('ready', function () {
// Check update every day
setInterval(function () {
- checkUpdate()
+ if (!isDev) checkUpdate()
}, 1000 * 60 * 60 * 24)
// Check update after 10 secs to prevent file locking of Windows
setTimeout(() => {
- checkUpdate()
+ if (!isDev) checkUpdate()
ipc.on('update-check', function (event, msg) {
if (isUpdateReady) {
diff --git a/lib/main-menu.js b/lib/main-menu.js
index 91f3c8c6..dcd85217 100644
--- a/lib/main-menu.js
+++ b/lib/main-menu.js
@@ -85,39 +85,24 @@ const file = {
},
{
label: 'Focus Note',
- accelerator: 'Control+E',
+ accelerator: macOS ? 'Command+E' : 'Control+E',
click () {
mainWindow.webContents.send('detail:focus')
}
},
{
- type: 'separator'
+ label: 'Delete Note',
+ accelerator: macOS ? 'Command+Shift+Backspace' : 'Control+Shift+Backspace',
+ click () {
+ mainWindow.webContents.send('detail:delete')
+ }
},
{
- label: 'Export as',
- submenu: [
- {
- label: 'Plain Text (.txt)',
- click () {
- mainWindow.webContents.send('list:isMarkdownNote')
- mainWindow.webContents.send('export:save-text')
- }
- },
- {
- label: 'MarkDown (.md)',
- click () {
- mainWindow.webContents.send('list:isMarkdownNote')
- mainWindow.webContents.send('export:save-md')
- }
- },
- {
- label: 'HTML (.html)',
- click () {
- mainWindow.webContents.send('list:isMarkdownNote')
- mainWindow.webContents.send('export:save-html')
- }
- }
- ]
+ label: 'Clone Note',
+ accelerator: macOS ? 'Command+D' : 'Control+D',
+ click () {
+ mainWindow.webContents.send('list:clone')
+ }
},
{
type: 'separator'
@@ -134,13 +119,30 @@ const file = {
]
},
{
- type: 'separator'
- },
- {
- label: 'Format Table',
- click () {
- mainWindow.webContents.send('code:format-table')
- }
+ label: 'Export as',
+ submenu: [
+ {
+ label: 'Plain Text (.txt)',
+ click () {
+ mainWindow.webContents.send('list:isMarkdownNote', 'export-txt')
+ mainWindow.webContents.send('export:save-text')
+ }
+ },
+ {
+ label: 'MarkDown (.md)',
+ click () {
+ mainWindow.webContents.send('list:isMarkdownNote', 'export-md')
+ mainWindow.webContents.send('export:save-md')
+ }
+ },
+ {
+ label: 'HTML (.html)',
+ click () {
+ mainWindow.webContents.send('list:isMarkdownNote', 'export-html')
+ mainWindow.webContents.send('export:save-html')
+ }
+ }
+ ]
},
{
type: 'separator'
@@ -153,24 +155,20 @@ const file = {
}
},
{
- type: 'separator'
- },
- {
- label: 'Print',
- accelerator: 'CommandOrControl+P',
+ label: 'Format Table',
click () {
- mainWindow.webContents.send('list:isMarkdownNote')
- mainWindow.webContents.send('print')
+ mainWindow.webContents.send('code:format-table')
}
},
{
type: 'separator'
},
{
- label: 'Delete Note',
- accelerator: macOS ? 'Control+Backspace' : 'Control+Delete',
+ label: 'Print',
+ accelerator: 'CommandOrControl+P',
click () {
- mainWindow.webContents.send('detail:delete')
+ mainWindow.webContents.send('list:isMarkdownNote', 'print')
+ mainWindow.webContents.send('print')
}
}
]
@@ -296,9 +294,6 @@ const view = {
mainWindow.setFullScreen(!mainWindow.isFullScreen())
}
},
- {
- type: 'separator'
- },
{
label: 'Toggle Side Bar',
accelerator: 'CommandOrControl+B',
@@ -388,6 +383,27 @@ const help = {
{
label: 'Changelog',
click () { shell.openExternal('https://github.com/BoostIO/boost-releases') }
+ },
+ {
+ label: 'Cheatsheets',
+ submenu: [
+ {
+ label: 'Markdown',
+ click () { shell.openExternal('https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet') }
+ },
+ {
+ label: 'Latex',
+ click () { shell.openExternal('https://katex.org/docs/supported.html') }
+ },
+ {
+ label: 'HTML',
+ click () { shell.openExternal('https://htmlcheatsheet.com/') }
+ },
+ {
+ label: 'Boostnote',
+ click () { shell.openExternal('https://github.com/TobseF/boostnote-markdown-cheatsheet/blob/master/BOOSTNOTE_MARKDOWN_CHEAT_SHEET.md') }
+ }
+ ]
}
]
}
diff --git a/lib/main-window.js b/lib/main-window.js
index 512782de..418fd442 100644
--- a/lib/main-window.js
+++ b/lib/main-window.js
@@ -6,7 +6,6 @@ const Config = require('electron-config')
const config = new Config()
const _ = require('lodash')
-var showMenu = process.platform !== 'win32'
const windowSize = config.get('windowsize') || {
x: null,
y: null,
@@ -22,7 +21,6 @@ const mainWindow = new BrowserWindow({
useContentSize: true,
minWidth: 500,
minHeight: 320,
- autoHideMenuBar: showMenu,
webPreferences: {
zoomFactor: 1.0,
enableBlinkFeatures: 'OverlayScrollbars'
@@ -33,6 +31,7 @@ const mainWindow = new BrowserWindow({
const url = path.resolve(__dirname, './main.html')
mainWindow.loadURL('file://' + url)
+mainWindow.setMenuBarVisibility(false)
mainWindow.webContents.on('new-window', function (e) {
e.preventDefault()
diff --git a/locales/ja.json b/locales/ja.json
index e33bbaa6..e7295360 100644
--- a/locales/ja.json
+++ b/locales/ja.json
@@ -8,7 +8,10 @@
"to create a new note": "ノートを新規に作成",
"Toggle Mode": "モード切替",
"Add tag...": "タグを追加...",
+ "Star": "お気に入り",
+ "Fullscreen": "全画面",
"Trash": "ゴミ箱",
+ "Info": "情報",
"MODIFICATION DATE": "修正日",
"Words": "ワード",
"Letters": "文字",
@@ -26,6 +29,9 @@
"Storage Locations": "ストレージ",
"Add Storage Location": "ストレージロケーションを追加",
"Add Folder": "フォルダを追加",
+ "Create new folder": "新規フォルダ作成",
+ "Folder name": "フォルダ名",
+ "Create": "作成",
"Select Folder": "フォルダを選択",
"Open Storage folder": "ストレージフォルダを開く",
"Unlink": "リンク解除",
@@ -37,9 +43,15 @@
"White": "白",
"Solarized Dark": "明灰",
"Dark": "暗灰",
+ "Default New Note": "新規ノートの形式",
+ "Always Ask": "作成時に聞く",
"Show a confirmation dialog when deleting notes": "ノートを削除する時に確認ダイアログを表示する",
"Disable Direct Write (It will be applied after restarting)": "Disable Direct Write (It will be applied after restarting)",
+ "Save tags of a note in alphabetical order": "ノートのタグをアルファベット順に保存する",
+ "Show tags of a note in alphabetical order": "ノートのタグをアルファベット順に表示する",
"Show only related tags": "関連するタグのみ表示する",
+ "Enable live count of notes": "タグ選択時にノート数を再計算して表示する",
+ "New notes are tagged with the filtering tags": "新規ノートに選択中のタグを付与する",
"Editor Theme": "エディタのテーマ",
"Editor Font Size": "エディタのフォントサイズ",
"Editor Font Family": "エディタのフォント",
@@ -55,21 +67,32 @@
"vim": "vim",
"emacs": "emacs",
"⚠️ Please restart boostnote after you change the keymap": "⚠️ キーマップ変更後は Boostnote を再起動してください",
+ "Snippet Default Language": "スニペットのデフォルト言語",
+ "Extract title from front matter": "Front matterからタイトルを抽出する",
"Show line numbers in the editor": "エディタ内に行番号を表示",
"Allow editor to scroll past the last line": "エディタが最終行以降にスクロールできるようにする",
"Enable smart quotes": "スマートクォートを有効にする",
"Bring in web page title when pasting URL on editor": "URLを貼り付けた時にWebページのタイトルを取得する",
+ "Enable smart table editor": "スマートテーブルエディタを有効にする",
+ "Enable HTML paste": "HTML貼り付けを有効にする",
+ "Matching character pairs": "自動補完する括弧ペアの列記",
+ "Matching character triples": "自動補完する3文字括弧の列記",
+ "Exploding character pairs": "改行時に空行を挿入する括弧ペアの列記",
"Preview": "プレビュー",
"Preview Font Size": "プレビュー時フォントサイズ",
"Preview Font Family": "プレビュー時フォント",
"Code Block Theme": "コードブロックのテーマ",
+ "Allow line through checkbox": "チェック済みチェックボックスのテキストに取り消し線を付与する",
"Allow preview to scroll past the last line": "プレビュー時に最終行以降にスクロールできるようにする",
+ "When scrolling, synchronize preview with editor": "エディタとプレビューのスクロールを同期する",
"Show line numbers for preview code blocks": "プレビュー時のコードブロック内に行番号を表示する",
"LaTeX Inline Open Delimiter": "LaTeX 開始デリミタ(インライン)",
"LaTeX Inline Close Delimiter": "LaTeX 終了デリミタ(インライン)",
"LaTeX Block Open Delimiter": "LaTeX 開始デリミタ(ブロック)",
"LaTeX Block Close Delimiter": "LaTeX 終了デリミタ(ブロック)",
"PlantUML Server": "PlantUML サーバー",
+ "Custom CSS": "カスタムCSS",
+ "Allow custom CSS for preview": "プレビュー用のカスタムCSSを許可する",
"Community": "コミュニティ",
"Subscribe to Newsletter": "ニュースレターを購読する",
"GitHub": "GitHub",
@@ -105,7 +128,19 @@
"French": "フランス語",
"Show \"Saved to Clipboard\" notification when copying": "クリップボードコピー時に \"クリップボードに保存\" 通知を表示する",
"All Notes": "すべてのノート",
+ "Pin to Top": "一番上にピン留め",
+ "Remove pin": "ピン削除",
+ "Clone Note": "ノート複製",
+ "Copy Note Link": "ノートのリンクをコピー",
+ "Publish Blog": "ブログを公開",
"Starred": "スター付き",
+ "Empty Trash": "ゴミ箱を空にする",
+ "Restore Note": "ノート復元",
+ "Rename Folder": "フォルダの名称変更",
+ "Export Folder": "フォルダの書き出し",
+ "Export as txt": ".txtで書き出す",
+ "Export as md": ".mdで書き出す",
+ "Delete Folder": "フォルダ削除",
"Are you sure to ": "本当に ",
" delete": "このフォルダを",
"this folder?": "削除しますか?",
@@ -135,6 +170,8 @@
"Hotkeys": "ホットキー",
"Show/Hide Boostnote": "Boostnote の表示/非表示",
"Toggle Editor Mode": "エディタモードの切替",
+ "Delete Note": "ノート削除",
+ "Paste HTML": "HTMLで貼り付け",
"Restore": "リストア",
"Permanent Delete": "永久に削除",
"Confirm note deletion": "ノート削除確認",
@@ -165,6 +202,7 @@
"Cloud-Syncing-and-Backup": "Cloud-Syncing-and-Backup",
"Location": "ロケーション",
"Add": "追加",
+ "Export Storage": "ストレージの書き出し",
"Unlink Storage": "ストレージのリンクを解除",
"Unlinking removes this linked storage from Boostnote. No data is removed, please manually delete the folder from your hard drive if needed.": "リンクの解除ではBoostnoteからリンクされたストレージを削除しますが、データは削除されません。データを削除する場合はご自身でハードドライブからフォルダを削除してください。",
"Editor Rulers": "罫線",
diff --git a/locales/pt-BR.json b/locales/pt-BR.json
index 6b3126cc..273466eb 100644
--- a/locales/pt-BR.json
+++ b/locales/pt-BR.json
@@ -33,7 +33,7 @@
"White": "Branco",
"Solarized Dark": "Escuro Solarizado",
"Dark": "Escuro",
- "Show a confirmation dialog when deleting notes": "Mostrar um diálogo de confirmação ao escluir notas",
+ "Show a confirmation dialog when deleting notes": "Mostrar um diálogo de confirmação ao excluir notas",
"Editor Theme": "Tema do Editor",
"Editor Font Size": "Tamanho da Fonte do Editor",
"Editor Font Family": "Família da Fonte do Editor",
diff --git a/package.json b/package.json
index 1fb8e380..62a0ced8 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "boost",
"productName": "Boostnote",
- "version": "0.11.11",
+ "version": "0.11.13",
"main": "index.js",
"description": "Boostnote",
"license": "GPL-3.0",
@@ -31,7 +31,7 @@
"storage",
"electron"
],
- "author": "Dick Choi (https://github.com/Rokt33r)",
+ "author": "Junyoung Choi (https://github.com/Rokt33r)",
"contributors": [
"Kazu Yokomizo (https://github.com/kazup01)",
"dojineko (https://github.com/dojineko)",
@@ -41,7 +41,8 @@
"Yoshihisa Mochihara (https://github.com/yosmoc)",
"Mike Resoli (https://github.com/mikeres0)",
"tjado (https://github.com/tejado)",
- "Sota Sugiura (https://github.com/sota1235)"
+ "Sota Sugiura (https://github.com/sota1235)",
+ "Milo Todt (https://github.com/MiloTodt)"
],
"bugs": {
"url": "https://github.com/BoostIO/Boostnote/issues"
@@ -62,13 +63,15 @@
"escape-string-regexp": "^1.0.5",
"file-uri-to-path": "^1.0.0",
"file-url": "^2.0.2",
- "filenamify": "^2.0.0",
+ "filenamify": "^2.1.0",
"flowchart.js": "^1.6.5",
"font-awesome": "^4.3.0",
"fs-extra": "^5.0.0",
+ "highlight.js": "^9.13.1",
"i18n-2": "^0.7.2",
"iconv-lite": "^0.4.19",
"immutable": "^3.8.1",
+ "invert-color": "^2.0.0",
"js-sequence-diagrams": "^1000000.0.6",
"js-yaml": "^3.12.0",
"katex": "^0.9.0",
@@ -90,17 +93,20 @@
"mdurl": "^1.0.1",
"mermaid": "^8.0.0-rc.8",
"moment": "^2.10.3",
- "mousetrap": "^1.6.1",
+ "mousetrap": "^1.6.2",
"mousetrap-global-bind": "^1.1.0",
"node-ipc": "^8.1.0",
"raphael": "^2.2.7",
"react": "^15.5.4",
"react-autosuggest": "^9.4.0",
"react-codemirror": "^0.3.0",
+ "react-color": "^2.2.2",
"react-debounce-render": "^4.0.1",
"react-dom": "^15.0.2",
+ "react-image-carousel": "^2.0.18",
"react-redux": "^4.4.5",
"react-sortable-hoc": "^0.6.7",
+ "react-transition-group": "^2.5.0",
"redux": "^3.5.2",
"sander": "^0.5.1",
"sanitize-html": "^1.18.2",
@@ -142,6 +148,7 @@
"grunt": "^0.4.5",
"grunt-electron-installer": "2.1.0",
"history": "^1.17.0",
+ "husky": "^1.1.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^22.4.3",
"jest-localstorage-mock": "^2.2.0",
@@ -150,7 +157,6 @@
"merge-stream": "^1.0.0",
"mock-require": "^3.0.1",
"nib": "^1.1.0",
- "react-color": "^2.2.2",
"react-css-modules": "^3.7.6",
"react-input-autosize": "^1.1.0",
"react-router": "^2.4.0",
@@ -189,5 +195,10 @@
"/tests/jest.js",
"jest-localstorage-mock"
]
+ },
+ "husky": {
+ "hooks": {
+ "pre-commit": "npm run lint"
+ }
}
}
diff --git a/readme.md b/readme.md
index b3f2ec46..5657cb0a 100644
--- a/readme.md
+++ b/readme.md
@@ -5,10 +5,14 @@
Note-taking app for programmers.
Apps available for Mac, Windows, Linux, Android, and iOS.
Built with Electron, React + Redux, Webpack, and CSSModules.
## Authors & Maintainers
+
- [Rokt33r](https://github.com/rokt33r)
- [Sosuke](https://github.com/sosukesuzuki)
- [Kazz](https://github.com/kazup01)
@@ -20,11 +24,11 @@ Thank you to all the people who have contributed to Boostnote!
## Supporting Boostnote
-Boostnote is an open source project. It's an independent project with its ongoing development made possible thanks to the support by our amazing backers.
+Boostnote is an open source project. It's an independent project with its ongoing development made possible thanks to the support by our amazing backers.
Issues on Boostnote can be funded by anyone and the money will be distributed to contributors and maintainers. If you use Boostnote please consider becoming a backer:
-[](https://issuehunt.io/repos/53266139)
+[](https://issuehunt.io/repos/53266139)
## Community
- [Facebook Group](https://www.facebook.com/groups/boostnote/)
@@ -38,7 +42,7 @@ Issues on Boostnote can be funded by anyone and the money will be distributed to
* Website: https://boostnote.io
* Newsletters: https://boostnote.io/#subscribe
* [Development](https://github.com/BoostIO/Boostnote/blob/master/docs/build.md): Development configurations for Boostnote.
-* Copyright (C) 2016 - 2018 BoostIO, Inc.
+* Copyright (C) 2016 - 2019 BoostIO, Inc.
#### License
diff --git a/resources/icon/icon-x-light.svg b/resources/icon/icon-x-light.svg
new file mode 100644
index 00000000..39828f0b
--- /dev/null
+++ b/resources/icon/icon-x-light.svg
@@ -0,0 +1,17 @@
+
+
\ No newline at end of file
diff --git a/tests/components/TagListItem.snapshot.test.js b/tests/components/TagListItem.snapshot.test.js
index 8bea2ccb..637844e6 100644
--- a/tests/components/TagListItem.snapshot.test.js
+++ b/tests/components/TagListItem.snapshot.test.js
@@ -3,7 +3,7 @@ import renderer from 'react-test-renderer'
import TagListItem from 'browser/components/TagListItem'
it('TagListItem renders correctly', () => {
- const tagListItem = renderer.create()
+ const tagListItem = renderer.create()
expect(tagListItem.toJSON()).toMatchSnapshot()
})
diff --git a/tests/components/__snapshots__/TagListItem.snapshot.test.js.snap b/tests/components/__snapshots__/TagListItem.snapshot.test.js.snap
index ad883222..e3798130 100644
--- a/tests/components/__snapshots__/TagListItem.snapshot.test.js.snap
+++ b/tests/components/__snapshots__/TagListItem.snapshot.test.js.snap
@@ -12,6 +12,14 @@ exports[`TagListItem renders correctly 1`] = `
className="tagList-item"
onClick={[Function]}
>
+
diff --git a/tests/dataApi/attachmentManagement.test.js b/tests/dataApi/attachmentManagement.test.js
index 38b863de..800159b8 100644
--- a/tests/dataApi/attachmentManagement.test.js
+++ b/tests/dataApi/attachmentManagement.test.js
@@ -268,6 +268,7 @@ it('should test that copyAttachment with url (without extension, with query)', f
it('should replace the all ":storage" path with the actual storage path', function () {
const storageFolder = systemUnderTest.DESTINATION_FOLDER
+ const noteKey = '9c9c4ba3-bc1e-441f-9866-c1e9a806e31c'
const testInput =
'\n' +
' \n' +
@@ -276,14 +277,18 @@ it('should replace the all ":storage" path with the actual storage path', functi
' \n' +
'
\n' +
' \n' +
''
const actual = systemUnderTest.fixLocalURLS(testInput, storagePath)
@@ -311,6 +320,7 @@ it('should replace the all ":storage" path with the actual storage path', functi
it('should replace the ":storage" path with the actual storage path when they have different path separators', function () {
const storageFolder = systemUnderTest.DESTINATION_FOLDER
+ const noteKey = '9c9c4ba3-bc1e-441f-9866-c1e9a806e31c'
const testInput =
'\n' +
' \n' +
@@ -319,10 +329,10 @@ it('should replace the ":storage" path with the actual storage path when they ha
' \n' +
'