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

Merge branch 'master' into add-delete-hotkey

This commit is contained in:
jacob
2018-10-23 09:16:29 -05:00
committed by GitHub
66 changed files with 1354 additions and 101 deletions

View File

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

View File

@@ -57,6 +57,7 @@ export default class CodeEditor extends React.Component {
} }
this.searchHandler = (e, msg) => this.handleSearch(msg) this.searchHandler = (e, msg) => this.handleSearch(msg)
this.searchState = null this.searchState = null
this.scrollToLineHandeler = this.scrollToLine.bind(this)
this.formatTable = () => this.handleFormatTable() this.formatTable = () => this.handleFormatTable()
this.editorActivityHandler = () => this.handleEditorActivity() this.editorActivityHandler = () => this.handleEditorActivity()
@@ -125,6 +126,7 @@ export default class CodeEditor extends React.Component {
componentDidMount () { componentDidMount () {
const { rulers, enableRulers } = this.props const { rulers, enableRulers } = this.props
const expandSnippet = this.expandSnippet.bind(this) const expandSnippet = this.expandSnippet.bind(this)
eventEmitter.on('line:jump', this.scrollToLineHandeler)
const defaultSnippet = [ const defaultSnippet = [
{ {
@@ -475,7 +477,13 @@ export default class CodeEditor extends React.Component {
moveCursorTo (row, col) {} moveCursorTo (row, col) {}
scrollToLine (num) {} scrollToLine (event, num) {
const cursor = {
line: num,
ch: 1
}
this.editor.setCursor(cursor)
}
focus () { focus () {
this.editor.focus() this.editor.focus()

View File

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

View File

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

View File

@@ -80,7 +80,6 @@ function buildStyle (
url('${appPath}/resources/fonts/MaterialIcons-Regular.woff') format('woff'), url('${appPath}/resources/fonts/MaterialIcons-Regular.woff') format('woff'),
url('${appPath}/resources/fonts/MaterialIcons-Regular.ttf') format('truetype'); url('${appPath}/resources/fonts/MaterialIcons-Regular.ttf') format('truetype');
} }
${allowCustomCSS ? customCSS : ''}
${markdownStyle} ${markdownStyle}
body { body {
@@ -88,6 +87,11 @@ body {
font-size: ${fontSize}px; font-size: ${fontSize}px;
${scrollPastEnd && 'padding-bottom: 90vh;'} ${scrollPastEnd && 'padding-bottom: 90vh;'}
} }
@media print {
body {
padding-bottom: initial;
}
}
code { code {
font-family: '${codeBlockFontFamily.join("','")}'; font-family: '${codeBlockFontFamily.join("','")}';
background-color: rgba(0,0,0,0.04); background-color: rgba(0,0,0,0.04);
@@ -144,6 +148,8 @@ body p {
display: none display: none
} }
} }
${allowCustomCSS ? customCSS : ''}
` `
} }
@@ -425,6 +431,7 @@ export default class MarkdownPreview extends React.Component {
case 'dark': case 'dark':
case 'solarized-dark': case 'solarized-dark':
case 'monokai': case 'monokai':
case 'dracula':
return scrollBarDarkStyle return scrollBarDarkStyle
default: default:
return scrollBarStyle return scrollBarStyle
@@ -526,7 +533,8 @@ export default class MarkdownPreview extends React.Component {
prevProps.smartQuotes !== this.props.smartQuotes || prevProps.smartQuotes !== this.props.smartQuotes ||
prevProps.sanitize !== this.props.sanitize || prevProps.sanitize !== this.props.sanitize ||
prevProps.smartArrows !== this.props.smartArrows || prevProps.smartArrows !== this.props.smartArrows ||
prevProps.breaks !== this.props.breaks prevProps.breaks !== this.props.breaks ||
prevProps.lineThroughCheckbox !== this.props.lineThroughCheckbox
) { ) {
this.initMarkdown() this.initMarkdown()
this.rewriteIframe() this.rewriteIframe()
@@ -855,6 +863,15 @@ export default class MarkdownPreview extends React.Component {
return return
} }
const regexIsLine = /^:line:[0-9]/
if (regexIsLine.test(linkHash)) {
const numberPattern = /\d+/g
const lineNumber = parseInt(linkHash.match(numberPattern)[0])
eventEmitter.emit('line:jump', lineNumber)
return
}
// this will match the old link format storage.key-note.key // this will match the old link format storage.key-note.key
// e.g. // e.g.
// 877f99c3268608328037-1c211eb7dcb463de6490 // 877f99c3268608328037-1c211eb7dcb463de6490

View File

@@ -20,6 +20,10 @@ class MarkdownSplitEditor extends React.Component {
} }
} }
setValue (value) {
this.refs.code.setValue(value)
}
handleOnChange () { handleOnChange () {
this.value = this.refs.code.value this.value = this.refs.code.value
this.props.onChange() this.props.onChange()
@@ -145,7 +149,7 @@ class MarkdownSplitEditor extends React.Component {
styleName='codeEditor' styleName='codeEditor'
ref='code' ref='code'
width={this.state.codeEditorWidthInPercent + '%'} width={this.state.codeEditorWidthInPercent + '%'}
mode='GitHub Flavored Markdown' mode='Boost Flavored Markdown'
value={value} value={value}
theme={config.editor.theme} theme={config.editor.theme}
keyMap={config.editor.keyMap} keyMap={config.editor.keyMap}
@@ -192,6 +196,7 @@ class MarkdownSplitEditor extends React.Component {
noteKey={noteKey} noteKey={noteKey}
customCSS={config.preview.customCSS} customCSS={config.preview.customCSS}
allowCustomCSS={config.preview.allowCustomCSS} allowCustomCSS={config.preview.allowCustomCSS}
lineThroughCheckbox={config.preview.lineThroughCheckbox}
/> />
</div> </div>
) )

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -80,6 +80,9 @@ li
&.checked &.checked
text-decoration line-through text-decoration line-through
opacity 0.5 opacity 0.5
&.taskListItem.checked
text-decoration line-through
opacity 0.5
div.math-rendered div.math-rendered
text-align center text-align center
.math-failed .math-failed
@@ -478,3 +481,32 @@ body[data-theme="monokai"]
border-right solid 1px themeMonokaiTableBorder border-right solid 1px themeMonokaiTableBorder
kbd kbd
background-color themeDarkBackground background-color themeDarkBackground
themeDraculaTableOdd = $ui-dracula-noteDetail-backgroundColor
themeDraculaTableEven = darken($ui-dracula-noteDetail-backgroundColor, 10%)
themeDraculaTableHead = themeDraculaTableEven
themeDraculaTableBorder = themeDarkBorder
body[data-theme="dracula"]
color $ui-dracula-text-color
border-color themeDarkBorder
background-color $ui-dracula-noteDetail-backgroundColor
table
thead
tr
background-color themeDraculaTableHead
th
border-color themeDraculaTableBorder
&:last-child
border-right solid 1px themeDraculaTableBorder
tbody
tr:nth-child(2n + 1)
background-color themeDraculaTableOdd
tr:nth-child(2n)
background-color themeDraculaTableEven
td
border-color themeDraculaTableBorder
&:last-child
border-right solid 1px themeDraculaTableBorder
kbd
background-color themeDarkBackground

View File

@@ -21,7 +21,7 @@ function getId () {
function render (element, content, theme) { function render (element, content, theme) {
try { try {
let isDarkTheme = theme === 'dark' || theme === 'solarized-dark' || theme === 'monokai' let isDarkTheme = theme === 'dark' || theme === 'solarized-dark' || theme === 'monokai' || theme === 'dracula'
mermaidAPI.initialize({ mermaidAPI.initialize({
theme: isDarkTheme ? 'dark' : 'default', theme: isDarkTheme ? 'dark' : 'default',
themeCSS: isDarkTheme ? darkThemeStyling : '' themeCSS: isDarkTheme ? darkThemeStyling : ''

View File

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

View File

@@ -7,6 +7,7 @@ import _ from 'lodash'
import ConfigManager from 'browser/main/lib/ConfigManager' import ConfigManager from 'browser/main/lib/ConfigManager'
import katex from 'katex' import katex from 'katex'
import { lastFindInArray } from './utils' import { lastFindInArray } from './utils'
import ee from 'browser/main/lib/eventEmitter'
function createGutter (str, firstLineNumber) { function createGutter (str, firstLineNumber) {
if (Number.isNaN(firstLineNumber)) firstLineNumber = 1 if (Number.isNaN(firstLineNumber)) firstLineNumber = 1
@@ -223,7 +224,11 @@ class Markdown {
if (!liToken.attrs) { if (!liToken.attrs) {
liToken.attrs = [] liToken.attrs = []
} }
liToken.attrs.push(['class', 'taskListItem']) if (config.preview.lineThroughCheckbox) {
liToken.attrs.push(['class', `taskListItem${match[1] !== ' ' ? ' checked' : ''}`])
} else {
liToken.attrs.push(['class', 'taskListItem'])
}
} }
content = `<label class='taskListItem${match[1] !== ' ' ? ' checked' : ''}' for='checkbox-${startLine + 1}'><input type='checkbox'${match[1] !== ' ' ? ' checked' : ''} id='checkbox-${startLine + 1}'/> ${content.substring(4, content.length)}</label>` content = `<label class='taskListItem${match[1] !== ' ' ? ' checked' : ''}' for='checkbox-${startLine + 1}'><input type='checkbox'${match[1] !== ' ' ? ' checked' : ''} id='checkbox-${startLine + 1}'/> ${content.substring(4, content.length)}</label>`
} }

View File

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

View File

@@ -159,3 +159,29 @@ body[data-theme="monokai"]
color $ui-monokai-button--active-color color $ui-monokai-button--active-color
.search-optionList-item-name-surfix .search-optionList-item-name-surfix
color $ui-monokai-inactive-text-color color $ui-monokai-inactive-text-color
body[data-theme="dracula"]
.root
color $ui-dracula-text-color
&:hover
color #f8f8f2
background-color $ui-dark-button--hover-backgroundColor
border-color $ui-dracula-borderColor
.search-optionList
color #f8f8f2
border-color $ui-dracula-borderColor
background-color $ui-dracula-button-backgroundColor
.search-optionList-item
&:hover
background-color lighten($ui-dracula-button--hover-backgroundColor, 15%)
.search-optionList-item--active
background-color $ui-dracula-button--active-backgroundColor
color $ui-dracula-button--active-color
&:hover
background-color $ui-dark-button--hover-backgroundColor
color $ui-dracula-button--active-color
.search-optionList-item-name-surfix
color $ui-dracula-inactive-text-color

View File

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

View File

@@ -66,7 +66,9 @@ class MarkdownNoteDetail extends React.Component {
} }
componentWillReceiveProps (nextProps) { componentWillReceiveProps (nextProps) {
if (nextProps.note.key !== this.props.note.key && !this.state.isMovingNote) { const isNewNote = nextProps.note.key !== this.props.note.key
const hasDeletedTags = nextProps.note.tags.length < this.props.note.tags.length
if (!this.state.isMovingNote && (isNewNote || hasDeletedTags)) {
if (this.saveQueue != null) this.saveNow() if (this.saveQueue != null) this.saveNow()
this.setState({ this.setState({
note: Object.assign({}, nextProps.note) note: Object.assign({}, nextProps.note)
@@ -92,7 +94,7 @@ class MarkdownNoteDetail extends React.Component {
handleUpdateContent () { handleUpdateContent () {
const { note } = this.state const { note } = this.state
note.content = this.refs.content.value note.content = this.refs.content.value
note.title = markdown.strip(striptags(findNoteTitle(note.content))) note.title = markdown.strip(striptags(findNoteTitle(note.content, this.props.config.editor.enableFrontMatterTitle, this.props.config.editor.frontMatterTitleField)))
this.updateNote(note) this.updateNote(note)
} }
@@ -298,9 +300,29 @@ class MarkdownNoteDetail extends React.Component {
this.handleTrashButtonClick() this.handleTrashButtonClick()
} }
handleClearTodo () {
const { note } = this.state
const splitted = note.content.split('\n')
const clearTodoContent = splitted.map((line) => {
const trimmedLine = line.trim()
if (trimmedLine.match(/\[x\]/i)) {
return line.replace(/\[x\]/i, '[ ]')
} else {
return line
}
}).join('\n')
note.content = clearTodoContent
this.refs.content.setValue(note.content)
this.updateNote(note)
}
renderEditor () { renderEditor () {
const { config, ignorePreviewPointerEvents } = this.props const { config, ignorePreviewPointerEvents } = this.props
const { note } = this.state const { note } = this.state
if (this.state.editorType === 'EDITOR_PREVIEW') { if (this.state.editorType === 'EDITOR_PREVIEW') {
return <MarkdownEditor return <MarkdownEditor
ref='content' ref='content'
@@ -380,7 +402,7 @@ class MarkdownNoteDetail extends React.Component {
data={data} data={data}
onChange={this.handleUpdateTag.bind(this)} onChange={this.handleUpdateTag.bind(this)}
/> />
<TodoListPercentage percentageOfTodo={getTodoPercentageOfCompleted(note.content)} /> <TodoListPercentage onClearCheckboxClick={(e) => this.handleClearTodo(e)} percentageOfTodo={getTodoPercentageOfCompleted(note.content)} />
</div> </div>
<div styleName='info-right'> <div styleName='info-right'>
<ToggleModeButton onClick={(e) => this.handleSwitchMode(e)} editorType={editorType} /> <ToggleModeButton onClick={(e) => this.handleSwitchMode(e)} editorType={editorType} />

View File

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

View File

@@ -103,3 +103,8 @@ body[data-theme="monokai"]
.info .info
border-color $ui-monokai-borderColor border-color $ui-monokai-borderColor
background-color $ui-monokai-noteDetail-backgroundColor background-color $ui-monokai-noteDetail-backgroundColor
body[data-theme="dracula"]
.info
border-color $ui-dracula-borderColor
background-color $ui-dracula-noteDetail-backgroundColor

View File

@@ -112,7 +112,7 @@ class SnippetNoteDetail extends React.Component {
if (this.refs.tags) note.tags = this.refs.tags.value if (this.refs.tags) note.tags = this.refs.tags.value
note.description = this.refs.description.value note.description = this.refs.description.value
note.updatedAt = new Date() note.updatedAt = new Date()
note.title = findNoteTitle(note.description) note.title = findNoteTitle(note.description, false)
this.setState({ this.setState({
note note

View File

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

View File

@@ -76,3 +76,14 @@ body[data-theme="monokai"]
.tag-label .tag-label
color $ui-monokai-text-color color $ui-monokai-text-color
body[data-theme="dracula"]
.tag
background-color $ui-dracula-tag-backgroundColor
.tag-removeButton
border-color $ui-dracula-button--focus-borderColor
background-color transparent
.tag-label
color $ui-dracula-borderColor

View File

@@ -63,3 +63,10 @@ body[data-theme="monokai"]
.active .active
background-color #f92672 background-color #f92672
box-shadow 2px 0px 7px #222222 box-shadow 2px 0px 7px #222222
body[data-theme="dracula"]
.control-toggleModeButton
background-color #44475a
.active
background-color #bd93f9
box-shadow 2px 0px 7px #222222

View File

@@ -141,7 +141,7 @@ class Main extends React.Component {
componentDidMount () { componentDidMount () {
const { dispatch, config } = this.props const { dispatch, config } = this.props
const supportedThemes = ['dark', 'white', 'solarized-dark', 'monokai'] const supportedThemes = ['dark', 'white', 'solarized-dark', 'monokai', 'dracula']
if (supportedThemes.indexOf(config.ui.theme) !== -1) { if (supportedThemes.indexOf(config.ui.theme) !== -1) {
document.body.setAttribute('data-theme', config.ui.theme) document.body.setAttribute('data-theme', config.ui.theme)
@@ -297,7 +297,7 @@ class Main extends React.Component {
onMouseUp={e => this.handleMouseUp(e)} onMouseUp={e => this.handleMouseUp(e)}
> >
<SideNav <SideNav
{..._.pick(this.props, ['dispatch', 'data', 'config', 'location'])} {..._.pick(this.props, ['dispatch', 'data', 'config', 'params', 'location'])}
width={this.state.navWidth} width={this.state.navWidth}
/> />
{!config.isSideNavFolded && {!config.isSideNavFolded &&

View File

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

View File

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

View File

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

View File

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

View File

@@ -80,3 +80,14 @@ body[data-theme="monokai"]
color $ui-monokai-active-color color $ui-monokai-active-color
&:active &:active
color $ui-monokai-active-color color $ui-monokai-active-color
body[data-theme="dracula"]
navButtonColor()
.zoom
border-color $ui-dark-borderColor
color $ui-dracula-text-color
&:hover
transition 0.15s
color $ui-dracula-active-color
&:active
color $ui-dracula-active-color

View File

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

View File

@@ -18,6 +18,9 @@ body
::-webkit-scrollbar ::-webkit-scrollbar
width 12px width 12px
::-webkit-scrollbar-corner
background-color: transparent;
::-webkit-scrollbar-thumb ::-webkit-scrollbar-thumb
background-color rgba(0, 0, 0, 0.15) background-color rgba(0, 0, 0, 0.15)
@@ -162,6 +165,15 @@ body[data-theme="monokai"]
.sortableItemHelper .sortableItemHelper
color: $ui-monokai-text-color color: $ui-monokai-text-color
body[data-theme="dracula"]
::-webkit-scrollbar-thumb
background-color rgba(0, 0, 0, 0.3)
.ModalBase
.modalBack
background-color $ui-dracula-backgroundColor
.sortableItemHelper
color: $ui-dracula-text-color
body[data-theme="default"] body[data-theme="default"]
.SideNav ::-webkit-scrollbar-thumb .SideNav ::-webkit-scrollbar-thumb
background-color rgba(255, 255, 255, 0.3) background-color rgba(255, 255, 255, 0.3)

View File

@@ -48,7 +48,9 @@ export const DEFAULT_CONFIG = {
scrollPastEnd: false, scrollPastEnd: false,
type: 'SPLIT', type: 'SPLIT',
fetchUrlTitle: true, fetchUrlTitle: true,
enableTableEditor: false enableTableEditor: false,
enableFrontMatterTitle: true,
frontMatterTitleField: 'title'
}, },
preview: { preview: {
fontSize: '14', fontSize: '14',
@@ -66,7 +68,8 @@ export const DEFAULT_CONFIG = {
smartArrows: false, smartArrows: false,
allowCustomCSS: false, allowCustomCSS: false,
customCSS: '', customCSS: '',
sanitize: 'STRICT' // 'STRICT', 'ALLOW_STYLES', 'NONE' sanitize: 'STRICT', // 'STRICT', 'ALLOW_STYLES', 'NONE'
lineThroughCheckbox: true
}, },
blog: { blog: {
type: 'wordpress', // Available value: wordpress, add more types in the future plz type: 'wordpress', // Available value: wordpress, add more types in the future plz
@@ -148,6 +151,8 @@ function set (updates) {
document.body.setAttribute('data-theme', 'solarized-dark') document.body.setAttribute('data-theme', 'solarized-dark')
} else if (newConfig.ui.theme === 'monokai') { } else if (newConfig.ui.theme === 'monokai') {
document.body.setAttribute('data-theme', 'monokai') document.body.setAttribute('data-theme', 'monokai')
} else if (newConfig.ui.theme === 'dracula') {
document.body.setAttribute('data-theme', 'dracula')
} else { } else {
document.body.setAttribute('data-theme', 'default') document.body.setAttribute('data-theme', 'default')
} }

View File

@@ -128,3 +128,29 @@ body[data-theme="monokai"]
.control-confirmButton .control-confirmButton
colorMonokaiPrimaryButton() colorMonokaiPrimaryButton()
body[data-theme="dracula"]
.root
modalDracula()
width 500px
height 270px
overflow hidden
position relative
.header
background-color transparent
border-color $ui-dark-borderColor
color $ui-dracula-text-color
.control-folder-label
color $ui-dracula-text-color
.control-folder-input
border 1px solid $ui-input--create-folder-modal
color white
.description
color $ui-inactive-text-color
.control-confirmButton
colorDraculaPrimaryButton()

View File

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

View File

@@ -138,6 +138,10 @@ colorMonokaiControl()
background-color $ui-monokai-button-backgroundColor background-color $ui-monokai-button-backgroundColor
color $ui-monokai-text-color color $ui-monokai-text-color
colorDraculaControl()
border none
background-color $ui-dracula-button-backgroundColor
color $ui-dracula-text-color
body[data-theme="dark"] body[data-theme="dark"]
.root .root
@@ -220,3 +224,30 @@ body[data-theme="monokai"]
.group-section-control .group-section-control
select, .group-section-control-input select, .group-section-control-input
colorMonokaiControl() colorMonokaiControl()
body[data-theme="dracula"]
.root
color $ui-dracula-text-color
.group-header
color $ui-dracula-text-color
border-color $ui-dracula-borderColor
.group-header2
color $ui-dracula-text-color
.group-section-control-input
border-color $ui-dracula-borderColor
.group-control
border-color $ui-dracula-borderColor
.group-control-leftButton
colorDarkDefaultButton()
border-color $ui-dracula-borderColor
.group-control-rightButton
colorDraculaPrimaryButton()
.group-hint
colorDraculaControl()
.group-section-control
select, .group-section-control-input
colorDraculaControl()

View File

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

View File

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

View File

@@ -154,3 +154,26 @@ body[data-theme="monokai"]
.folderItem-right-dangerButton .folderItem-right-dangerButton
colorMonokaiPrimaryButton() colorMonokaiPrimaryButton()
body[data-theme="dracula"]
.folderItem
&:hover
background-color $ui-dracula-button-backgroundColor
.folderItem-left-danger
color $danger-color
.folderItem-left-key
color $ui-dark-inactive-text-color
.folderItem-left-colorButton
colorDraculaPrimaryButton()
.folderItem-right-button
colorDraculaPrimaryButton()
.folderItem-right-confirmButton
colorDraculaPrimaryButton()
.folderItem-right-dangerButton
colorDraculaPrimaryButton()

View File

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

View File

@@ -75,3 +75,10 @@ body[data-theme="monokai"]
.list .list
a a
color $ui-monokai-active-color color $ui-monokai-active-color
body[data-theme="dracula"]
.root
color $ui-dracula-text-color
.list
a
color $ui-dracula-active-color

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -89,7 +89,9 @@ class UiTab extends React.Component {
snippetDefaultLanguage: this.refs.editorSnippetDefaultLanguage.value, snippetDefaultLanguage: this.refs.editorSnippetDefaultLanguage.value,
scrollPastEnd: this.refs.scrollPastEnd.checked, scrollPastEnd: this.refs.scrollPastEnd.checked,
fetchUrlTitle: this.refs.editorFetchUrlTitle.checked, fetchUrlTitle: this.refs.editorFetchUrlTitle.checked,
enableTableEditor: this.refs.enableTableEditor.checked enableTableEditor: this.refs.enableTableEditor.checked,
enableFrontMatterTitle: this.refs.enableFrontMatterTitle.checked,
frontMatterTitleField: this.refs.frontMatterTitleField.value
}, },
preview: { preview: {
fontSize: this.refs.previewFontSize.value, fontSize: this.refs.previewFontSize.value,
@@ -107,6 +109,7 @@ class UiTab extends React.Component {
smartArrows: this.refs.previewSmartArrows.checked, smartArrows: this.refs.previewSmartArrows.checked,
sanitize: this.refs.previewSanitize.value, sanitize: this.refs.previewSanitize.value,
allowCustomCSS: this.refs.previewAllowCustomCSS.checked, allowCustomCSS: this.refs.previewAllowCustomCSS.checked,
lineThroughCheckbox: this.refs.lineThroughCheckbox.checked,
customCSS: this.customCSSCM.getCodeMirror().getValue() customCSS: this.customCSSCM.getCodeMirror().getValue()
} }
} }
@@ -187,6 +190,7 @@ class UiTab extends React.Component {
<option value='white'>{i18n.__('White')}</option> <option value='white'>{i18n.__('White')}</option>
<option value='solarized-dark'>{i18n.__('Solarized Dark')}</option> <option value='solarized-dark'>{i18n.__('Solarized Dark')}</option>
<option value='monokai'>{i18n.__('Monokai')}</option> <option value='monokai'>{i18n.__('Monokai')}</option>
<option value='dracula'>{i18n.__('Dracula')}</option>
<option value='dark'>{i18n.__('Dark')}</option> <option value='dark'>{i18n.__('Dark')}</option>
</select> </select>
</div> </div>
@@ -426,6 +430,31 @@ class UiTab extends React.Component {
</div> </div>
</div> </div>
<div styleName='group-section'>
<div styleName='group-section-label'>
{i18n.__('Front matter title field')}
</div>
<div styleName='group-section-control'>
<input styleName='group-section-control-input'
ref='frontMatterTitleField'
value={config.editor.frontMatterTitleField}
onChange={(e) => this.handleUIChange(e)}
type='text'
/>
</div>
</div>
<div styleName='group-checkBoxSection'>
<label>
<input onChange={(e) => this.handleUIChange(e)}
checked={this.state.config.editor.enableFrontMatterTitle}
ref='enableFrontMatterTitle'
type='checkbox'
/>&nbsp;
{i18n.__('Extract title from front matter')}
</label>
</div>
<div styleName='group-checkBoxSection'> <div styleName='group-checkBoxSection'>
<label> <label>
<input onChange={(e) => this.handleUIChange(e)} <input onChange={(e) => this.handleUIChange(e)}
@@ -512,6 +541,16 @@ class UiTab extends React.Component {
</select> </select>
</div> </div>
</div> </div>
<div styleName='group-checkBoxSection'>
<label>
<input onChange={(e) => this.handleUIChange(e)}
checked={this.state.config.preview.lineThroughCheckbox}
ref='lineThroughCheckbox'
type='checkbox'
/>&nbsp;
{i18n.__('Allow line through checkbox')}
</label>
</div>
<div styleName='group-checkBoxSection'> <div styleName='group-checkBoxSection'>
<label> <label>
<input onChange={(e) => this.handleUIChange(e)} <input onChange={(e) => this.handleUIChange(e)}

View File

@@ -16,7 +16,7 @@
margin 0 margin 0
border-radius 4px border-radius 4px
margin .2em 0 0 margin .5rem 0 0
background-color $ui-noteList-backgroundColor background-color $ui-noteList-backgroundColor
border 1px solid rgba(0,0,0,.3) border 1px solid rgba(0,0,0,.3)
box-shadow .05em .2em .6em rgba(0,0,0,.2) box-shadow .05em .2em .6em rgba(0,0,0,.2)
@@ -83,6 +83,23 @@ body[data-theme="monokai"]
background-color $ui-monokai-button-backgroundColor background-color $ui-monokai-button-backgroundColor
color $ui-monokai-text-color color $ui-monokai-text-color
body[data-theme="dracula"]
.TagSelect
.react-autosuggest__input
color $ui-dracula-text-color
ul
border-color $ui-dracula-borderColor
background-color $ui-dracula-noteList-backgroundColor
color $ui-dracula-text-color
&:before
background-color $ui-dark-noteList-backgroundColor
li[aria-selected="true"]
background-color $ui-dracula-button-backgroundColor
color $ui-dracula-text-color
body[data-theme="solarized-dark"] body[data-theme="solarized-dark"]
.TagSelect .TagSelect
.react-autosuggest__input .react-autosuggest__input

View File

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

View File

@@ -52,7 +52,10 @@
if (className.indexOf('cm-url') !== -1) { if (className.indexOf('cm-url') !== -1) {
const match = /^\((.*)\)|\[(.*)\]|(.*)$/.exec(el.textContent) const match = /^\((.*)\)|\[(.*)\]|(.*)$/.exec(el.textContent)
return match[1] || match[2] || match[3] const url = match[1] || match[2] || match[3]
// `:storage` is the value of the variable `STORAGE_FOLDER_PLACEHOLDER` defined in `browser/main/lib/dataApi/attachmentManagement`
return /^:storage(?:\/|%5C)/.test(url) ? null : url
} }
return null return null

View File

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

View File

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

View File

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

View File

@@ -10,6 +10,7 @@
<link rel="stylesheet" href="../node_modules/codemirror/lib/codemirror.css"> <link rel="stylesheet" href="../node_modules/codemirror/lib/codemirror.css">
<link rel="stylesheet" href="../node_modules/katex/dist/katex.min.css"> <link rel="stylesheet" href="../node_modules/katex/dist/katex.min.css">
<link rel="stylesheet" href="../node_modules/codemirror/addon/dialog/dialog.css"> <link rel="stylesheet" href="../node_modules/codemirror/addon/dialog/dialog.css">
<link rel="stylesheet" href="../extra_scripts/codemirror/mode/bfm/bfm.css">
<title>Boostnote</title> <title>Boostnote</title>
@@ -94,9 +95,13 @@
<script src="../node_modules/codemirror/keymap/vim.js"></script> <script src="../node_modules/codemirror/keymap/vim.js"></script>
<script src="../node_modules/codemirror/keymap/emacs.js"></script> <script src="../node_modules/codemirror/keymap/emacs.js"></script>
<script src="../node_modules/codemirror/addon/runmode/runmode.js"></script> <script src="../node_modules/codemirror/addon/runmode/runmode.js"></script>
<script src="../node_modules/codemirror/mode/xml/xml.js"></script>
<script src="../node_modules/codemirror/mode/markdown/markdown.js"></script>
<script src="../node_modules/codemirror/mode/gfm/gfm.js"></script>
<script src="../extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js"></script> <script src="../extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js"></script>
<script src="../extra_scripts/codemirror/addon/hyperlink/hyperlink.js"></script> <script src="../extra_scripts/codemirror/addon/hyperlink/hyperlink.js"></script>
<script src="../extra_scripts/codemirror/mode/bfm/bfm.js"></script>
<script src="../node_modules/codemirror/addon/edit/closebrackets.js"></script> <script src="../node_modules/codemirror/addon/edit/closebrackets.js"></script>
<script src="../node_modules/codemirror/addon/edit/matchbrackets.js"></script> <script src="../node_modules/codemirror/addon/edit/matchbrackets.js"></script>

View File

@@ -1,7 +1,7 @@
{ {
"name": "boost", "name": "boost",
"productName": "Boostnote", "productName": "Boostnote",
"version": "0.11.9", "version": "0.11.10",
"main": "index.js", "main": "index.js",
"description": "Boostnote", "description": "Boostnote",
"license": "GPL-3.0", "license": "GPL-3.0",
@@ -53,7 +53,7 @@
"aws-sdk": "^2.48.0", "aws-sdk": "^2.48.0",
"aws-sdk-mobile-analytics": "^0.9.2", "aws-sdk-mobile-analytics": "^0.9.2",
"chart.js": "^2.7.2", "chart.js": "^2.7.2",
"codemirror": "^5.39.0", "codemirror": "^5.40.2",
"codemirror-mode-elixir": "^1.1.1", "codemirror-mode-elixir": "^1.1.1",
"electron-config": "^1.0.0", "electron-config": "^1.0.0",
"electron-gh-releases": "^2.0.2", "electron-gh-releases": "^2.0.2",
@@ -116,8 +116,10 @@
"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",
"color": "^3.0.0",
"concurrently": "^3.4.0", "concurrently": "^3.4.0",
"copy-to-clipboard": "^3.0.6", "copy-to-clipboard": "^3.0.6",
"css": "^2.2.4",
"css-loader": "^0.19.0", "css-loader": "^0.19.0",
"devtron": "^1.1.0", "devtron": "^1.1.0",
"dom-storage": "^2.0.2", "dom-storage": "^2.0.2",

View File

@@ -30,7 +30,7 @@ Issues on Boostnote can be funded by anyone and the money will be distributed to
- [Facebook Group](https://www.facebook.com/groups/boostnote/) - [Facebook Group](https://www.facebook.com/groups/boostnote/)
- [Twitter](https://twitter.com/boostnoteapp) - [Twitter](https://twitter.com/boostnoteapp)
- [Slack Group](https://join.slack.com/t/boostnote-group/shared_invite/enQtMzkxOTk4ODkyNzc0LThkNmMzY2VlZjVhYTNiYjE5YjQyZGVjNTJlYTY1OGMyZTFjNGU5YTUyYjUzOWZhYTU4OTVlNDYyNDFjYWMzNDM) - [Slack Group](https://join.slack.com/t/boostnote-group/shared_invite/enQtMzkxOTk4ODkyNzc0LThkNmMzY2VlZjVhYTNiYjE5YjQyZGVjNTJlYTY1OGMyZTFjNGU5YTUyYjUzOWZhYTU4OTVlNDYyNDFjYWMzNDM)
- [Blog](https://boostlog.io/tags/boostnote) - [Blog](https://medium.com/boostnote)
- [Reddit](https://www.reddit.com/r/Boostnote/) - [Reddit](https://www.reddit.com/r/Boostnote/)

View File

@@ -3,6 +3,7 @@
exports[`TagListItem renders correctly 1`] = ` exports[`TagListItem renders correctly 1`] = `
<div <div
className="tagList-itemContainer" className="tagList-itemContainer"
onContextMenu={[Function]}
> >
<div <div
className="tagList-itemNarrow" className="tagList-itemNarrow"

View File

@@ -20,7 +20,47 @@ test('findNoteTitle#find should return a correct title (string)', t => {
testCases.forEach(testCase => { testCases.forEach(testCase => {
const [input, expected] = testCase const [input, expected] = testCase
t.is(findNoteTitle(input), expected, `Test for find() input: ${input} expected: ${expected}`) t.is(findNoteTitle(input, false), expected, `Test for find() input: ${input} expected: ${expected}`)
}) })
}) })
test('findNoteTitle#find should ignore front matter when enableFrontMatterTitle=false', t => {
// [input, expected]
const testCases = [
['---\nlayout: test\ntitle: hoge hoge hoge \n---\n# fuga', '# fuga'],
['---\ntitle:hoge\n---\n# fuga', '# fuga'],
['title: fuga\n# hoge', '# hoge']
]
testCases.forEach(testCase => {
const [input, expected] = testCase
t.is(findNoteTitle(input, false), expected, `Test for find() input: ${input} expected: ${expected}`)
})
})
test('findNoteTitle#find should respect front matter when enableFrontMatterTitle=true', t => {
// [input, expected]
const testCases = [
['---\nlayout: test\ntitle: hoge hoge hoge \n---\n# fuga', 'hoge hoge hoge'],
['---\ntitle:hoge\n---\n# fuga', 'hoge'],
['title: fuga\n# hoge', '# hoge']
]
testCases.forEach(testCase => {
const [input, expected] = testCase
t.is(findNoteTitle(input, true), expected, `Test for find() input: ${input} expected: ${expected}`)
})
})
test('findNoteTitle#find should respect frontMatterTitleField when provided', t => {
// [input, expected]
const testCases = [
['---\ntitle: hoge\n---\n# fuga', '# fuga'],
['---\ncustom: hoge\n---\n# fuga', 'hoge']
]
testCases.forEach(testCase => {
const [input, expected] = testCase
t.is(findNoteTitle(input, true, 'custom'), expected, `Test for find() input: ${input} expected: ${expected}`)
})
})

View File

@@ -31,7 +31,7 @@ Generated by [AVA](https://ava.li).
`<ul>␊ `<ul>␊
<li class="taskListItem"><input type="checkbox" id="checkbox-2" /> Unchecked</li>␊ <li class="taskListItem"><input type="checkbox" id="checkbox-2" /> Unchecked</li>␊
<li class="taskListItem"><input type="checkbox" checked id="checkbox-3" /> Checked</li>␊ <li class="taskListItem checked"><input type="checkbox" checked id="checkbox-3" /> Checked</li>␊
</ul>␊ </ul>␊
` `

View File

@@ -1803,9 +1803,9 @@ codemirror@^5.18.2, codemirror@^5.20.2:
version "5.38.0" version "5.38.0"
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.38.0.tgz#26a9551446e51dbdde36aabe60f72469724fd332" resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.38.0.tgz#26a9551446e51dbdde36aabe60f72469724fd332"
codemirror@^5.39.0: codemirror@^5.40.2:
version "5.39.0" version "5.40.2"
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.39.0.tgz#4654f7d2f7e525e04a62e72d9482348ccb37dce5" resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.40.2.tgz#f4a41fee2d84e679543591b3680af259d903330b"
coffee-script@^1.10.0, coffee-script@^1.12.4: coffee-script@^1.10.0, coffee-script@^1.12.4:
version "1.12.7" version "1.12.7"
@@ -1832,7 +1832,13 @@ color-convert@^1.3.0, color-convert@^1.9.0:
dependencies: dependencies:
color-name "^1.1.1" color-name "^1.1.1"
color-name@^1.0.0, color-name@^1.1.1: color-convert@^1.9.1:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
dependencies:
color-name "1.1.3"
color-name@1.1.3, color-name@^1.0.0, color-name@^1.1.1:
version "1.1.3" version "1.1.3"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
@@ -1842,6 +1848,13 @@ color-string@^0.3.0:
dependencies: dependencies:
color-name "^1.0.0" color-name "^1.0.0"
color-string@^1.5.2:
version "1.5.3"
resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc"
dependencies:
color-name "^1.0.0"
simple-swizzle "^0.2.2"
color@^0.11.0: color@^0.11.0:
version "0.11.4" version "0.11.4"
resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764" resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764"
@@ -1850,6 +1863,13 @@ color@^0.11.0:
color-convert "^1.3.0" color-convert "^1.3.0"
color-string "^0.3.0" color-string "^0.3.0"
color@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a"
dependencies:
color-convert "^1.9.1"
color-string "^1.5.2"
colormin@^1.0.5: colormin@^1.0.5:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133" resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133"
@@ -2149,6 +2169,15 @@ css-selector-tokenizer@^0.5.0, css-selector-tokenizer@^0.5.1:
cssesc "^0.1.0" cssesc "^0.1.0"
fastparse "^1.1.1" fastparse "^1.1.1"
css@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929"
dependencies:
inherits "^2.0.3"
source-map "^0.6.1"
source-map-resolve "^0.5.2"
urix "^0.1.0"
cssesc@^0.1.0: cssesc@^0.1.0:
version "0.1.0" version "0.1.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4"
@@ -4591,6 +4620,10 @@ is-arrayish@^0.2.1:
version "0.2.1" version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
is-arrayish@^0.3.1:
version "0.3.2"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
is-binary-path@^1.0.0: is-binary-path@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
@@ -8047,6 +8080,12 @@ signale@^1.2.1:
figures "^2.0.0" figures "^2.0.0"
pkg-conf "^2.1.0" pkg-conf "^2.1.0"
simple-swizzle@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
dependencies:
is-arrayish "^0.3.1"
single-line-log@^1.1.2: single-line-log@^1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/single-line-log/-/single-line-log-1.1.2.tgz#c2f83f273a3e1a16edb0995661da0ed5ef033364" resolved "https://registry.yarnpkg.com/single-line-log/-/single-line-log-1.1.2.tgz#c2f83f273a3e1a16edb0995661da0ed5ef033364"
@@ -8138,7 +8177,7 @@ source-list-map@^0.1.4, source-list-map@~0.1.7:
version "0.1.8" version "0.1.8"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106"
source-map-resolve@^0.5.0: source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
version "0.5.2" version "0.5.2"
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259"
dependencies: dependencies: