diff --git a/browser/main/HomePage/ArticleDetail.js b/browser/main/HomePage/ArticleDetail.js index 4a4b7f0d..52e49f39 100644 --- a/browser/main/HomePage/ArticleDetail.js +++ b/browser/main/HomePage/ArticleDetail.js @@ -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 { {this.state.previewMode - ? + ? : ( this.handleContentChange(e, value)} diff --git a/lib/components/CodeEditor.js b/lib/components/CodeEditor.js index d82ca3f2..e6941ed8 100644 --- a/lib/components/CodeEditor.js +++ b/lib/components/CodeEditor.js @@ -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 (
diff --git a/lib/markdown.js b/lib/markdown.js index b27830ea..619b9655 100644 --- a/lib/markdown.js +++ b/lib/markdown.js @@ -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 + '' + } + return result +} + export default function markdown (content) { if (content == null) content = '' + return md.render(content.toString()) }