/
index.js
94 lines (90 loc) · 2.65 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import Delta from 'quill-delta'
import normalizeUrl from 'normalize-url'
const defaults = {
globalRegularExpression: /(https?:\/\/|www\.)[\S]+/g,
urlRegularExpression: /(https?:\/\/[\S]+)|(www.[\S]+)/,
normalizeRegularExpression: /(https?:\/\/[\S]+)|(www.[\S]+)/,
normalizeUrlOptions: {
stripFragment: false,
stripWWW: false
}
}
export default class MagicUrl {
constructor (quill, options) {
this.quill = quill
options = options || {}
this.options = {...defaults, ...options}
this.registerTypeListener()
this.registerPasteListener()
}
registerPasteListener () {
this.quill.clipboard.addMatcher(Node.TEXT_NODE, (node, delta) => {
if (typeof node.data !== 'string') {
return
}
const matches = node.data.match(this.options.globalRegularExpression)
if (matches && matches.length > 0) {
const newDelta = new Delta()
let str = node.data
matches.forEach(match => {
const split = str.split(match)
const beforeLink = split.shift()
newDelta.insert(beforeLink)
newDelta.insert(match, {link: this.normalize(match)})
str = split.join(match)
})
newDelta.insert(str)
delta.ops = newDelta.ops
}
return delta
})
}
registerTypeListener () {
this.quill.on('text-change', (delta) => {
let ops = delta.ops
// Only return true, if last operation includes whitespace inserts
// Equivalent to listening for enter, tab or space
if (!ops || ops.length < 1 || ops.length > 2) {
return
}
let lastOp = ops[ops.length - 1]
if (!lastOp.insert || typeof lastOp.insert !== 'string' || !lastOp.insert.match(/\s/)) {
return
}
this.checkTextForUrl()
})
}
checkTextForUrl () {
let sel = this.quill.getSelection()
if (!sel) {
return
}
let [leaf] = this.quill.getLeaf(sel.index)
if (!leaf.text || leaf.parent.domNode.localName === "a") {
return
}
let urlMatch = leaf.text.match(this.options.urlRegularExpression)
if (!urlMatch) {
return
}
let leafIndex = this.quill.getIndex(leaf)
let index = leafIndex + urlMatch.index
this.textToUrl(index, urlMatch[0])
}
textToUrl (index, url) {
const ops = new Delta()
.retain(index)
.delete(url.length)
.insert(url, {link: this.normalize(url)})
this.quill.updateContents(ops)
}
normalize (url) {
if (this.options.normalizeRegularExpression.test(url)) {
return normalizeUrl(url, this.options.normalizeUrlOptions)
}
return url
}
}
if (window.Quill) {
window.Quill.register('modules/magicUrl', MagicUrl);
}