1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-15 18:56:22 +00:00

Merge pull request #1307 from BoostIO/split-markdown

Split markdown
This commit is contained in:
Kazz Yokomizo
2017-12-20 18:20:49 +09:00
committed by GitHub
15 changed files with 257 additions and 70 deletions

View File

@@ -144,10 +144,12 @@ export default class MarkdownPreview extends React.Component {
}
handleContextMenu (e) {
if (!this.props.onContextMenu) return
this.props.onContextMenu(e)
}
handleMouseDown (e) {
if (!this.props.onMouseDown) return
if (e.target != null) {
switch (e.target.tagName) {
case 'A':
@@ -159,6 +161,7 @@ export default class MarkdownPreview extends React.Component {
}
handleMouseUp (e) {
if (!this.props.onMouseUp) return
if (e.target != null && e.target.tagName === 'A') {
return null
}

View File

@@ -0,0 +1,87 @@
import React from 'react'
import CodeEditor from 'browser/components/CodeEditor'
import MarkdownPreview from 'browser/components/MarkdownPreview'
import { findStorage } from 'browser/lib/findStorage'
import styles from './MarkdownSplitEditor.styl'
import CSSModules from 'browser/lib/CSSModules'
class MarkdownSplitEditor extends React.Component {
constructor (props) {
super(props)
this.value = props.value
this.focus = () => this.refs.code.focus()
this.reload = () => this.refs.code.reload()
}
handleOnChange () {
this.value = this.refs.code.value
this.props.onChange()
}
handleCheckboxClick (e) {
e.preventDefault()
e.stopPropagation()
const idMatch = /checkbox-([0-9]+)/
const checkedMatch = /\[x\]/i
const uncheckedMatch = /\[ \]/
if (idMatch.test(e.target.getAttribute('id'))) {
const lineIndex = parseInt(e.target.getAttribute('id').match(idMatch)[1], 10) - 1
const lines = this.refs.code.value
.split('\n')
const targetLine = lines[lineIndex]
if (targetLine.match(checkedMatch)) {
lines[lineIndex] = targetLine.replace(checkedMatch, '[ ]')
}
if (targetLine.match(uncheckedMatch)) {
lines[lineIndex] = targetLine.replace(uncheckedMatch, '[x]')
}
this.refs.code.setValue(lines.join('\n'))
}
}
render () {
const { config, value, storageKey } = this.props
const storage = findStorage(storageKey)
const previewStyle = {}
if (this.props.ignorePreviewPointerEvents) previewStyle.pointerEvents = 'none'
return (
<div styleName='root'>
<CodeEditor
styleName='codeEditor'
ref='code'
mode='GitHub Flavored Markdown'
value={value}
theme={config.editor.theme}
keyMap={config.editor.keyMap}
fontFamily={config.editor.fontFamily}
indentType={config.editor.indentType}
scrollPastEnd={config.editor.scrollPastEnd}
storageKey={storageKey}
onChange={this.handleOnChange.bind(this)}
/>
<MarkdownPreview
style={previewStyle}
styleName='preview'
theme={config.ui.theme}
keyMap={config.editor.keyMap}
fontSize={config.preview.fontSize}
fontFamily={config.preview.fontFamily}
codeBlockTheme={config.preview.codeBlockTheme}
codeBlockFontFamily={config.editor.fontFamily}
lineNumber={config.preview.lineNumber}
ref='preview'
tabInde='0'
value={value}
onCheckboxClick={(e) => this.handleCheckboxClick(e)}
showCopyNotification={config.ui.showCopyNotification}
storagePath={storage.path}
/>
</div>
)
}
}
export default CSSModules(MarkdownSplitEditor, styles)

View File

@@ -0,0 +1,9 @@
.root
width 100%
height 100%
font-size 30px
display flex
.codeEditor
width 50%
.preview
width 50%

View File

@@ -120,6 +120,7 @@ hr
margin 15px 0
h1, h2, h3, h4, h5, h6
font-weight bold
word-wrap break-word
h1
font-size 2.55em
padding-bottom 0.3em
@@ -157,6 +158,7 @@ p
line-height 1.6em
margin 0 0 1em
white-space pre-line
word-wrap break-word
img
max-width 100%
strong, b
@@ -338,4 +340,4 @@ body[data-theme="dark"]
body[data-theme="solarized-dark"]
color $ui-solarized-dark-text-color
border-color themeDarkBorder
background-color $ui-solarized-dark-noteDetail-backgroundColor
background-color $ui-solarized-dark-noteDetail-backgroundColor

View File

@@ -3,6 +3,7 @@ import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './MarkdownNoteDetail.styl'
import MarkdownEditor from 'browser/components/MarkdownEditor'
import MarkdownSplitEditor from 'browser/components/MarkdownSplitEditor'
import TodoListPercentage from 'browser/components/TodoListPercentage'
import StarButton from './StarButton'
import TagSelect from './TagSelect'
@@ -15,6 +16,7 @@ import StatusBar from '../StatusBar'
import _ from 'lodash'
import { findNoteTitle } from 'browser/lib/findNoteTitle'
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
import ConfigManager from 'browser/main/lib/ConfigManager'
import TrashButton from './TrashButton'
import PermanentDeleteButton from './PermanentDeleteButton'
import InfoButton from './InfoButton'
@@ -39,7 +41,8 @@ class MarkdownNoteDetail extends React.Component {
content: ''
}, props.note),
isLockButtonShown: false,
isLocked: false
isLocked: false,
editorType: props.config.editor.type
}
this.dispatchTimer = null
@@ -233,7 +236,7 @@ class MarkdownNoteDetail extends React.Component {
}
getToggleLockButton () {
return this.state.isLocked ? '../resources/icon/icon-edit-lock.svg' : '../resources/icon/icon-edit.svg'
return this.state.isLocked ? '../resources/icon/icon-previewoff-on.svg' : '../resources/icon/icon-previewoff-off.svg'
}
handleDeleteKeyDown (e) {
@@ -262,9 +265,42 @@ class MarkdownNoteDetail extends React.Component {
ee.emit('print')
}
render () {
const { data, config, location } = this.props
handleSwitchMode (type) {
this.setState({ editorType: type }, () => {
const newConfig = Object.assign({}, this.props.config)
newConfig.editor.type = type
ConfigManager.set(newConfig)
})
}
renderEditor () {
const { config, ignorePreviewPointerEvents } = this.props
const { note } = this.state
if (this.state.editorType === 'EDITOR_PREVIEW') {
return <MarkdownEditor
ref='content'
styleName='body-noteEditor'
config={config}
value={note.content}
storageKey={note.storage}
onChange={(e) => this.handleChange(e)}
ignorePreviewPointerEvents={ignorePreviewPointerEvents}
/>
} else {
return <MarkdownSplitEditor
ref='content'
config={config}
value={note.content}
storageKey={note.storage}
onChange={(e) => this.handleChange(e)}
ignorePreviewPointerEvents={ignorePreviewPointerEvents}
/>
}
}
render () {
const { data, location } = this.props
const { note, editorType } = this.state
const storageKey = note.storage
const folderKey = note.folder
@@ -320,11 +356,11 @@ class MarkdownNoteDetail extends React.Component {
/>
<div styleName='mode-tab'>
<div styleName='active'>
<img styleName='item-star' src='../resources/icon/icon-WYSIWYG-on.svg' />
<div styleName={editorType === 'SPLIT' ? 'active' : 'non-active'} onClick={() => this.handleSwitchMode('SPLIT')}>
<img styleName='item-star' src='../resources/icon/icon-mode-split-on.svg' />
</div>
<div>
<img styleName='item-star' src='../resources/icon/icon-code-off.svg' />
<div styleName={editorType === 'EDITOR_PREVIEW' ? 'active' : 'non-active'} onClick={() => this.handleSwitchMode('EDITOR_PREVIEW')}>
<img styleName='item-star' src='../resources/icon/icon-mode-markdown-off.svg' />
</div>
</div>
@@ -360,7 +396,7 @@ class MarkdownNoteDetail extends React.Component {
<button styleName='control-fullScreenButton'
onMouseDown={(e) => this.handleFullScreenButton(e)}
>
<img styleName='iconInfo' src='../resources/icon/icon-sidebar.svg' />
<img styleName='iconInfo' src='../resources/icon/icon-full.svg' />
</button>
<TrashButton onClick={(e) => this.handleTrashButtonClick(e)} />
@@ -390,15 +426,7 @@ class MarkdownNoteDetail extends React.Component {
{location.pathname === '/trashed' ? trashTopBar : detailTopBar}
<div styleName='body'>
<MarkdownEditor
ref='content'
styleName='body-noteEditor'
config={config}
value={this.state.note.content}
storageKey={this.state.note.storage}
onChange={(e) => this.handleChange(e)}
ignorePreviewPointerEvents={this.props.ignorePreviewPointerEvents}
/>
{this.renderEditor()}
</div>
<StatusBar

View File

@@ -48,8 +48,6 @@
cursor pointer
&:first-child
border-right 1px solid #eee
img
transform scale(0.7)
.active
background-color #fff
box-shadow 2px 0px 7px #eee

View File

@@ -35,7 +35,8 @@ export const DEFAULT_CONFIG = {
indentType: 'space',
indentSize: '2',
switchPreview: 'BLUR', // Available value: RIGHTCLICK, BLUR
scrollPastEnd: false
scrollPastEnd: false,
type: 'SPLIT'
},
preview: {
fontSize: '14',

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 47.1 (45422) - http://www.bohemiancoding.com/sketch -->
<title>icon-WYSIWYG-off</title>
<desc>Created with Sketch.</desc>
<defs>
<filter x="0.0%" y="0.0%" width="100.0%" height="100.0%" filterUnits="objectBoundingBox" id="filter-1">
<feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0" type="matrix" in="shadowOffsetOuter1" result="shadowMatrixOuter1"></feColorMatrix>
<feMerge>
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
<feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>
</filter>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="Artboard-4" transform="translate(-1378.000000, -372.000000)" stroke="#1EC38B" stroke-width="1.43999988">
<g id="Group" filter="url(#filter-1)" transform="translate(1336.000000, 363.000000)">
<g id="icon-WYSIWYG-off" transform="translate(43.000000, 9.714286)">
<path d="M12.768,7.79918367 C14.4091141,6.17242331 14.4091141,3.53492363 12.768,1.90816327 C11.1268859,0.281402899 8.46611413,0.281402899 6.825,1.90816327 L2.1,6.59183673 L2.1,12.4897959 L8.05,12.4897959 L12.768,7.79918367 Z" id="Shape"></path>
<path d="M9.8,4.85714286 L0,14.5714286" id="Shape"></path>
<path d="M10.5,9.71428571 L4.9,9.71428571" id="Shape"></path>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 47.1 (45422) - http://www.bohemiancoding.com/sketch -->
<title>icon-WYSIWYG-on</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="Artboard-4" transform="translate(-1254.000000, -293.000000)" stroke="#1EC38B" stroke-width="2">
<g id="icon-WYSIWYG-on" transform="translate(1255.000000, 293.000000)">
<path d="M18.24,11.24 C20.5844488,8.89555124 20.5844488,5.09444876 18.24,2.75 C15.8955512,0.405551237 12.0944488,0.405551237 9.75,2.75 L3,9.5 L3,18 L11.5,18 L18.24,11.24 Z" id="Shape"></path>
<path d="M14,7 L0,21" id="Shape"></path>
<path d="M15,14 L7,14" id="Shape"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -3,11 +3,22 @@
<!-- Generator: Sketch 48.1 (47250) - http://www.bohemiancoding.com/sketch -->
<title>icon-edit</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Artboard" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(-1464.000000, -336.000000)" stroke-linecap="round" stroke-linejoin="round">
<g id="icon-edit" transform="translate(1465.000000, 337.000000)" stroke="#C7C7C7" stroke-width="1.66666667">
<polygon id="Shape" points="9.16666667 0 12.5 3.42857143 3.33333333 12.8571429 0 12.8571429 0 9.42857143"></polygon>
<path d="M0,17.1428571 L15,17.1428571" id="Shape"></path>
<defs>
<filter x="0.0%" y="0.0%" width="100.0%" height="100.0%" filterUnits="objectBoundingBox" id="filter-1">
<feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0" type="matrix" in="shadowOffsetOuter1" result="shadowMatrixOuter1"></feColorMatrix>
<feMerge>
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
<feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>
</filter>
</defs>
<g id="Artboard-4" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(-1478.000000, -370.000000)" stroke-linecap="round" stroke-linejoin="round">
<g id="Group" filter="url(#filter-1)" transform="translate(1336.000000, 363.000000)" stroke="#C7C7C7" stroke-width="1.66666667">
<g id="icon-edit" transform="translate(143.000000, 8.000000)">
<polygon id="Shape" points="9.16666667 0 12.5 3.42857143 3.33333333 12.8571429 0 12.8571429 0 9.42857143"></polygon>
<path d="M0,17.1428571 L15,17.1428571" id="Shape"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 877 B

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.1 (47250) - http://www.bohemiancoding.com/sketch -->
<title>icon-full</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Artboard" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(-1421.000000, -219.000000)" stroke-linecap="round" stroke-linejoin="round">
<g id="icon-full" transform="translate(1422.000000, 220.000000)" stroke="#C7C7C7" stroke-width="1.33333333">
<polyline id="Shape" points="8 0 12 0 12 4"></polyline>
<polyline id="Shape" points="4 12 0 12 0 8"></polyline>
<path d="M12,0 L7.33333333,4.66666667" id="Shape"></path>
<path d="M0,12 L4.66666667,7.33333333" id="Shape"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 954 B

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.1 (47250) - http://www.bohemiancoding.com/sketch -->
<title>icon-mode-markdown-off</title>
<desc>Created with Sketch.</desc>
<defs>
<filter x="0.0%" y="0.0%" width="100.0%" height="100.0%" filterUnits="objectBoundingBox" id="filter-1">
<feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0" type="matrix" in="shadowOffsetOuter1" result="shadowMatrixOuter1"></feColorMatrix>
<feMerge>
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
<feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>
</filter>
</defs>
<g id="Artboard-4" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(-1478.000000, -372.000000)" stroke-linecap="round" stroke-linejoin="round">
<g id="Group" filter="url(#filter-1)" transform="translate(1336.000000, 363.000000)" stroke="#C7C7C7" stroke-width="1.55555556">
<g id="icon-mode-markdown-off" transform="translate(143.000000, 10.000000)">
<polygon id="Shape" points="10.1111111 0 14 3.88888889 3.88888889 14 0 14 0 10.1111111"></polygon>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.1 (47250) - http://www.bohemiancoding.com/sketch -->
<title>icon-mode-split-on</title>
<desc>Created with Sketch.</desc>
<defs>
<filter x="0.0%" y="0.0%" width="100.0%" height="100.0%" filterUnits="objectBoundingBox" id="filter-1">
<feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0" type="matrix" in="shadowOffsetOuter1" result="shadowMatrixOuter1"></feColorMatrix>
<feMerge>
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
<feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>
</filter>
</defs>
<g id="Artboard-4" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(-1378.000000, -372.000000)">
<g id="Group" filter="url(#filter-1)" transform="translate(1336.000000, 363.000000)">
<g id="icon-mode-split-on" transform="translate(40.000000, 7.000000)">
<rect id="Rectangle-7" fill="#D8D8D8" opacity="0" x="0" y="0" width="20" height="20"></rect>
<g id="sidebar" transform="translate(3.000000, 3.000000)" stroke="#1EC38B" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.55555556">
<rect id="Rectangle-path" x="0" y="0" width="14" height="14" rx="1.55555556"></rect>
<path d="M5.66666667,0 L5.66666667,14" id="Shape"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.1 (47250) - http://www.bohemiancoding.com/sketch -->
<title>icon-previewoff-off</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Artboard" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(-1463.000000, -366.000000)" stroke-linecap="round" stroke-linejoin="round">
<g id="icon-previewoff-off" transform="translate(1464.000000, 367.000000)" stroke="#C7C7C7" stroke-width="1.45454545">
<path d="M12.32,12.32 C11.0767927,13.267638 9.56298725,13.7926278 8,13.8181818 C2.90909091,13.8181818 0,8 0,8 C0.904647197,6.31410594 2.15937124,4.84116902 3.68,3.68 M6.47272727,2.35636364 C6.97333258,2.2391851 7.48586478,2.18060999 8,2.18181818 C13.0909091,2.18181818 16,8 16,8 C15.5585306,8.82589626 15.0320403,9.60344443 14.4290909,10.32 M9.54181818,9.54181818 C8.99790377,10.1255365 8.17874751,10.3658158 7.40570499,10.1683943 C6.63266247,9.97097281 6.02902719,9.36733753 5.8316057,8.59429501 C5.6341842,7.82125249 5.87446348,7.00209623 6.45818182,6.45818182" id="Shape"></path>
<path d="M0,0 L16,16" id="Shape"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.1 (47250) - http://www.bohemiancoding.com/sketch -->
<title>icon-previewoff-on</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Artboard" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(-1438.000000, -366.000000)" stroke-linecap="round" stroke-linejoin="round">
<g id="icon-previewoff-on" transform="translate(1439.000000, 367.000000)" stroke="#1EC38B" stroke-width="1.45454545">
<path d="M12.32,12.32 C11.0767927,13.267638 9.56298725,13.7926278 8,13.8181818 C2.90909091,13.8181818 0,8 0,8 C0.904647197,6.31410594 2.15937124,4.84116902 3.68,3.68 M6.47272727,2.35636364 C6.97333258,2.2391851 7.48586478,2.18060999 8,2.18181818 C13.0909091,2.18181818 16,8 16,8 C15.5585306,8.82589626 15.0320403,9.60344443 14.4290909,10.32 M9.54181818,9.54181818 C8.99790377,10.1255365 8.17874751,10.3658158 7.40570499,10.1683943 C6.63266247,9.97097281 6.02902719,9.36733753 5.8316057,8.59429501 C5.6341842,7.82125249 5.87446348,7.00209623 6.45818182,6.45818182" id="Shape"></path>
<path d="M0,0 L16,16" id="Shape"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB