mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-15 02:36:36 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3758ea2cf4 | ||
|
|
e62fc11328 | ||
|
|
3cbfae83c1 | ||
|
|
57667654ef | ||
|
|
eadd66fa91 | ||
|
|
75cd94a39a | ||
|
|
7872bfe19d | ||
|
|
af008e69c2 | ||
|
|
a549abc20f | ||
|
|
116344737a | ||
|
|
93c03f4e88 | ||
|
|
445332c27c | ||
|
|
c42e1892d0 | ||
|
|
b6b526dd57 | ||
|
|
3ef7f19ffc | ||
|
|
9d0d851c2e |
@@ -21,6 +21,29 @@ export default class CodeEditor extends React.Component {
|
|||||||
|
|
||||||
this.configApplyHandler = (e, config) => this.handleConfigApply(e, config)
|
this.configApplyHandler = (e, config) => this.handleConfigApply(e, config)
|
||||||
this.changeHandler = e => this.handleChange(e)
|
this.changeHandler = e => this.handleChange(e)
|
||||||
|
this.blurHandler = (e) => {
|
||||||
|
if (e.relatedTarget === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let isFocusingToSearch = e.relatedTarget.className && e.relatedTarget.className.split(' ').some(clss => {
|
||||||
|
return clss === 'ace_search_field' || clss === 'ace_searchbtn' || clss === 'ace_replacebtn' || clss === 'ace_searchbtn_close' || clss === 'ace_text-input'
|
||||||
|
})
|
||||||
|
if (isFocusingToSearch) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.props.onBlur) this.props.onBlur(e)
|
||||||
|
}
|
||||||
|
this.afterExecHandler = (e) => {
|
||||||
|
switch (e.command.name) {
|
||||||
|
case 'find':
|
||||||
|
Array.prototype.forEach.call(ReactDOM.findDOMNode(this).querySelectorAll('.ace_search_field, .ace_searchbtn, .ace_replacebtn, .ace_searchbtn_close'), el => {
|
||||||
|
el.removeEventListener('blur', this.blurHandler)
|
||||||
|
el.addEventListener('blur', this.blurHandler)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
fontSize: config['editor-font-size'],
|
fontSize: config['editor-font-size'],
|
||||||
@@ -49,6 +72,8 @@ export default class CodeEditor extends React.Component {
|
|||||||
editor.setReadOnly(!!this.props.readOnly)
|
editor.setReadOnly(!!this.props.readOnly)
|
||||||
editor.setFontSize(this.state.fontSize)
|
editor.setFontSize(this.state.fontSize)
|
||||||
|
|
||||||
|
editor.on('blur', this.blurHandler)
|
||||||
|
|
||||||
editor.commands.addCommand({
|
editor.commands.addCommand({
|
||||||
name: 'Emacs cursor up',
|
name: 'Emacs cursor up',
|
||||||
bindKey: {mac: 'Ctrl-P'},
|
bindKey: {mac: 'Ctrl-P'},
|
||||||
@@ -67,9 +92,7 @@ export default class CodeEditor extends React.Component {
|
|||||||
readOnly: true
|
readOnly: true
|
||||||
})
|
})
|
||||||
|
|
||||||
editor.on('blur', () => {
|
editor.commands.on('afterExec', this.afterExecHandler)
|
||||||
if (this.props.onBlur) this.props.onBlur()
|
|
||||||
})
|
|
||||||
|
|
||||||
var session = editor.getSession()
|
var session = editor.getSession()
|
||||||
let mode = _.findWhere(modes, {name: article.mode})
|
let mode = _.findWhere(modes, {name: article.mode})
|
||||||
@@ -92,6 +115,8 @@ export default class CodeEditor extends React.Component {
|
|||||||
componentWillUnmount () {
|
componentWillUnmount () {
|
||||||
ipc.removeListener('config-apply', this.configApplyHandler)
|
ipc.removeListener('config-apply', this.configApplyHandler)
|
||||||
this.editor.getSession().removeListener('change', this.changeHandler)
|
this.editor.getSession().removeListener('change', this.changeHandler)
|
||||||
|
this.editor.removeListener('blur', this.blurHandler)
|
||||||
|
this.editor.commands.removeListener('afterExec', this.afterExecHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate (prevProps, prevState) {
|
componentDidUpdate (prevProps, prevState) {
|
||||||
@@ -166,8 +191,8 @@ CodeEditor.propTypes = {
|
|||||||
key: PropTypes.string
|
key: PropTypes.string
|
||||||
}),
|
}),
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
onChange: PropTypes.func,
|
|
||||||
onBlur: PropTypes.func,
|
onBlur: PropTypes.func,
|
||||||
|
onChange: PropTypes.func,
|
||||||
readOnly: PropTypes.bool
|
readOnly: PropTypes.bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,10 +11,12 @@ const ipc = electron.ipcRenderer
|
|||||||
|
|
||||||
const katex = window.katex
|
const katex = window.katex
|
||||||
|
|
||||||
|
const OSX = global.process.platform === 'darwin'
|
||||||
|
|
||||||
const sanitizeOpts = {
|
const sanitizeOpts = {
|
||||||
allowedTags: [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol',
|
allowedTags: [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol',
|
||||||
'nl', 'li', 'b', 'i', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div',
|
'nl', 'li', 'b', 'i', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div',
|
||||||
'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre', 'img', 'span', 'cite', 'del', 'u', 'sub', 'sup' ],
|
'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre', 'img', 'span', 'cite', 'del', 'u', 'sub', 'sup', 's', 'input', 'label' ],
|
||||||
allowedClasses: {
|
allowedClasses: {
|
||||||
'a': ['lineAnchor'],
|
'a': ['lineAnchor'],
|
||||||
'div': ['math'],
|
'div': ['math'],
|
||||||
@@ -24,14 +26,20 @@ const sanitizeOpts = {
|
|||||||
allowedAttributes: {
|
allowedAttributes: {
|
||||||
a: ['href', 'data-key'],
|
a: ['href', 'data-key'],
|
||||||
img: [ 'src' ],
|
img: [ 'src' ],
|
||||||
|
label: ['for'],
|
||||||
|
input: ['checked', 'type'],
|
||||||
'*': ['id', 'name']
|
'*': ['id', 'name']
|
||||||
},
|
},
|
||||||
transformTags: {
|
transformTags: {
|
||||||
'*': function (tagName, attribs) {
|
'*': function (tagName, attribs) {
|
||||||
let href = attribs.href
|
let href = attribs.href
|
||||||
|
if (tagName === 'input' && attribs.type !== 'checkbox') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if (_.isString(href) && href.match(/^#.+$/)) attribs.href = href.replace(/^#/, '#md-anchor-')
|
if (_.isString(href) && href.match(/^#.+$/)) attribs.href = href.replace(/^#/, '#md-anchor-')
|
||||||
if (attribs.id) attribs.id = 'md-anchor-' + attribs.id
|
if (attribs.id) attribs.id = 'md-anchor-' + attribs.id
|
||||||
if (attribs.name) attribs.name = 'md-anchor-' + attribs.name
|
if (attribs.name) attribs.name = 'md-anchor-' + attribs.name
|
||||||
|
if (attribs.for) attribs.for = 'md-anchor-' + attribs.for
|
||||||
return {
|
return {
|
||||||
tagName: tagName,
|
tagName: tagName,
|
||||||
attribs: attribs
|
attribs: attribs
|
||||||
@@ -46,7 +54,10 @@ function handleAnchorClick (e) {
|
|||||||
}
|
}
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
shell.openExternal(e.target.href)
|
let href = e.target.href
|
||||||
|
if (href.match(/^http:\/\/|https:\/\/|mailto:\/\//)) {
|
||||||
|
shell.openExternal(href)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopPropagation (e) {
|
function stopPropagation (e) {
|
||||||
@@ -57,7 +68,7 @@ function stopPropagation (e) {
|
|||||||
function math2Katex (display) {
|
function math2Katex (display) {
|
||||||
return function (el) {
|
return function (el) {
|
||||||
try {
|
try {
|
||||||
katex.render(el.innerHTML, el, {display: display})
|
katex.render(el.innerHTML.replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/&/g, '&'), el, {display: display})
|
||||||
el.className = 'math-rendered'
|
el.className = 'math-rendered'
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
el.innerHTML = e.message
|
el.innerHTML = e.message
|
||||||
@@ -111,22 +122,30 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
|
|
||||||
addListener () {
|
addListener () {
|
||||||
var anchors = ReactDOM.findDOMNode(this).querySelectorAll('a:not(.lineAnchor)')
|
var anchors = ReactDOM.findDOMNode(this).querySelectorAll('a:not(.lineAnchor)')
|
||||||
|
var inputs = ReactDOM.findDOMNode(this).querySelectorAll('input')
|
||||||
|
|
||||||
for (var i = 0; i < anchors.length; i++) {
|
Array.prototype.forEach.call(anchors, anchor => {
|
||||||
anchors[i].addEventListener('click', handleAnchorClick)
|
anchor.addEventListener('click', handleAnchorClick)
|
||||||
anchors[i].addEventListener('mousedown', stopPropagation)
|
anchor.addEventListener('mousedown', stopPropagation)
|
||||||
anchors[i].addEventListener('mouseup', stopPropagation)
|
anchor.addEventListener('mouseup', stopPropagation)
|
||||||
}
|
})
|
||||||
|
Array.prototype.forEach.call(inputs, input => {
|
||||||
|
input.addEventListener('click', stopPropagation)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
removeListener () {
|
removeListener () {
|
||||||
var anchors = ReactDOM.findDOMNode(this).querySelectorAll('a:not(.lineAnchor)')
|
var anchors = ReactDOM.findDOMNode(this).querySelectorAll('a:not(.lineAnchor)')
|
||||||
|
var inputs = ReactDOM.findDOMNode(this).querySelectorAll('input')
|
||||||
|
|
||||||
for (var i = 0; i < anchors.length; i++) {
|
Array.prototype.forEach.call(anchors, anchor => {
|
||||||
anchors[i].removeEventListener('click', handleAnchorClick)
|
anchor.removeEventListener('click', handleAnchorClick)
|
||||||
anchors[i].removeEventListener('mousedown', stopPropagation)
|
anchor.removeEventListener('mousedown', stopPropagation)
|
||||||
anchors[i].removeEventListener('mouseup', stopPropagation)
|
anchor.removeEventListener('mouseup', stopPropagation)
|
||||||
}
|
})
|
||||||
|
Array.prototype.forEach.call(inputs, input => {
|
||||||
|
input.removeEventListener('click', stopPropagation)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClick (e) {
|
handleClick (e) {
|
||||||
@@ -185,7 +204,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
dangerouslySetInnerHTML={{__html: ' ' + content}}
|
dangerouslySetInnerHTML={{__html: ' ' + content}}
|
||||||
style={{
|
style={{
|
||||||
fontSize: this.state.fontSize,
|
fontSize: this.state.fontSize,
|
||||||
fontFamily: this.state.fontFamily.trim() + ', helvetica, arial, sans-serif'
|
fontFamily: this.state.fontFamily.trim() + (OSX ? '' : ', meiryo, \'Microsoft YaHei\'') + ', helvetica, arial, sans-serif'
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,9 +11,17 @@ import _ from 'lodash'
|
|||||||
import dataStore from 'browser/lib/dataStore'
|
import dataStore from 'browser/lib/dataStore'
|
||||||
|
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
const { clipboard, ipcRenderer } = electron
|
const { clipboard, ipcRenderer, remote } = electron
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
window.addEventListener('keydown', function (e) {
|
||||||
|
if (e.keyCode === 73 && e.metaKey && e.altKey) {
|
||||||
|
remote.getCurrentWindow().toggleDevTools()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function hideFinder () {
|
function hideFinder () {
|
||||||
ipcRenderer.send('hide-finder')
|
ipcRenderer.send('hide-finder')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ Post all records(except today)
|
|||||||
and remove all posted records
|
and remove all posted records
|
||||||
*/
|
*/
|
||||||
export function postRecords (data) {
|
export function postRecords (data) {
|
||||||
if (process.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
console.log('post failed - NOT PRODUCTION ')
|
console.log('post failed - NOT PRODUCTION ')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ var md = markdownit({
|
|||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
md.use(emoji)
|
md.use(emoji, {
|
||||||
|
shortcuts: {}
|
||||||
|
})
|
||||||
md.use(math, {
|
md.use(math, {
|
||||||
inlineRenderer: function (str) {
|
inlineRenderer: function (str) {
|
||||||
return `<span class='math'>${str}</span>`
|
return `<span class='math'>${str}</span>`
|
||||||
@@ -26,6 +28,7 @@ md.use(math, {
|
|||||||
return `<div class='math'>${str}</div>`
|
return `<div class='math'>${str}</div>`
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
md.use(require('markdown-it-checkbox'))
|
||||||
|
|
||||||
let originalRenderToken = md.renderer.renderToken
|
let originalRenderToken = md.renderer.renderToken
|
||||||
md.renderer.renderToken = function renderToken (tokens, idx, options) {
|
md.renderer.renderToken = function renderToken (tokens, idx, options) {
|
||||||
|
|||||||
@@ -2,21 +2,44 @@ import React, { PropTypes } from 'react'
|
|||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import MarkdownPreview from 'browser/components/MarkdownPreview'
|
import MarkdownPreview from 'browser/components/MarkdownPreview'
|
||||||
import CodeEditor from 'browser/components/CodeEditor'
|
import CodeEditor from 'browser/components/CodeEditor'
|
||||||
|
import activityRecord from 'browser/lib/activityRecord'
|
||||||
|
import fetchConfig from 'browser/lib/fetchConfig'
|
||||||
|
|
||||||
|
const electron = require('electron')
|
||||||
|
const ipc = electron.ipcRenderer
|
||||||
|
|
||||||
export const PREVIEW_MODE = 'PREVIEW_MODE'
|
export const PREVIEW_MODE = 'PREVIEW_MODE'
|
||||||
export const EDIT_MODE = 'EDIT_MODE'
|
export const EDIT_MODE = 'EDIT_MODE'
|
||||||
|
|
||||||
|
let config = fetchConfig()
|
||||||
|
ipc.on('config-apply', function (e, newConfig) {
|
||||||
|
config = newConfig
|
||||||
|
})
|
||||||
|
|
||||||
export default class ArticleEditor extends React.Component {
|
export default class ArticleEditor extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
|
this.configApplyHandler = (e, config) => this.handleConfigApply(e, config)
|
||||||
this.isMouseDown = false
|
this.isMouseDown = false
|
||||||
this.state = {
|
this.state = {
|
||||||
status: PREVIEW_MODE,
|
status: PREVIEW_MODE,
|
||||||
cursorPosition: null,
|
cursorPosition: null,
|
||||||
firstVisibleRow: null
|
firstVisibleRow: null,
|
||||||
|
switchPreview: config['switch-preview'],
|
||||||
|
isTemporary: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount () {
|
||||||
|
console.log(this.state.switchPreview)
|
||||||
|
ipc.on('config-apply', this.configApplyHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount () {
|
||||||
|
ipc.removeListener('config-apply', this.configApplyHandler)
|
||||||
|
}
|
||||||
|
|
||||||
componentWillReceiveProps (nextProps) {
|
componentWillReceiveProps (nextProps) {
|
||||||
if (nextProps.article.key !== this.props.article.key) {
|
if (nextProps.article.key !== this.props.article.key) {
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -25,6 +48,12 @@ export default class ArticleEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleConfigApply (e, newConfig) {
|
||||||
|
this.setState({
|
||||||
|
switchPreview: newConfig['switch-preview']
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
resetCursorPosition () {
|
resetCursorPosition () {
|
||||||
this.setState({
|
this.setState({
|
||||||
cursorPosition: null,
|
cursorPosition: null,
|
||||||
@@ -35,13 +64,14 @@ export default class ArticleEditor extends React.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
switchPreviewMode () {
|
switchPreviewMode (isTemporary = false) {
|
||||||
let cursorPosition = this.refs.editor.getCursorPosition()
|
let cursorPosition = this.refs.editor.getCursorPosition()
|
||||||
let firstVisibleRow = this.refs.editor.getFirstVisibleRow()
|
let firstVisibleRow = this.refs.editor.getFirstVisibleRow()
|
||||||
this.setState({
|
this.setState({
|
||||||
status: PREVIEW_MODE,
|
status: PREVIEW_MODE,
|
||||||
cursorPosition,
|
cursorPosition,
|
||||||
firstVisibleRow
|
firstVisibleRow,
|
||||||
|
isTemporary: isTemporary
|
||||||
}, function () {
|
}, function () {
|
||||||
let previewEl = ReactDOM.findDOMNode(this.refs.preview)
|
let previewEl = ReactDOM.findDOMNode(this.refs.preview)
|
||||||
let anchors = previewEl.querySelectorAll('.lineAnchor')
|
let anchors = previewEl.querySelectorAll('.lineAnchor')
|
||||||
@@ -55,43 +85,27 @@ export default class ArticleEditor extends React.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
switchEditMode () {
|
switchEditMode (isTemporary = false) {
|
||||||
this.setState({
|
this.setState({
|
||||||
status: EDIT_MODE
|
status: EDIT_MODE,
|
||||||
|
isTemporary: false
|
||||||
}, function () {
|
}, function () {
|
||||||
if (this.state.cursorPosition != null) {
|
if (this.state.cursorPosition != null) {
|
||||||
this.refs.editor.moveCursorTo(this.state.cursorPosition.row, this.state.cursorPosition.column)
|
this.refs.editor.moveCursorTo(this.state.cursorPosition.row, this.state.cursorPosition.column)
|
||||||
this.refs.editor.scrollToLine(this.state.firstVisibleRow)
|
this.refs.editor.scrollToLine(this.state.firstVisibleRow)
|
||||||
}
|
}
|
||||||
this.refs.editor.editor.focus()
|
this.refs.editor.editor.focus()
|
||||||
|
|
||||||
|
if (!isTemporary) activityRecord.emit('ARTICLE_UPDATE', this.props.article)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePreviewMouseDown (e) {
|
handleBlurCodeEditor (e) {
|
||||||
if (e.button === 2) return true
|
let isFocusingToThis = e.relatedTarget === ReactDOM.findDOMNode(this)
|
||||||
this.isDrag = false
|
if (isFocusingToThis || this.state.switchPreview !== 'blur') {
|
||||||
this.isMouseDown = true
|
return
|
||||||
this.moveCount = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
handlePreviewMouseMove () {
|
|
||||||
if (this.isMouseDown) {
|
|
||||||
this.moveCount++
|
|
||||||
if (this.moveCount > 5) {
|
|
||||||
this.isDrag = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
handlePreviewMouseUp () {
|
|
||||||
this.isMouseDown = false
|
|
||||||
this.moveCount = 0
|
|
||||||
if (!this.isDrag) {
|
|
||||||
this.switchEditMode()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleBlurCodeEditor () {
|
|
||||||
let { article } = this.props
|
let { article } = this.props
|
||||||
if (article.mode === 'markdown') {
|
if (article.mode === 'markdown') {
|
||||||
this.switchPreviewMode()
|
this.switchPreviewMode()
|
||||||
@@ -102,36 +116,97 @@ export default class ArticleEditor extends React.Component {
|
|||||||
this.props.onChange(value)
|
this.props.onChange(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleRightClick (e) {
|
||||||
|
let { article } = this.props
|
||||||
|
if (this.state.switchPreview === 'rightclick' && article.mode === 'markdown') {
|
||||||
|
if (this.state.status === EDIT_MODE) this.switchPreviewMode()
|
||||||
|
else this.switchEditMode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMouseUp (e) {
|
||||||
|
switch (this.state.switchPreview) {
|
||||||
|
case 'blur':
|
||||||
|
switch (e.button) {
|
||||||
|
case 0:
|
||||||
|
this.isMouseDown = false
|
||||||
|
this.moveCount = 0
|
||||||
|
if (!this.isDrag) {
|
||||||
|
this.switchEditMode()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
if (this.state.isTemporary) this.switchEditMode(true)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'rightclick':
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMouseMove (e) {
|
||||||
|
if (this.state.switchPreview === 'blur' && this.isMouseDown) {
|
||||||
|
this.moveCount++
|
||||||
|
if (this.moveCount > 5) {
|
||||||
|
this.isDrag = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMouseDowm (e) {
|
||||||
|
switch (this.state.switchPreview) {
|
||||||
|
case 'blur':
|
||||||
|
switch (e.button) {
|
||||||
|
case 0:
|
||||||
|
this.isDrag = false
|
||||||
|
this.isMouseDown = true
|
||||||
|
this.moveCount = 0
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
if (this.state.status === EDIT_MODE && this.props.article.mode === 'markdown') {
|
||||||
|
this.switchPreviewMode(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'rightclick':
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { article } = this.props
|
let { article } = this.props
|
||||||
let showPreview = article.mode === 'markdown' && this.state.status === PREVIEW_MODE
|
let showPreview = article.mode === 'markdown' && this.state.status === PREVIEW_MODE
|
||||||
if (showPreview) {
|
|
||||||
return (
|
|
||||||
<div className='ArticleEditor'>
|
|
||||||
<MarkdownPreview
|
|
||||||
ref='preview'
|
|
||||||
onMouseUp={e => this.handlePreviewMouseUp(e)}
|
|
||||||
onMouseDown={e => this.handlePreviewMouseDown(e)}
|
|
||||||
onMouseMove={e => this.handlePreviewMouseMove(e)}
|
|
||||||
content={article.content}
|
|
||||||
/>
|
|
||||||
<div className='ArticleDetail-panel-content-tooltip'>Click to Edit</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='ArticleEditor'>
|
<div
|
||||||
<CodeEditor
|
tabIndex='5'
|
||||||
ref='editor'
|
onContextMenu={e => this.handleRightClick(e)}
|
||||||
onBlur={e => this.handleBlurCodeEditor(e)}
|
onMouseUp={e => this.handleMouseUp(e)}
|
||||||
onChange={value => this.handleCodeEditorChange(value)}
|
onMouseMove={e => this.handleMouseMove(e)}
|
||||||
article={article}
|
onMouseDown={e => this.handleMouseDowm(e)}
|
||||||
/>
|
className='ArticleEditor'
|
||||||
|
>
|
||||||
|
{showPreview
|
||||||
|
? <MarkdownPreview
|
||||||
|
ref='preview'
|
||||||
|
content={article.content}
|
||||||
|
/>
|
||||||
|
: <CodeEditor
|
||||||
|
ref='editor'
|
||||||
|
onBlur={e => this.handleBlurCodeEditor(e)}
|
||||||
|
onChange={value => this.handleCodeEditorChange(value)}
|
||||||
|
article={article}
|
||||||
|
/>
|
||||||
|
}
|
||||||
{article.mode === 'markdown'
|
{article.mode === 'markdown'
|
||||||
? (
|
? <div className='ArticleDetail-panel-content-tooltip' children={
|
||||||
<div className='ArticleDetail-panel-content-tooltip'>Press ESC to watch Preview</div>
|
showPreview
|
||||||
)
|
? this.state.switchPreview === 'blur'
|
||||||
|
? 'Click to Edit'
|
||||||
|
: 'Right Click to Edit'
|
||||||
|
: this.state.switchPreview === 'blur'
|
||||||
|
? 'Press ESC to Watch Preview'
|
||||||
|
: 'Right Click to Watch Preview'
|
||||||
|
}
|
||||||
|
/>
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@@ -145,5 +220,6 @@ ArticleEditor.propTypes = {
|
|||||||
key: PropTypes.string,
|
key: PropTypes.string,
|
||||||
mode: PropTypes.string
|
mode: PropTypes.string
|
||||||
}),
|
}),
|
||||||
onChange: PropTypes.func
|
onChange: PropTypes.func,
|
||||||
|
parent: PropTypes.object
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ export default class ArticleDetail extends React.Component {
|
|||||||
|
|
||||||
dispatch(updateArticle(article))
|
dispatch(updateArticle(article))
|
||||||
|
|
||||||
let targetFolderKey = this.state.article.FolderKey
|
let targetFolderKey = e.target.value
|
||||||
if (status.targetFolders.length > 0) {
|
if (status.targetFolders.length > 0) {
|
||||||
let targetFolder = _.findWhere(folders, {key: targetFolderKey})
|
let targetFolder = _.findWhere(folders, {key: targetFolderKey})
|
||||||
dispatch(switchFolder(targetFolder.name))
|
dispatch(switchFolder(targetFolder.name))
|
||||||
|
|||||||
@@ -10,6 +10,15 @@ import activityRecord from 'browser/lib/activityRecord'
|
|||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
const ipc = electron.ipcRenderer
|
const ipc = electron.ipcRenderer
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
const remote = electron.remote
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
window.addEventListener('keydown', function (e) {
|
||||||
|
if (e.keyCode === 73 && e.metaKey && e.altKey) {
|
||||||
|
remote.getCurrentWindow().toggleDevTools()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
activityRecord.init()
|
activityRecord.init()
|
||||||
window.addEventListener('online', function () {
|
window.addEventListener('online', function () {
|
||||||
|
|||||||
@@ -138,9 +138,9 @@ export default class AppSettingTab extends React.Component {
|
|||||||
<label>Editor Font Family</label>
|
<label>Editor Font Family</label>
|
||||||
<input valueLink={this.linkState('config.editor-font-family')} onKeyDown={e => this.handleConfigKeyDown(e)} type='text'/>
|
<input valueLink={this.linkState('config.editor-font-family')} onKeyDown={e => this.handleConfigKeyDown(e)} type='text'/>
|
||||||
</div>
|
</div>
|
||||||
<div className='sectionSelect'>
|
<div className='sectionMultiSelect'>
|
||||||
<label>Editor Indent Style</label>
|
<label>Editor Indent Style</label>
|
||||||
<div className='sectionSelect-input'>
|
<div className='sectionMultiSelect-input'>
|
||||||
type
|
type
|
||||||
<select valueLink={this.linkState('config.editor-indent-type')}>
|
<select valueLink={this.linkState('config.editor-indent-type')}>
|
||||||
<option value='space'>Space</option>
|
<option value='space'>Space</option>
|
||||||
@@ -162,8 +162,15 @@ export default class AppSettingTab extends React.Component {
|
|||||||
<label>Preview Font Family</label>
|
<label>Preview Font Family</label>
|
||||||
<input valueLink={this.linkState('config.preview-font-family')} onKeyDown={e => this.handleConfigKeyDown(e)} type='text'/>
|
<input valueLink={this.linkState('config.preview-font-family')} onKeyDown={e => this.handleConfigKeyDown(e)} type='text'/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className='sectionSelect'>
|
||||||
|
<label>Switching Preview</label>
|
||||||
|
<select valueLink={this.linkState('config.switch-preview')}>
|
||||||
|
<option value='blur'>When Editor Blurred</option>
|
||||||
|
<option value='rightclick'>When Right Clicking</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
{
|
{
|
||||||
true// !OSX
|
global.process.platform === 'win32'
|
||||||
? (
|
? (
|
||||||
<div className='sectionCheck'>
|
<div className='sectionCheck'>
|
||||||
<label><input onClick={e => this.handleDisableDirectWriteClick(e)} checked={this.state.config['disable-direct-write']} disabled={OSX} type='checkbox'/>Disable Direct Write<span className='sectionCheck-warn'>It will be applied after restarting</span></label>
|
<label><input onClick={e => this.handleDisableDirectWriteClick(e)} checked={this.state.config['disable-direct-write']} disabled={OSX} type='checkbox'/>Disable Direct Write<span className='sectionCheck-warn'>It will be applied after restarting</span></label>
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ iptFocusBorderColor = #369DCD
|
|||||||
left 180px
|
left 180px
|
||||||
overflow-y auto
|
overflow-y auto
|
||||||
&>.section
|
&>.section
|
||||||
padding 10px
|
padding 10px 20px
|
||||||
border-bottom 1px solid borderColor
|
border-bottom 1px solid borderColor
|
||||||
overflow-y auto
|
overflow-y auto
|
||||||
&:nth-last-child(1)
|
&:nth-last-child(1)
|
||||||
@@ -102,7 +102,6 @@ iptFocusBorderColor = #369DCD
|
|||||||
&:focus
|
&:focus
|
||||||
border-color iptFocusBorderColor
|
border-color iptFocusBorderColor
|
||||||
&>.sectionSelect
|
&>.sectionSelect
|
||||||
|
|
||||||
margin-bottom 5px
|
margin-bottom 5px
|
||||||
clearfix()
|
clearfix()
|
||||||
height 33px
|
height 33px
|
||||||
@@ -111,7 +110,28 @@ iptFocusBorderColor = #369DCD
|
|||||||
padding-left 15px
|
padding-left 15px
|
||||||
float left
|
float left
|
||||||
line-height 33px
|
line-height 33px
|
||||||
.sectionSelect-input
|
select
|
||||||
|
float left
|
||||||
|
width 200px
|
||||||
|
height 25px
|
||||||
|
margin-top 4px
|
||||||
|
border-radius 5px
|
||||||
|
border 1px solid borderColor
|
||||||
|
padding 0 10px
|
||||||
|
font-size 14px
|
||||||
|
outline none
|
||||||
|
&:focus
|
||||||
|
border-color iptFocusBorderColor
|
||||||
|
&>.sectionMultiSelect
|
||||||
|
margin-bottom 5px
|
||||||
|
clearfix()
|
||||||
|
height 33px
|
||||||
|
label
|
||||||
|
width 150px
|
||||||
|
padding-left 15px
|
||||||
|
float left
|
||||||
|
line-height 33px
|
||||||
|
.sectionMultiSelect-input
|
||||||
float left
|
float left
|
||||||
select
|
select
|
||||||
width 80px
|
width 80px
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ marked()
|
|||||||
font-weight bold
|
font-weight bold
|
||||||
em, i
|
em, i
|
||||||
font-style italic
|
font-style italic
|
||||||
s
|
s, del, strike
|
||||||
text-decoration line-through
|
text-decoration line-through
|
||||||
u
|
u
|
||||||
text-decoration underline
|
text-decoration underline
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ const defaultConfig = {
|
|||||||
'editor-indent-size': '4',
|
'editor-indent-size': '4',
|
||||||
'preview-font-size': '14',
|
'preview-font-size': '14',
|
||||||
'preview-font-family': 'Lato',
|
'preview-font-family': 'Lato',
|
||||||
|
'switch-preview': 'blur',
|
||||||
'disable-direct-write': false
|
'disable-direct-write': false
|
||||||
}
|
}
|
||||||
const configFile = 'config.json'
|
const configFile = 'config.json'
|
||||||
|
|||||||
@@ -75,16 +75,6 @@ var view = {
|
|||||||
click: function () {
|
click: function () {
|
||||||
BrowserWindow.getFocusedWindow().reload()
|
BrowserWindow.getFocusedWindow().reload()
|
||||||
}
|
}
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: 'Toggle Developer Tools',
|
|
||||||
// accelerator: (function () {
|
|
||||||
// if (process.platform === 'darwin') return 'Alt+Command+I'
|
|
||||||
// else return 'Ctrl+Shift+I'
|
|
||||||
// })(),
|
|
||||||
// click: function (item, focusedWindow) {
|
|
||||||
// if (focusedWindow) BrowserWindow.getFocusedWindow().toggleDevTools()
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ const nodeIpc = require('@rokt33r/node-ipc')
|
|||||||
const OSX = global.process.platform === 'darwin'
|
const OSX = global.process.platform === 'darwin'
|
||||||
|
|
||||||
const defaultKeymap = {
|
const defaultKeymap = {
|
||||||
toggleFinder: OSX ? 'Cmd + alt + s' : 'Super + alt + s',
|
toggleFinder: OSX ? 'Cmd + Alt + S' : 'Super + Alt + S',
|
||||||
toggleMain: OSX ? 'Cmd + alt + v' : 'Super + alt + v'
|
toggleMain: OSX ? 'Cmd + Alt + L' : 'Super + Alt + E'
|
||||||
}
|
}
|
||||||
const keymapFilename = 'keymap.json'
|
const keymapFilename = 'keymap.json'
|
||||||
|
|
||||||
|
|||||||
@@ -149,16 +149,6 @@ var view = {
|
|||||||
click: function () {
|
click: function () {
|
||||||
BrowserWindow.getFocusedWindow().reload()
|
BrowserWindow.getFocusedWindow().reload()
|
||||||
}
|
}
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: 'Toggle Developer Tools',
|
|
||||||
// accelerator: (function () {
|
|
||||||
// if (process.platform === 'darwin') return 'Alt+Command+I'
|
|
||||||
// else return 'Ctrl+Shift+I'
|
|
||||||
// })(),
|
|
||||||
// click: function (item, focusedWindow) {
|
|
||||||
// if (focusedWindow) BrowserWindow.getFocusedWindow().toggleDevTools()
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "boost",
|
"name": "boost",
|
||||||
"version": "0.5.1",
|
"version": "0.5.2",
|
||||||
"description": "Boostnote",
|
"description": "Boostnote",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -39,6 +39,7 @@
|
|||||||
"highlight.js": "^8.9.1",
|
"highlight.js": "^8.9.1",
|
||||||
"lodash": "^3.10.1",
|
"lodash": "^3.10.1",
|
||||||
"markdown-it": "^4.4.0",
|
"markdown-it": "^4.4.0",
|
||||||
|
"markdown-it-checkbox": "^1.1.0",
|
||||||
"markdown-it-emoji": "^1.1.0",
|
"markdown-it-emoji": "^1.1.0",
|
||||||
"markdown-it-math": "^3.0.2",
|
"markdown-it-math": "^3.0.2",
|
||||||
"md5": "^2.0.0",
|
"md5": "^2.0.0",
|
||||||
@@ -72,7 +73,7 @@
|
|||||||
"webpack": "^1.12.2",
|
"webpack": "^1.12.2",
|
||||||
"webpack-dev-server": "^1.12.0"
|
"webpack-dev-server": "^1.12.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {},
|
"optional": false,
|
||||||
"standard": {
|
"standard": {
|
||||||
"ignore": [],
|
"ignore": [],
|
||||||
"globals": [
|
"globals": [
|
||||||
|
|||||||
@@ -32,7 +32,8 @@ var config = {
|
|||||||
'markdown-it-emoji',
|
'markdown-it-emoji',
|
||||||
'fs-jetpack',
|
'fs-jetpack',
|
||||||
'markdown-it-math',
|
'markdown-it-math',
|
||||||
'@rokt33r/sanitize-html'
|
'@rokt33r/sanitize-html',
|
||||||
|
'markdown-it-checkbox'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
const skeleton = require('./webpack-skeleton')
|
const skeleton = require('./webpack-skeleton')
|
||||||
const webpack = require('webpack')
|
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
||||||
var config = Object.assign({}, skeleton, {
|
var config = Object.assign({}, skeleton, {
|
||||||
|
|||||||
Reference in New Issue
Block a user