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

Merge branch 'master' into feature-add-esilnt-rule

This commit is contained in:
Sota Sugiura
2017-03-21 15:04:14 +09:00
committed by GitHub
20 changed files with 233 additions and 57 deletions

View File

@@ -55,19 +55,64 @@ export default class CodeEditor extends React.Component {
indentWithTabs: this.props.indentType !== 'space',
keyMap: this.props.keyMap,
inputStyle: 'textarea',
dragDrop: false,
extraKeys: {
Tab: function (cm) {
const cursor = cm.getCursor()
const line = cm.getLine(cursor.line)
if (cm.somethingSelected()) cm.indentSelection('add')
else {
if (cm.getOption('indentWithTabs')) {
cm.execCommand('insertTab')
const tabs = cm.getOption('indentWithTabs')
if (line.trimLeft() === '- ' || line.trimLeft() === '* ' || line.trimLeft() === '+ ') {
cm.execCommand('goLineStart')
if (tabs) {
cm.execCommand('insertTab')
} else {
cm.execCommand('insertSoftTab')
}
cm.execCommand('goLineEnd')
} else {
cm.execCommand('insertSoftTab')
if (tabs) {
cm.execCommand('insertTab')
} else {
cm.execCommand('insertSoftTab')
}
}
}
},
'Cmd-T': function (cm) {
// Do nothing
},
Enter: (cm) => {
const cursor = cm.getCursor()
const line = cm.getLine(cursor.line)
let bulletType;
if (line.trim().startsWith('- ')) {
bulletType = 1 // dash
} else if (line.trim().startsWith('* ')) {
bulletType = 2 // star
} else if (line.trim().startsWith('+ ')) {
bulletType = 3 // plus
} else {
bulletType = 0 // not a bullet
}
const numberedListRegex = /^(\d+)\. .+/
const match = line.trim().match(numberedListRegex)
if (bulletType !== 0 || match) {
cm.execCommand('newlineAndIndent')
const range = {line: cursor.line + 1, ch: cm.getLine(cursor.line + 1).length}
if (match) {
cm.replaceRange((parseInt(match[1]) + 1) + '. ', range)
} else if (bulletType === 1) {
cm.replaceRange('- ', range)
} else if (bulletType === 2) {
cm.replaceRange('* ', range)
} else if (bulletType === 3) {
cm.replaceRange('+ ', range)
}
} else {
cm.execCommand('newlineAndIndent')
}
}
}
})

View File

@@ -11,6 +11,10 @@ class MarkdownEditor extends React.Component {
this.escapeFromEditor = ['Control', 'w']
this.supportMdBold = ['Control', 'b']
this.supportMdWordBold = ['Control', ':']
this.state = {
status: 'PREVIEW',
renderValue: props.value,
@@ -78,7 +82,7 @@ class MarkdownEditor extends React.Component {
this.refs.code.blur()
this.refs.preview.focus()
}
eventEmitter.emit('topbar:showlockbutton')
eventEmitter.emit('topbar:togglelockbutton', this.state.status)
})
}
}
@@ -95,7 +99,7 @@ class MarkdownEditor extends React.Component {
this.refs.preview.focus()
this.refs.preview.scrollTo(cursorPosition.line)
})
eventEmitter.emit('topbar:showlockbutton')
eventEmitter.emit('topbar:togglelockbutton', this.state.status)
}
}
@@ -111,7 +115,7 @@ class MarkdownEditor extends React.Component {
}, () => {
this.refs.code.focus()
})
eventEmitter.emit('topbar:showlockbutton')
eventEmitter.emit('topbar:togglelockbutton', this.state.status)
}
}
@@ -148,7 +152,7 @@ class MarkdownEditor extends React.Component {
} else {
this.refs.code.focus()
}
eventEmitter.emit('topbar:showlockbutton')
eventEmitter.emit('topbar:togglelockbutton', this.state.status)
}
reload () {
@@ -157,7 +161,8 @@ class MarkdownEditor extends React.Component {
this.renderPreview(this.props.value)
}
handleKeyDown (e) {
handleKeyDown(e) {
if (this.state.status !== 'CODE') return false
const keyPressed = Object.assign(this.state.keyPressed, {
[e.key]: true
})
@@ -166,6 +171,27 @@ class MarkdownEditor extends React.Component {
if (!this.state.isLocked && this.state.status === 'CODE' && this.escapeFromEditor.every(isNoteHandlerKey)) {
document.activeElement.blur()
}
if (this.supportMdBold.every(isNoteHandlerKey)) {
this.addMdAndMoveCaretToCenter('****')
}
if (this.supportMdWordBold.every(isNoteHandlerKey)) {
this.addMdBetweenWord('**')
}
}
addMdAndMoveCaretToCenter (mdElement) {
const currentCaret = this.refs.code.editor.getCursor()
const cmDoc = this.refs.code.editor.getDoc()
cmDoc.replaceRange(mdElement, currentCaret)
this.refs.code.editor.setCursor({line: currentCaret.line, ch: currentCaret.ch + mdElement.length/2})
}
addMdBetweenWord (mdElement) {
const currentCaret = this.refs.code.editor.getCursor()
const word = this.refs.code.editor.findWordAt(currentCaret)
const cmDoc = this.refs.code.editor.getDoc()
cmDoc.replaceRange(mdElement, word.anchor)
cmDoc.replaceRange(mdElement, { line: word.head.line, ch: word.head.ch + mdElement.length })
}
handleKeyUp (e) {

View File

@@ -243,6 +243,10 @@ export default class MarkdownPreview extends React.Component {
this.refs.root.contentWindow.document.body.setAttribute('data-theme', theme)
this.refs.root.contentWindow.document.body.innerHTML = markdown.render(value)
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('.taskListItem'), (el) => {
el.parentNode.parentNode.style.listStyleType = 'none'
})
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('a'), (el) => {
el.addEventListener('click', this.anchorClickHandler)
})

View File

@@ -182,8 +182,6 @@ ul
list-style-type circle
&>li>ul
list-style-type square
ul.markdownIt-TOC, ul.markdownIt-TOC ul
list-style-type none
ol
list-style-type decimal
padding-left 2em

View File

@@ -1,7 +1,6 @@
import markdownit from 'markdown-it'
import emoji from 'markdown-it-emoji'
import math from '@rokt33r/markdown-it-math'
import tocAndAnchor from 'markdown-it-toc-and-anchor'
import _ from 'lodash'
const katex = window.katex
@@ -37,9 +36,6 @@ var md = markdownit({
md.use(emoji, {
shortcuts: {}
})
md.use(tocAndAnchor, {
anchorLink: false
})
md.use(math, {
inlineRenderer: function (str) {
let output = ''

View File

@@ -26,12 +26,12 @@ class MarkdownNoteDetail extends React.Component {
title: '',
content: ''
}, props.note),
editorStatus: false,
isLockButtonShown: false,
isLocked: false
}
this.dispatchTimer = null
this.showLockButton = this.handleShowLockButton.bind(this)
this.toggleLockButton = this.handleToggleLockButton.bind(this)
}
focus () {
@@ -39,7 +39,7 @@ class MarkdownNoteDetail extends React.Component {
}
componentDidMount () {
ee.on('topbar:showlockbutton', this.showLockButton)
ee.on('topbar:togglelockbutton', this.toggleLockButton)
}
componentWillReceiveProps (nextProps) {
@@ -59,16 +59,19 @@ class MarkdownNoteDetail extends React.Component {
}
componentDidUnmount () {
ee.off('topbar:lock', this.showLockButton)
ee.off('topbar:togglelockbutton', this.toggleLockButton)
}
findTitle (value) {
let splitted = value.split('\n')
let title = null
let isMarkdownInCode = false
for (let i = 0; i < splitted.length; i++) {
let trimmedLine = splitted[i].trim()
if (trimmedLine.match(/^# .+/)) {
if (trimmedLine.match('```')) {
isMarkdownInCode = !isMarkdownInCode
} else if (isMarkdownInCode === false && trimmedLine.match(/^# +/)) {
title = trimmedLine.substring(1, trimmedLine.length).trim()
break
}
@@ -216,6 +219,7 @@ class MarkdownNoteDetail extends React.Component {
e.preventDefault()
ee.emit('editor:lock')
this.setState({ isLocked: !this.state.isLocked })
if (this.state.isLocked) this.focus()
}
getToggleLockButton () {
@@ -226,8 +230,13 @@ class MarkdownNoteDetail extends React.Component {
if (e.keyCode === 27) this.handleDeleteCancelButtonClick(e)
}
handleShowLockButton () {
this.setState({editorStatus: this.refs.content.state.status})
handleToggleLockButton (event, noteStatus) {
// first argument event is not used
if (this.props.config.editor.switchPreview === 'BLUR' && noteStatus === 'CODE') {
this.setState({isLockButtonShown: true})
} else {
this.setState({isLockButtonShown: false})
}
}
handleFocus (e) {
@@ -268,20 +277,31 @@ class MarkdownNoteDetail extends React.Component {
{(() => {
const faClassName = `fa ${this.getToggleLockButton()}`
const lockButtonComponent =
<button styleName='info-right-button'
<button styleName='control-lockButton'
onFocus={(e) => this.handleFocus(e)}
onMouseDown={(e) => this.handleLockButtonMouseDown(e)}
>
<i className={faClassName} />
<i className={faClassName} styleName='lock-button'/>
<span styleName='control-lockButton-tooltip'>
{this.state.isLocked ? 'Unlock' : 'Lock'}
</span>
</button>
return (
this.state.editorStatus === 'CODE' ? lockButtonComponent : ''
this.state.isLockButtonShown ? lockButtonComponent : ''
)
})()}
<button styleName='info-right-button'
<button styleName='control-trashButton'
onClick={(e) => this.handleContextButtonClick(e)}
>
<i className='fa fa-ellipsis-v' />
<svg height="17px" id="Capa_1" style={{"enableBackground":"new 0 0 753.23 753.23"}} width="17px" version="1.1" viewBox="0 0 753.23 753.23" x="0px" y="0px" xmlSpace="preserve">
<g>
<g id="_x34__19_">
<g>
<path d="M494.308,659.077c12.993,0,23.538-10.546,23.538-23.539V353.077c0-12.993-10.545-23.539-23.538-23.539&#xA;&#x9;&#x9;&#x9;&#x9;s-23.538,10.545-23.538,23.539v282.461C470.77,648.531,481.314,659.077,494.308,659.077z M635.538,94.154h-141.23V47.077&#xA;&#x9;&#x9;&#x9;&#x9;C494.308,21.067,473.24,0,447.23,0H306c-26.01,0-47.077,21.067-47.077,47.077v47.077h-141.23&#xA;&#x9;&#x9;&#x9;&#x9;c-26.01,0-47.077,21.067-47.077,47.077v47.077c0,25.986,21.067,47.077,47.077,47.077v423.692&#xA;&#x9;&#x9;&#x9;&#x9;c0,51.996,42.157,94.153,94.154,94.153h329.539c51.996,0,94.153-42.157,94.153-94.153V235.385&#xA;&#x9;&#x9;&#x9;&#x9;c26.01,0,47.077-21.091,47.077-47.077V141.23C682.615,115.221,661.548,94.154,635.538,94.154z M306,70.615&#xA;&#x9;&#x9;&#x9;&#x9;c0-12.993,10.545-23.539,23.538-23.539h94.154c12.993,0,23.538,10.545,23.538,23.539v23.539c-22.809,0-141.23,0-141.23,0V70.615z&#xA;&#x9;&#x9;&#x9;&#x9; M588.461,659.077c0,25.986-21.066,47.076-47.076,47.076H211.846c-26.01,0-47.077-21.09-47.077-47.076V235.385h423.692V659.077z&#xA;&#x9;&#x9;&#x9;&#x9; M612,188.308H141.23c-12.993,0-23.538-10.545-23.538-23.539s10.545-23.539,23.538-23.539H612&#xA;&#x9;&#x9;&#x9;&#x9;c12.993,0,23.538,10.545,23.538,23.539S624.993,188.308,612,188.308z M258.923,659.077c12.993,0,23.539-10.546,23.539-23.539&#xA;&#x9;&#x9;&#x9;&#x9;V353.077c0-12.993-10.545-23.539-23.539-23.539s-23.539,10.545-23.539,23.539v282.461&#xA;&#x9;&#x9;&#x9;&#x9;C235.384,648.531,245.93,659.077,258.923,659.077z M376.615,659.077c12.993,0,23.538-10.546,23.538-23.539V353.077&#xA;&#x9;&#x9;&#x9;&#x9;c0-12.993-10.545-23.539-23.538-23.539s-23.539,10.545-23.539,23.539v282.461C353.077,648.531,363.622,659.077,376.615,659.077z"/>
</g>
</g>
</g>
</svg>
</button>
</div>
</div>

View File

@@ -9,6 +9,28 @@
background-color $ui-noteDetail-backgroundColor
box-shadow $note-detail-box-shadow
.lock-button
padding-bottom 3px
.control-lockButton
topBarButtonLight()
.control-lockButton-tooltip
tooltip()
position fixed
pointer-events none
top 50px
z-index 200
padding 5px
line-height normal
border-radius 2px
opacity 0
transition 0.1s
.control-trashButton
float right
topBarButtonLight()
.body
absolute left right
left $note-detail-left-margin
@@ -24,3 +46,12 @@ body[data-theme="dark"]
border-color $ui-dark-borderColor
background-color $ui-dark-noteDetail-backgroundColor
box-shadow none
.control-lockButton
topBarButtonDark()
.control-lockButton-tooltip
darkTooltip()
.control-trashButton
topBarButtonDark()

View File

@@ -38,7 +38,7 @@ $info-margin-under-border = 27px
margin 13px 2px
padding 0
border-radius 17px
&:hover .info-right-button-tooltip
&:hover .info-left-button-tooltip
opacity 1
&:focus
border-color $ui-favorite-star-button-color
@@ -54,21 +54,6 @@ $info-margin-under-border = 27px
bottom 1px
padding-left 30px
.info-right-button
width 34px
height 34px
border-radius 17px
font-size 14px
margin 13px 7px
padding 0
border none
color $ui-button-color
background-color transparent
&:hover
opacity 1
background-color $ui-button--hover-backgroundColor
body[data-theme="dark"]
.info
border-color $ui-dark-borderColor
@@ -88,11 +73,3 @@ body[data-theme="dark"]
.info-right
background-color $ui-dark-noteDetail-backgroundColor
.info-right-button
navDarkButtonColor()
border-color $ui-dark-borderColor
&:active
border-color $ui-dark-button--focus-borderColor
&:focus
border-color $ui-button--focus-borderColor

View File

@@ -259,6 +259,8 @@ class SnippetNoteDetail extends React.Component {
this.setState({
note: this.state.note,
snippetIndex
}, () => {
this.save()
})
}
@@ -545,10 +547,18 @@ class SnippetNoteDetail extends React.Component {
/>
</div>
<div styleName='info-right'>
<button styleName='info-right-button'
<button styleName='control-trashButton'
onClick={(e) => this.handleContextButtonClick(e)}
>
<i className='fa fa-ellipsis-v' />
<svg height="17px" id="Capa_1" style={{"enableBackground":"new 0 0 753.23 753.23"}} width="17px" version="1.1" viewBox="0 0 753.23 753.23" x="0px" y="0px" xmlSpace="preserve">
<g>
<g id="_x34__19_">
<g>
<path d="M494.308,659.077c12.993,0,23.538-10.546,23.538-23.539V353.077c0-12.993-10.545-23.539-23.538-23.539&#xA;&#x9;&#x9;&#x9;&#x9;s-23.538,10.545-23.538,23.539v282.461C470.77,648.531,481.314,659.077,494.308,659.077z M635.538,94.154h-141.23V47.077&#xA;&#x9;&#x9;&#x9;&#x9;C494.308,21.067,473.24,0,447.23,0H306c-26.01,0-47.077,21.067-47.077,47.077v47.077h-141.23&#xA;&#x9;&#x9;&#x9;&#x9;c-26.01,0-47.077,21.067-47.077,47.077v47.077c0,25.986,21.067,47.077,47.077,47.077v423.692&#xA;&#x9;&#x9;&#x9;&#x9;c0,51.996,42.157,94.153,94.154,94.153h329.539c51.996,0,94.153-42.157,94.153-94.153V235.385&#xA;&#x9;&#x9;&#x9;&#x9;c26.01,0,47.077-21.091,47.077-47.077V141.23C682.615,115.221,661.548,94.154,635.538,94.154z M306,70.615&#xA;&#x9;&#x9;&#x9;&#x9;c0-12.993,10.545-23.539,23.538-23.539h94.154c12.993,0,23.538,10.545,23.538,23.539v23.539c-22.809,0-141.23,0-141.23,0V70.615z&#xA;&#x9;&#x9;&#x9;&#x9; M588.461,659.077c0,25.986-21.066,47.076-47.076,47.076H211.846c-26.01,0-47.077-21.09-47.077-47.076V235.385h423.692V659.077z&#xA;&#x9;&#x9;&#x9;&#x9; M612,188.308H141.23c-12.993,0-23.538-10.545-23.538-23.539s10.545-23.539,23.538-23.539H612&#xA;&#x9;&#x9;&#x9;&#x9;c12.993,0,23.538,10.545,23.538,23.539S624.993,188.308,612,188.308z M258.923,659.077c12.993,0,23.539-10.546,23.539-23.539&#xA;&#x9;&#x9;&#x9;&#x9;V353.077c0-12.993-10.545-23.539-23.539-23.539s-23.539,10.545-23.539,23.539v282.461&#xA;&#x9;&#x9;&#x9;&#x9;C235.384,648.531,245.93,659.077,258.923,659.077z M376.615,659.077c12.993,0,23.538-10.546,23.538-23.539V353.077&#xA;&#x9;&#x9;&#x9;&#x9;c0-12.993-10.545-23.539-23.538-23.539s-23.539,10.545-23.539,23.539v282.461C353.077,648.531,363.622,659.077,376.615,659.077z"/>
</g>
</g>
</g>
</svg>
</button>
</div>
</div>

View File

@@ -68,6 +68,10 @@
&:active .update-icon
color white
.control-trashButton
float right
topBarButtonLight()
body[data-theme="dark"]
.root
border-color $ui-dark-borderColor
@@ -93,3 +97,6 @@ body[data-theme="dark"]
.override
button
border-color $ui-dark-borderColor
.control-trashButton
topBarButtonDark()

View File

@@ -38,10 +38,14 @@ class NoteList extends React.Component {
this.focusHandler = () => {
this.refs.list.focus()
}
this.alertIfSnippetHnalder = () => {
this.alertIfSnippetHandler = () => {
this.alertIfSnippet()
}
this.jumpToTopHandler = () => {
this.jumpToTop()
}
this.state = {
}
}
@@ -51,7 +55,9 @@ class NoteList extends React.Component {
ee.on('list:next', this.selectNextNoteHandler)
ee.on('list:prior', this.selectPriorNoteHandler)
ee.on('list:focus', this.focusHandler)
ee.on('list:isMarkdownNote', this.alertIfSnippetHnalder)
ee.on('list:isMarkdownNote', this.alertIfSnippetHandler)
ee.on('list:top', this.jumpToTopHandler)
ee.on('list:jumpToTop', this.jumpToTopHandler)
}
componentWillReceiveProps (nextProps) {
@@ -70,7 +76,9 @@ class NoteList extends React.Component {
ee.off('list:next', this.selectNextNoteHandler)
ee.off('list:prior', this.selectPriorNoteHandler)
ee.off('list:focus', this.focusHandler)
ee.off('list:isMarkdownNote', this.alertIfSnippetHnalder)
ee.off('list:isMarkdownNote', this.alertIfSnippetHandler)
ee.off('list:top', this.jumpToTopHandler)
ee.off('list:jumpToTop', this.jumpToTopHandler)
}
componentDidUpdate (prevProps) {
@@ -324,6 +332,23 @@ class NoteList extends React.Component {
}
}
jumpToTop() {
if (this.notes === null || this.notes.length === 0) {
return
}
let { router } = this.context
let { location } = this.props
const targetIndex = 0
router.push({
pathname: location.pathname,
query: {
key: this.notes[targetIndex].storage + '-' + this.notes[targetIndex].key
}
})
}
render () {
let { location, notes, config } = this.props
let sortFunc = config.sortBy === 'CREATED_AT'

View File

@@ -139,6 +139,24 @@ modal()
border-radius $modal-border-radius
box-shadow 2px 2px 10px gray
topBarButtonLight()
width 34px
height 34px
border-radius 17px
font-size 14px
margin 13px 7px
padding-top 7px
border none
color $ui-button-color
fill $ui-button-color
background-color transparent
&:active
border-color $ui-button--active-backgroundColor
&:hover
background-color $ui-button--hover-backgroundColor
.control-lockButton-tooltip
opacity 1
// Dark theme
$ui-dark-borderColor = lighten(#21252B, 20%)
$ui-dark-backgroundColor = #1D1D1D
@@ -151,6 +169,7 @@ $ui-dark-button--active-color = white
$ui-dark-button--active-backgroundColor = #6AA5E9
$ui-dark-button--hover-backgroundColor = lighten($ui-dark-backgroundColor, 10%)
$ui-dark-button--focus-borderColor = lighten(#369DCD, 25%)
$ui-dark-topbar-button-color = #939395
$dark-default-button-background = $ui-dark-backgroundColor
$dark-default-button-background--hover = $ui-dark-button--hover-backgroundColor
@@ -190,6 +209,18 @@ navDarkButtonColor()
background-color $ui-dark-button--active-backgroundColor
color $ui-dark-button--active-color
topBarButtonDark()
border-color $ui-dark-borderColor
color $ui-dark-topbar-button-color
&:hover
background-color $dark-default-button-background--hover
&:active
border-color $ui-dark-button--focus-borderColor
&:active:hover
background-color $ui-dark-button--active-backgroundColor
&:focus
border-color $ui-button--focus-borderColor
$ui-dark-tooltip-text-color = white
$ui-dark-tooltip-backgroundColor = alpha(#444, 70%)
$ui-dark-tooltip-button-backgroundColor = #D1D1D1