@@ -15,6 +15,7 @@ const pathStr = `<svg viewBox="0 0 1024 1024" width="16" height="16" fill="curre
15
15
export interface HyperLinkState {
16
16
at : number ;
17
17
url : string ;
18
+ anchor : HyperLinkExtensionOptions [ 'anchor' ] ;
18
19
}
19
20
20
21
class HyperLinkIcon extends WidgetType {
@@ -33,11 +34,12 @@ class HyperLinkIcon extends WidgetType {
33
34
wrapper . innerHTML = pathStr ;
34
35
wrapper . className = 'cm-hyper-link-icon' ;
35
36
wrapper . rel = 'nofollow' ;
36
- return wrapper ;
37
+ const anchor = this . state . anchor && this . state . anchor ( wrapper ) ;
38
+ return anchor || wrapper ;
37
39
}
38
40
}
39
41
40
- function hyperLinkDecorations ( view : EditorView ) {
42
+ function hyperLinkDecorations ( view : EditorView , anchor ?: HyperLinkExtensionOptions [ 'anchor' ] ) {
41
43
const widgets : Array < Range < Decoration > > = [ ] ;
42
44
for ( const range of view . visibleRanges ) {
43
45
syntaxTree ( view . state ) . iterate ( {
@@ -50,6 +52,7 @@ function hyperLinkDecorations(view: EditorView) {
50
52
widget : new HyperLinkIcon ( {
51
53
at : to ,
52
54
url : callExp ,
55
+ anchor,
53
56
} ) ,
54
57
side : 1 ,
55
58
} ) ;
@@ -61,7 +64,12 @@ function hyperLinkDecorations(view: EditorView) {
61
64
return Decoration . set ( widgets ) ;
62
65
}
63
66
64
- const linkDecorator = ( regexp ?: RegExp , matchData ?: Record < string , string > , matchFn ?: ( str : string ) => string ) =>
67
+ const linkDecorator = (
68
+ regexp ?: RegExp ,
69
+ matchData ?: Record < string , string > ,
70
+ matchFn ?: ( str : string ) => string ,
71
+ anchor ?: HyperLinkExtensionOptions [ 'anchor' ] ,
72
+ ) =>
65
73
new MatchDecorator ( {
66
74
regexp : regexp || / \b ( (?: h t t p s ? | f t p ) : \/ \/ [ ^ \s / $ . ? # ] .[ ^ \s ] * ) \b / gi,
67
75
decorate : ( add , from , to , match , view ) => {
@@ -72,36 +80,37 @@ const linkDecorator = (regexp?: RegExp, matchData?: Record<string, string>, matc
72
80
}
73
81
const start = to ,
74
82
end = to ;
75
- const linkIcon = new HyperLinkIcon ( { at : start , url : urlStr } ) ;
83
+ const linkIcon = new HyperLinkIcon ( { at : start , url : urlStr , anchor } ) ;
76
84
add ( start , end , Decoration . widget ( { widget : linkIcon , side : 1 } ) ) ;
77
85
} ,
78
86
} ) ;
79
87
80
- export type hyperLinkExtensionOptions = {
88
+ export type HyperLinkExtensionOptions = {
81
89
regexp ?: RegExp ;
82
90
match ?: Record < string , string > ;
83
91
handle ?: ( value : string ) => string ;
92
+ anchor ?: ( dom : HTMLAnchorElement ) => HTMLAnchorElement ;
84
93
} ;
85
94
86
- export function hyperLinkExtension ( { regexp, match, handle } : hyperLinkExtensionOptions = { } ) {
95
+ export function hyperLinkExtension ( { regexp, match, handle, anchor } : HyperLinkExtensionOptions = { } ) {
87
96
return ViewPlugin . fromClass (
88
97
class HyperLinkView {
89
98
decorator ?: MatchDecorator ;
90
99
decorations : DecorationSet ;
91
100
constructor ( view : EditorView ) {
92
101
if ( regexp ) {
93
- this . decorator = linkDecorator ( regexp , match , handle ) ;
102
+ this . decorator = linkDecorator ( regexp , match , handle , anchor ) ;
94
103
this . decorations = this . decorator . createDeco ( view ) ;
95
104
} else {
96
- this . decorations = hyperLinkDecorations ( view ) ;
105
+ this . decorations = hyperLinkDecorations ( view , anchor ) ;
97
106
}
98
107
}
99
108
update ( update : ViewUpdate ) {
100
109
if ( update . docChanged || update . viewportChanged ) {
101
110
if ( regexp && this . decorator ) {
102
111
this . decorations = this . decorator . updateDeco ( update , this . decorations ) ;
103
112
} else {
104
- this . decorations = hyperLinkDecorations ( update . view ) ;
113
+ this . decorations = hyperLinkDecorations ( update . view , anchor ) ;
105
114
}
106
115
}
107
116
}
0 commit comments