diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index 6ec2aceb8..9811aac54 100644 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -108,6 +108,8 @@ export default class MarkdownPreview extends React.Component { this.checkboxClickHandler = (e) => this.handleCheckboxClick(e) this.saveAsTextHandler = () => this.handleSaveAsText() this.saveAsMdHandler = () => this.handleSaveAsMd() + + this.linkClickHandler = this.handlelinkClick.bind(this) } handlePreviewAnchorClick (e) { @@ -249,6 +251,10 @@ export default class MarkdownPreview extends React.Component { el.removeEventListener('click', this.checkboxClickHandler) }) + _.forEach(this.refs.root.contentWindow.document.querySelectorAll('a'), (el) => { + el.removeEventListener('click', this.linkClickHandler) + }) + let { value, theme, indentSize, codeBlockTheme } = this.props this.refs.root.contentWindow.document.body.setAttribute('data-theme', theme) @@ -273,6 +279,10 @@ export default class MarkdownPreview extends React.Component { el.addEventListener('click', this.checkboxClickHandler) }) + _.forEach(this.refs.root.contentWindow.document.querySelectorAll('a'), (el) => { + el.addEventListener('click', this.linkClickHandler) + }) + codeBlockTheme = consts.THEMES.some((_theme) => _theme === codeBlockTheme) ? codeBlockTheme : 'default' @@ -373,6 +383,14 @@ export default class MarkdownPreview extends React.Component { return new window.Notification(title, options) } + handlelinkClick (e) { + const noteHash = e.target.hash + const regexIsNoteLink = /^#(.{20})-(.{20})$/ + if (regexIsNoteLink.test(noteHash)) { + eventEmitter.emit('list:jump', noteHash.replace(/^#/, '')) + } + } + render () { let { className, style, tabIndex } = this.props return ( diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index 59da9c9b6..833c276ce 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -47,6 +47,7 @@ class NoteList extends React.Component { this.alertIfSnippet() } this.importFromFileHandler = this.importFromFile.bind(this) + this.jumpNoteByHash = this.jumpNoteByHashHandler.bind(this) this.jumpToTopHandler = () => { this.jumpToTop() @@ -65,6 +66,7 @@ class NoteList extends React.Component { ee.on('list:top', this.jumpToTopHandler) ee.on('list:jumpToTop', this.jumpToTopHandler) ee.on('import:file', this.importFromFileHandler) + ee.on('list:jump', this.jumpNoteByHash) } componentWillReceiveProps (nextProps) { @@ -87,6 +89,7 @@ class NoteList extends React.Component { ee.off('list:top', this.jumpToTopHandler) ee.off('list:jumpToTop', this.jumpToTopHandler) ee.off('import:file', this.importFromFileHandler) + ee.off('list:jump', this.jumpNoteByHash) } componentDidUpdate (prevProps) { @@ -179,6 +182,31 @@ class NoteList extends React.Component { ee.emit('list:moved') } + jumpNoteByHashHandler (event, noteHash) { + // first argument event isn't used. + if (this.notes === null || this.notes.length === 0) { + return + } + + const { router } = this.context + const { location } = this.props + + let targetIndex = _.findIndex(this.notes, (note) => { + return note.storage + '-' + note.key === noteHash + }) + + if (targetIndex < 0) targetIndex = 0 + + router.push({ + pathname: location.pathname, + query: { + key: this.notes[targetIndex].storage + '-' + this.notes[targetIndex].key + } + }) + + ee.emit('list:moved') + } + handleNoteListKeyDown (e) { if (e.metaKey || e.ctrlKey) return true