Skip to content

Commit 5f96e31

Browse files
committed
add tag link handling with :tag:#tag syntax
1 parent 9a6ee9d commit 5f96e31

File tree

3 files changed

+60
-21
lines changed

3 files changed

+60
-21
lines changed

browser/components/MarkdownPreview.js

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import i18n from 'browser/lib/i18n'
2323
import fs from 'fs'
2424
import { render } from 'react-dom'
2525
import Carousel from 'react-image-carousel'
26+
import { hashHistory } from 'react-router'
2627
import ConfigManager from '../main/lib/ConfigManager'
2728

2829
const { remote, shell } = require('electron')
@@ -1015,15 +1016,19 @@ export default class MarkdownPreview extends React.Component {
10151016
e.preventDefault()
10161017
e.stopPropagation()
10171018

1018-
const href = e.target.getAttribute('href')
1019-
const linkHash = href.split('/').pop()
1019+
const rawHref = e.target.getAttribute('href')
1020+
const parser = document.createElement('a')
1021+
parser.href = e.target.getAttribute('href')
1022+
const { href, hash } = parser
1023+
const linkHash = hash === '' ? rawHref : hash // needed because we're having special link formats that are removed by parser e.g. :line:10
10201024

1021-
if (!href) return
1025+
if (!rawHref) return // not checked href because parser will create file://... string for [empty link]()
10221026

1023-
const regexNoteInternalLink = /main.html#(.+)/
1024-
if (regexNoteInternalLink.test(linkHash)) {
1025-
const targetId = mdurl.encode(linkHash.match(regexNoteInternalLink)[1])
1026-
const targetElement = this.refs.root.contentWindow.document.getElementById(
1027+
const regexNoteInternalLink = /.*[main.\w]*.html#/
1028+
1029+
if (regexNoteInternalLink.test(href)) {
1030+
const targetId = mdurl.encode(linkHash)
1031+
const targetElement = this.refs.root.contentWindow.document.querySelector(
10271032
targetId
10281033
)
10291034

@@ -1061,6 +1066,13 @@ export default class MarkdownPreview extends React.Component {
10611066
return
10621067
}
10631068

1069+
const regexIsTagLink = /^:tag:#([\w]+)$/
1070+
if (regexIsTagLink.test(rawHref)) {
1071+
const tag = rawHref.match(regexIsTagLink)[1]
1072+
hashHistory.push(`/tags/${encodeURIComponent(tag)}`)
1073+
return
1074+
}
1075+
10641076
// other case
10651077
shell.openExternal(href)
10661078
}

extra_scripts/codemirror/addon/hyperlink/hyperlink.js

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
const modifier = macOS ? 'metaKey' : 'ctrlKey'
1717

1818
class HyperLink {
19-
constructor(cm) {
19+
constructor (cm) {
2020
this.cm = cm
2121
this.lineDiv = cm.display.lineDiv
2222

@@ -47,7 +47,7 @@
4747
passive: true
4848
})
4949
}
50-
getUrl(el) {
50+
getUrl (el) {
5151
const className = el.className.split(' ')
5252

5353
if (className.indexOf('cm-url') !== -1) {
@@ -60,7 +60,7 @@
6060

6161
return null
6262
}
63-
onMouseDown(e) {
63+
onMouseDown (e) {
6464
const { target } = e
6565
if (!e[modifier]) {
6666
return
@@ -73,39 +73,37 @@
7373
shell.openExternal(url)
7474
}
7575
}
76-
onMouseEnter(e) {
76+
onMouseEnter (e) {
7777
const { target } = e
7878

7979
const url = this.getUrl(target)
8080
if (url) {
8181
if (e[modifier]) {
8282
target.classList.add('CodeMirror-activeline-background', 'CodeMirror-hyperlink')
83-
}
84-
else {
83+
} else {
8584
target.classList.add('CodeMirror-activeline-background')
8685
}
8786

8887
this.showInfo(target)
8988
}
9089
}
91-
onMouseLeave(e) {
90+
onMouseLeave (e) {
9291
if (this.tooltip.parentElement === this.lineDiv) {
9392
e.target.classList.remove('CodeMirror-activeline-background', 'CodeMirror-hyperlink')
9493

9594
this.lineDiv.removeChild(this.tooltip)
9695
}
9796
}
98-
onMouseMove(e) {
97+
onMouseMove (e) {
9998
if (this.tooltip.parentElement === this.lineDiv) {
10099
if (e[modifier]) {
101100
e.target.classList.add('CodeMirror-hyperlink')
102-
}
103-
else {
101+
} else {
104102
e.target.classList.remove('CodeMirror-hyperlink')
105103
}
106104
}
107105
}
108-
showInfo(relatedTo) {
106+
showInfo (relatedTo) {
109107
const b1 = relatedTo.getBoundingClientRect()
110108
const b2 = this.lineDiv.getBoundingClientRect()
111109
const tdiv = this.tooltip
@@ -117,8 +115,7 @@
117115
const top = b1.top - b2.top - b3.height - yOffset
118116
if (top < 0) {
119117
tdiv.style.top = (b1.top - b2.top + b1.height + yOffset) + 'px'
120-
}
121-
else {
118+
} else {
122119
tdiv.style.top = top + 'px'
123120
}
124121
}
@@ -127,4 +124,4 @@
127124
CodeMirror.defineOption('hyperlink', true, (cm) => {
128125
const addon = new HyperLink(cm)
129126
})
130-
})
127+
})

yarn.lock

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5685,6 +5685,13 @@ levn@^0.3.0, levn@~0.3.0:
56855685
prelude-ls "~1.1.2"
56865686
type-check "~0.3.2"
56875687

5688+
linkify-it@^2.0.0:
5689+
version "2.1.0"
5690+
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.1.0.tgz#c4caf38a6cd7ac2212ef3c7d2bde30a91561f9db"
5691+
integrity sha512-4REs8/062kV2DSHxNfq5183zrqXMl7WP0WzABH9IeJI+NLm429FgE1PDecltYfnOoFDFlZGh2T8PfZn0r+GTRg==
5692+
dependencies:
5693+
uc.micro "^1.0.1"
5694+
56885695
linkify-it@~1.2.0, linkify-it@~1.2.2:
56895696
version "1.2.4"
56905697
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-1.2.4.tgz#0773526c317c8fd13bd534ee1d180ff88abf881a"
@@ -5968,6 +5975,17 @@ markdown-it-sup@^1.0.0:
59685975
version "1.0.0"
59695976
resolved "https://registry.yarnpkg.com/markdown-it-sup/-/markdown-it-sup-1.0.0.tgz#cb9c9ff91a5255ac08f3fd3d63286e15df0a1fc3"
59705977

5978+
5979+
version "8.4.2"
5980+
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54"
5981+
integrity sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==
5982+
dependencies:
5983+
argparse "^1.0.7"
5984+
entities "~1.1.1"
5985+
linkify-it "^2.0.0"
5986+
mdurl "^1.0.1"
5987+
uc.micro "^1.0.5"
5988+
59715989
markdown-it@^5.0.3:
59725990
version "5.1.0"
59735991
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-5.1.0.tgz#25286b8465bac496f3f1b77eed544643e9bd718d"
@@ -6009,6 +6027,13 @@ markdown-toc@^1.2.0:
60096027
repeat-string "^1.6.1"
60106028
strip-color "^0.1.0"
60116029

6030+
markdownlint@^0.11.0:
6031+
version "0.11.0"
6032+
resolved "https://registry.yarnpkg.com/markdownlint/-/markdownlint-0.11.0.tgz#3858bbdbc1ab78abf0c098d841c72b63dd3206a0"
6033+
integrity sha512-wE5WdKD6zW2DQaPQ5TFBTXh5j76DnWd/IFffnDQgHmi6Y61DJXBDfLftZ/suJHuv6cwPjM6gKw2GaRLJMOR+Mg==
6034+
dependencies:
6035+
markdown-it "8.4.2"
6036+
60126037
match-at@^0.1.1:
60136038
version "0.1.1"
60146039
resolved "https://registry.yarnpkg.com/match-at/-/match-at-0.1.1.tgz#25d040d291777704d5e6556bbb79230ec2de0540"
@@ -9048,6 +9073,11 @@ uc.micro@^1.0.0, uc.micro@^1.0.1:
90489073
version "1.0.5"
90499074
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.5.tgz#0c65f15f815aa08b560a61ce8b4db7ffc3f45376"
90509075

9076+
uc.micro@^1.0.5:
9077+
version "1.0.6"
9078+
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
9079+
integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
9080+
90519081
uglify-js@^2.6:
90529082
version "2.8.29"
90539083
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"

0 commit comments

Comments
 (0)