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

自動的にスクロールを合わせてくれる

This commit is contained in:
Rokt33r
2015-12-05 05:56:53 +09:00
parent 35bb792496
commit 77f9e60177
3 changed files with 60 additions and 11 deletions

View File

@@ -435,7 +435,34 @@ export default class ArticleDetail extends React.Component {
handleTogglePreviewButtonClick (e) {
if (this.state.article.mode === 'markdown') {
this.setState({previewMode: !this.state.previewMode})
if (!this.state.previewMode) {
let cursorPosition = this.refs.code.getCursorPosition()
let firstVisibleRow = this.refs.code.getFirstVisibleRow()
this.setState({
previewMode: true,
cursorPosition,
firstVisibleRow
}, function () {
let previewEl = ReactDOM.findDOMNode(this.refs.preview)
let anchors = previewEl.querySelectorAll('.lineAnchor')
for (let i = 0; i < anchors.length; i++) {
if (parseInt(anchors[i].dataset.key, 10) > cursorPosition.row || i === anchors.length - 1) {
var targetAnchor = anchors[i > 0 ? i - 1 : 0]
previewEl.scrollTop = targetAnchor.offsetTop - 100
break
}
}
})
} else {
this.setState({
previewMode: false
}, function () {
console.log(this.state.cursorPosition)
this.refs.code.moveCursorTo(this.state.cursorPosition.row, this.state.cursorPosition.column)
this.refs.code.scrollToLine(this.state.firstVisibleRow)
this.refs.code.editor.focus()
})
}
}
}
@@ -524,7 +551,7 @@ export default class ArticleDetail extends React.Component {
</div>
{this.state.previewMode
? <MarkdownPreview content={this.state.article.content}/>
? <MarkdownPreview ref='preview' content={this.state.article.content}/>
: (<CodeEditor
ref='code'
onChange={(e, value) => this.handleContentChange(e, value)}

View File

@@ -30,6 +30,7 @@ module.exports = React.createClass({
editor.renderer.setShowGutter(true)
editor.setTheme('ace/theme/xcode')
editor.clearSelection()
editor.moveCursorTo(0, 0)
editor.setReadOnly(!!this.props.readOnly)
@@ -50,16 +51,14 @@ module.exports = React.createClass({
this.props.onChange(e, value)
}
}.bind(this))
this.setState({editor: editor})
},
componentDidUpdate: function (prevProps) {
if (this.state.editor.getValue() !== this.props.code) {
this.state.editor.setValue(this.props.code)
this.state.editor.clearSelection()
if (this.editor.getValue() !== this.props.code) {
this.editor.setValue(this.props.code)
this.editor.clearSelection()
}
if (prevProps.mode !== this.props.mode) {
var session = this.state.editor.getSession()
var session = this.editor.getSession()
let mode = _.findWhere(modes, {name: this.props.mode})
let syntaxMode = mode != null
? mode.mode
@@ -67,6 +66,18 @@ module.exports = React.createClass({
session.setMode('ace/mode/' + syntaxMode)
}
},
getFirstVisibleRow: function () {
return this.editor.getFirstVisibleRow()
},
getCursorPosition: function () {
return this.editor.getCursorPosition()
},
moveCursorTo: function (row, col) {
this.editor.moveCursorTo(row, col)
},
scrollToLine: function (num) {
this.editor.scrollToLine(num, false, false)
},
render: function () {
return (
<div ref='target' className={this.props.className == null ? 'CodeEditor' : 'CodeEditor ' + this.props.className}></div>

View File

@@ -8,20 +8,31 @@ var md = markdownit({
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(lang, str).value;
return hljs.highlight(lang, str).value
} catch (__) {}
}
try {
return hljs.highlightAuto(str).value;
return hljs.highlightAuto(str).value
} catch (__) {}
return ''; // use external default escaping
return ''
}
})
md.use(emoji)
let originalRenderToken = md.renderer.renderToken
md.renderer.renderToken = function renderToken (tokens, idx, options) {
let token = tokens[idx]
let result = originalRenderToken.call(md.renderer, tokens, idx, options)
if (token.map != null) {
return result + '<a class=\'lineAnchor\' data-key=\'' + token.map[0] + '\'></a>'
}
return result
}
export default function markdown (content) {
if (content == null) content = ''
return md.render(content.toString())
}