1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-13 17:56:25 +00:00

Merge pull request #3002 from AWolf81/feature-tag-links

Add tag link handling with :tag:#tag syntax
This commit is contained in:
Junyoung Choi
2020-02-26 17:32:05 +09:00
committed by GitHub
2 changed files with 26 additions and 15 deletions

View File

@@ -1,5 +1,6 @@
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import React from 'react' import React from 'react'
import { connect } from 'react-redux'
import Markdown from 'browser/lib/markdown' import Markdown from 'browser/lib/markdown'
import _ from 'lodash' import _ from 'lodash'
import CodeMirror from 'codemirror' import CodeMirror from 'codemirror'
@@ -21,6 +22,7 @@ import { escapeHtmlCharacters } from 'browser/lib/utils'
import yaml from 'js-yaml' import yaml from 'js-yaml'
import { render } from 'react-dom' import { render } from 'react-dom'
import Carousel from 'react-image-carousel' import Carousel from 'react-image-carousel'
import { push } from 'connected-react-router'
import ConfigManager from '../main/lib/ConfigManager' import ConfigManager from '../main/lib/ConfigManager'
import uiThemes from 'browser/lib/ui-themes' import uiThemes from 'browser/lib/ui-themes'
import i18n from 'browser/lib/i18n' import i18n from 'browser/lib/i18n'
@@ -252,7 +254,7 @@ function getSourceLineNumberByElement(element) {
return parent.dataset.line !== undefined ? parseInt(parent.dataset.line) : -1 return parent.dataset.line !== undefined ? parseInt(parent.dataset.line) : -1
} }
export default class MarkdownPreview extends React.Component { class MarkdownPreview extends React.Component {
constructor(props) { constructor(props) {
super(props) super(props)
@@ -1116,6 +1118,7 @@ export default class MarkdownPreview extends React.Component {
e.stopPropagation() e.stopPropagation()
const rawHref = e.target.getAttribute('href') const rawHref = e.target.getAttribute('href')
const { dispatch } = this.props
if (!rawHref) return // not checked href because parser will create file://... string for [empty link]() if (!rawHref) return // not checked href because parser will create file://... string for [empty link]()
const parser = document.createElement('a') const parser = document.createElement('a')
@@ -1123,6 +1126,8 @@ export default class MarkdownPreview extends React.Component {
const isStartWithHash = rawHref[0] === '#' const isStartWithHash = rawHref[0] === '#'
const { href, hash } = parser const { href, hash } = parser
if (!rawHref) return // not checked href because parser will create file://... string for [empty link]()
const linkHash = hash === '' ? rawHref : hash // needed because we're having special link formats that are removed by parser e.g. :line:10 const linkHash = hash === '' ? rawHref : hash // needed because we're having special link formats that are removed by parser e.g. :line:10
const extractIdRegex = /file:\/\/.*main.?\w*.html#/ // file://path/to/main(.development.)html const extractIdRegex = /file:\/\/.*main.?\w*.html#/ // file://path/to/main(.development.)html
@@ -1169,6 +1174,13 @@ export default class MarkdownPreview extends React.Component {
return return
} }
const regexIsTagLink = /^:tag:([\w]+)$/
if (regexIsTagLink.test(rawHref)) {
const tag = rawHref.match(regexIsTagLink)[1]
dispatch(push(`/tags/${encodeURIComponent(tag)}`))
return
}
// other case // other case
this.openExternal(href) this.openExternal(href)
} }
@@ -1213,3 +1225,5 @@ MarkdownPreview.propTypes = {
smartArrows: PropTypes.bool, smartArrows: PropTypes.bool,
breaks: PropTypes.bool breaks: PropTypes.bool
} }
export default connect()(MarkdownPreview)

View File

@@ -16,7 +16,7 @@
const modifier = macOS ? 'metaKey' : 'ctrlKey' const modifier = macOS ? 'metaKey' : 'ctrlKey'
class HyperLink { class HyperLink {
constructor(cm) { constructor (cm) {
this.cm = cm this.cm = cm
this.lineDiv = cm.display.lineDiv this.lineDiv = cm.display.lineDiv
@@ -47,7 +47,7 @@
passive: true passive: true
}) })
} }
getUrl(el) { getUrl (el) {
const className = el.className.split(' ') const className = el.className.split(' ')
if (className.indexOf('cm-url') !== -1) { if (className.indexOf('cm-url') !== -1) {
@@ -60,7 +60,7 @@
return null return null
} }
onMouseDown(e) { onMouseDown (e) {
const { target } = e const { target } = e
if (!e[modifier]) { if (!e[modifier]) {
return return
@@ -73,39 +73,37 @@
shell.openExternal(url) shell.openExternal(url)
} }
} }
onMouseEnter(e) { onMouseEnter (e) {
const { target } = e const { target } = e
const url = this.getUrl(target) const url = this.getUrl(target)
if (url) { if (url) {
if (e[modifier]) { if (e[modifier]) {
target.classList.add('CodeMirror-activeline-background', 'CodeMirror-hyperlink') target.classList.add('CodeMirror-activeline-background', 'CodeMirror-hyperlink')
} } else {
else {
target.classList.add('CodeMirror-activeline-background') target.classList.add('CodeMirror-activeline-background')
} }
this.showInfo(target) this.showInfo(target)
} }
} }
onMouseLeave(e) { onMouseLeave (e) {
if (this.tooltip.parentElement === this.lineDiv) { if (this.tooltip.parentElement === this.lineDiv) {
e.target.classList.remove('CodeMirror-activeline-background', 'CodeMirror-hyperlink') e.target.classList.remove('CodeMirror-activeline-background', 'CodeMirror-hyperlink')
this.lineDiv.removeChild(this.tooltip) this.lineDiv.removeChild(this.tooltip)
} }
} }
onMouseMove(e) { onMouseMove (e) {
if (this.tooltip.parentElement === this.lineDiv) { if (this.tooltip.parentElement === this.lineDiv) {
if (e[modifier]) { if (e[modifier]) {
e.target.classList.add('CodeMirror-hyperlink') e.target.classList.add('CodeMirror-hyperlink')
} } else {
else {
e.target.classList.remove('CodeMirror-hyperlink') e.target.classList.remove('CodeMirror-hyperlink')
} }
} }
} }
showInfo(relatedTo) { showInfo (relatedTo) {
const b1 = relatedTo.getBoundingClientRect() const b1 = relatedTo.getBoundingClientRect()
const b2 = this.lineDiv.getBoundingClientRect() const b2 = this.lineDiv.getBoundingClientRect()
const tdiv = this.tooltip const tdiv = this.tooltip
@@ -117,8 +115,7 @@
const top = b1.top - b2.top - b3.height - yOffset const top = b1.top - b2.top - b3.height - yOffset
if (top < 0) { if (top < 0) {
tdiv.style.top = (b1.top - b2.top + b1.height + yOffset) + 'px' tdiv.style.top = (b1.top - b2.top + b1.height + yOffset) + 'px'
} } else {
else {
tdiv.style.top = top + 'px' tdiv.style.top = top + 'px'
} }
} }
@@ -127,4 +124,4 @@
CodeMirror.defineOption('hyperlink', true, (cm) => { CodeMirror.defineOption('hyperlink', true, (cm) => {
const addon = new HyperLink(cm) const addon = new HyperLink(cm)
}) })
}) })