|
1 |
| -(function (mod) { |
2 |
| - if (typeof exports === 'object' && typeof module === 'object') { // Common JS |
| 1 | +;(function(mod) { |
| 2 | + if (typeof exports === 'object' && typeof module === 'object') { |
| 3 | + // Common JS |
3 | 4 | mod(require('../codemirror/lib/codemirror'))
|
4 |
| - } else if (typeof define === 'function' && define.amd) { // AMD |
| 5 | + } else if (typeof define === 'function' && define.amd) { |
| 6 | + // AMD |
5 | 7 | define(['../codemirror/lib/codemirror'], mod)
|
6 |
| - } else { // Plain browser env |
| 8 | + } else { |
| 9 | + // Plain browser env |
7 | 10 | mod(CodeMirror)
|
8 | 11 | }
|
9 |
| -})(function (CodeMirror) { |
| 12 | +})(function(CodeMirror) { |
10 | 13 | 'use strict'
|
11 | 14 |
|
12 | 15 | const shell = require('electron').shell
|
| 16 | + const remote = require('electron').remote |
| 17 | + const eventEmitter = { |
| 18 | + emit: function() { |
| 19 | + remote.getCurrentWindow().webContents.send.apply(null, arguments) |
| 20 | + } |
| 21 | + } |
13 | 22 | const yOffset = 2
|
14 | 23 |
|
15 | 24 | const macOS = global.process.platform === 'darwin'
|
16 | 25 | const modifier = macOS ? 'metaKey' : 'ctrlKey'
|
17 | 26 |
|
18 | 27 | class HyperLink {
|
19 |
| - constructor (cm) { |
| 28 | + constructor(cm) { |
20 | 29 | this.cm = cm
|
21 | 30 | this.lineDiv = cm.display.lineDiv
|
22 | 31 |
|
|
28 | 37 | this.tooltip = document.createElement('div')
|
29 | 38 | this.tooltipContent = document.createElement('div')
|
30 | 39 | this.tooltipIndicator = document.createElement('div')
|
31 |
| - this.tooltip.setAttribute('class', 'CodeMirror-hover CodeMirror-matchingbracket CodeMirror-selected') |
| 40 | + this.tooltip.setAttribute( |
| 41 | + 'class', |
| 42 | + 'CodeMirror-hover CodeMirror-matchingbracket CodeMirror-selected' |
| 43 | + ) |
32 | 44 | this.tooltip.setAttribute('cm-ignore-events', 'true')
|
33 | 45 | this.tooltip.appendChild(this.tooltipContent)
|
34 | 46 | this.tooltip.appendChild(this.tooltipIndicator)
|
35 |
| - this.tooltipContent.textContent = `${macOS ? 'Cmd(⌘)' : 'Ctrl(^)'} + click to follow link` |
| 47 | + this.tooltipContent.textContent = `${ |
| 48 | + macOS ? 'Cmd(⌘)' : 'Ctrl(^)' |
| 49 | + } + click to follow link` |
36 | 50 |
|
37 | 51 | this.lineDiv.addEventListener('mousedown', this.onMouseDown)
|
38 | 52 | this.lineDiv.addEventListener('mouseenter', this.onMouseEnter, {
|
|
47 | 61 | passive: true
|
48 | 62 | })
|
49 | 63 | }
|
50 |
| - getUrl (el) { |
| 64 | + getUrl(el) { |
51 | 65 | const className = el.className.split(' ')
|
52 | 66 |
|
53 | 67 | if (className.indexOf('cm-url') !== -1) {
|
|
60 | 74 |
|
61 | 75 | return null
|
62 | 76 | }
|
63 |
| - onMouseDown (e) { |
| 77 | + specialLinkHandler(e, rawHref, linkHash) { |
| 78 | + const isStartWithHash = rawHref[0] === '#' |
| 79 | + |
| 80 | + const extractIdRegex = /file:\/\/.*main.?\w*.html#/ // file://path/to/main(.development.)html |
| 81 | + const regexNoteInternalLink = new RegExp(`${extractIdRegex.source}(.+)`) |
| 82 | + if (isStartWithHash || regexNoteInternalLink.test(rawHref)) { |
| 83 | + const posOfHash = linkHash.indexOf('#') |
| 84 | + if (posOfHash > -1) { |
| 85 | + const extractedId = linkHash.slice(posOfHash + 1) |
| 86 | + const targetId = mdurl.encode(extractedId) |
| 87 | + const targetElement = document.getElementById(targetId) // this.getWindow().document.getElementById(targetId) |
| 88 | + |
| 89 | + if (targetElement != null) { |
| 90 | + this.scrollTo(0, targetElement.offsetTop) |
| 91 | + } |
| 92 | + return |
| 93 | + } |
| 94 | + } |
| 95 | + |
| 96 | + // this will match the new uuid v4 hash and the old hash |
| 97 | + // e.g. |
| 98 | + // :note:1c211eb7dcb463de6490 and |
| 99 | + // :note:7dd23275-f2b4-49cb-9e93-3454daf1af9c |
| 100 | + const regexIsNoteLink = /^:note:([a-zA-Z0-9-]{20,36})$/ |
| 101 | + if (regexIsNoteLink.test(linkHash)) { |
| 102 | + eventEmitter.emit('list:jump', linkHash.replace(':note:', '')) |
| 103 | + return |
| 104 | + } |
| 105 | + |
| 106 | + const regexIsLine = /^:line:[0-9]/ |
| 107 | + if (regexIsLine.test(linkHash)) { |
| 108 | + const numberPattern = /\d+/g |
| 109 | + |
| 110 | + const lineNumber = parseInt(linkHash.match(numberPattern)[0]) |
| 111 | + eventEmitter.emit('line:jump', lineNumber) |
| 112 | + return |
| 113 | + } |
| 114 | + |
| 115 | + // this will match the old link format storage.key-note.key |
| 116 | + // e.g. |
| 117 | + // 877f99c3268608328037-1c211eb7dcb463de6490 |
| 118 | + const regexIsLegacyNoteLink = /^(.{20})-(.{20})$/ |
| 119 | + if (regexIsLegacyNoteLink.test(linkHash)) { |
| 120 | + eventEmitter.emit('list:jump', linkHash.split('-')[1]) |
| 121 | + return |
| 122 | + } |
| 123 | + |
| 124 | + const regexIsTagLink = /^:tag:#([\w]+)$/ |
| 125 | + if (regexIsTagLink.test(rawHref)) { |
| 126 | + const tag = rawHref.match(regexIsTagLink)[1] |
| 127 | + eventEmitter.emit('dispatch:push', `/tags/${encodeURIComponent(tag)}`) |
| 128 | + return |
| 129 | + } |
| 130 | + } |
| 131 | + onMouseDown(e) { |
64 | 132 | const { target } = e
|
65 | 133 | if (!e[modifier]) {
|
66 | 134 | return
|
67 | 135 | }
|
68 | 136 |
|
| 137 | + const rawHref = e.target.innerText.trim().slice(1, -1) // get link text from markdown text |
| 138 | + |
| 139 | + if (!rawHref) return // not checked href because parser will create file://... string for [empty link]() |
| 140 | + |
| 141 | + const parser = document.createElement('a') |
| 142 | + parser.href = rawHref |
| 143 | + const { href, hash } = parser |
| 144 | + |
| 145 | + if (!rawHref) return // not checked href because parser will create file://... string for [empty link]() |
| 146 | + |
| 147 | + const linkHash = hash === '' ? rawHref : hash // needed because we're having special link formats that are removed by parser e.g. :line:10 |
| 148 | + |
| 149 | + this.specialLinkHandler(target, rawHref, linkHash) |
| 150 | + |
69 | 151 | const url = this.getUrl(target)
|
| 152 | + |
| 153 | + // all special cases handled --> other case |
70 | 154 | if (url) {
|
71 | 155 | e.preventDefault()
|
72 | 156 |
|
73 | 157 | shell.openExternal(url)
|
74 | 158 | }
|
75 | 159 | }
|
76 |
| - onMouseEnter (e) { |
| 160 | + onMouseEnter(e) { |
77 | 161 | const { target } = e
|
78 | 162 |
|
79 | 163 | const url = this.getUrl(target)
|
80 | 164 | if (url) {
|
81 | 165 | if (e[modifier]) {
|
82 |
| - target.classList.add('CodeMirror-activeline-background', 'CodeMirror-hyperlink') |
| 166 | + target.classList.add( |
| 167 | + 'CodeMirror-activeline-background', |
| 168 | + 'CodeMirror-hyperlink' |
| 169 | + ) |
83 | 170 | } else {
|
84 | 171 | target.classList.add('CodeMirror-activeline-background')
|
85 | 172 | }
|
86 | 173 |
|
87 | 174 | this.showInfo(target)
|
88 | 175 | }
|
89 | 176 | }
|
90 |
| - onMouseLeave (e) { |
| 177 | + onMouseLeave(e) { |
91 | 178 | if (this.tooltip.parentElement === this.lineDiv) {
|
92 |
| - e.target.classList.remove('CodeMirror-activeline-background', 'CodeMirror-hyperlink') |
| 179 | + e.target.classList.remove( |
| 180 | + 'CodeMirror-activeline-background', |
| 181 | + 'CodeMirror-hyperlink' |
| 182 | + ) |
93 | 183 |
|
94 | 184 | this.lineDiv.removeChild(this.tooltip)
|
95 | 185 | }
|
96 | 186 | }
|
97 |
| - onMouseMove (e) { |
| 187 | + onMouseMove(e) { |
98 | 188 | if (this.tooltip.parentElement === this.lineDiv) {
|
99 | 189 | if (e[modifier]) {
|
100 | 190 | e.target.classList.add('CodeMirror-hyperlink')
|
|
103 | 193 | }
|
104 | 194 | }
|
105 | 195 | }
|
106 |
| - showInfo (relatedTo) { |
| 196 | + showInfo(relatedTo) { |
107 | 197 | const b1 = relatedTo.getBoundingClientRect()
|
108 | 198 | const b2 = this.lineDiv.getBoundingClientRect()
|
109 | 199 | const tdiv = this.tooltip
|
110 | 200 |
|
111 |
| - tdiv.style.left = (b1.left - b2.left) + 'px' |
| 201 | + tdiv.style.left = b1.left - b2.left + 'px' |
112 | 202 | this.lineDiv.appendChild(tdiv)
|
113 | 203 |
|
114 | 204 | const b3 = tdiv.getBoundingClientRect()
|
115 | 205 | const top = b1.top - b2.top - b3.height - yOffset
|
116 | 206 | if (top < 0) {
|
117 |
| - tdiv.style.top = (b1.top - b2.top + b1.height + yOffset) + 'px' |
| 207 | + tdiv.style.top = b1.top - b2.top + b1.height + yOffset + 'px' |
118 | 208 | } else {
|
119 | 209 | tdiv.style.top = top + 'px'
|
120 | 210 | }
|
121 | 211 | }
|
122 | 212 | }
|
123 | 213 |
|
124 |
| - CodeMirror.defineOption('hyperlink', true, (cm) => { |
| 214 | + CodeMirror.defineOption('hyperlink', true, cm => { |
125 | 215 | const addon = new HyperLink(cm)
|
126 | 216 | })
|
127 | 217 | })
|
0 commit comments