44//
55
66import type StateCore from '../state_core'
7- import { arrayReplaceAt } from '../../../common/utils'
87
98function isLinkOpen ( str : string ) {
109 return / ^ < a [ > \s ] / i. test ( str )
@@ -14,18 +13,19 @@ function isLinkClose(str: string) {
1413}
1514
1615export default function linkify ( state : StateCore ) {
17- const blockTokens = state . tokens
18-
1916 if ( ! state . md . options . linkify )
2017 return
2118
19+ const blockTokens = state . tokens
20+ const linkify = state . md . linkify
21+
2222 for ( let j = 0 , l = blockTokens . length ; j < l ; j ++ ) {
2323 if ( blockTokens [ j ] . type !== 'inline' ||
24- ! state . md . linkify . pretest ( blockTokens [ j ] . content ) ) {
24+ ! linkify . pretest ( blockTokens [ j ] . content ) ) {
2525 continue
2626 }
2727
28- let tokens = blockTokens [ j ] . children !
28+ const tokens = blockTokens [ j ] . children !
2929
3030 let htmlLinkLevel = 0
3131
@@ -55,9 +55,14 @@ export default function linkify(state: StateCore) {
5555 if ( htmlLinkLevel > 0 )
5656 continue
5757
58- if ( currentToken . type === 'text' && state . md . linkify . test ( currentToken . content ) ) {
58+ if ( currentToken . type === 'text' ) {
5959 const text = currentToken . content
60- let links = state . md . linkify . match ( text ) ?? [ ]
60+ if ( ! linkify . pretest ( text ) )
61+ continue
62+
63+ const links = linkify . match ( text )
64+ if ( ! links ?. length )
65+ continue
6166
6267 // Now split string to nodes
6368 const nodes = [ ]
@@ -67,34 +72,33 @@ export default function linkify(state: StateCore) {
6772 // forbid escape sequence at the start of the string,
6873 // this avoids http\://example.com/ from being linkified as
6974 // http:<a href="//example.com/">//example.com/</a>
70- if ( links . length > 0 &&
71- links [ 0 ] . index === 0 &&
75+ const startFrom = ( links [ 0 ] . index === 0 &&
7276 i > 0 &&
73- tokens [ i - 1 ] . type === 'text_special' ) {
74- links = links . slice ( 1 )
75- }
77+ tokens [ i - 1 ] . type === 'text_special' )
78+ ? 1
79+ : 0
7680
77- for ( let ln = 0 ; ln < links . length ; ln ++ ) {
78- const url = links [ ln ] . url
79- const fullUrl = state . md . normalizeLink ( url )
81+ for ( let ln = startFrom ; ln < links . length ; ln ++ ) {
82+ const link = links [ ln ]
83+ const fullUrl = state . md . normalizeLink ( link . url )
8084 if ( ! state . md . validateLink ( fullUrl ) )
8185 continue
8286
83- let urlText = links [ ln ] . text
87+ let urlText = link . text
8488
8589 // Linkifier might send raw hostnames like "example.com", where url
8690 // starts with domain name. So we prepend http:// in those cases,
8791 // and remove it afterwards.
8892 //
89- if ( ! links [ ln ] . schema ) {
93+ if ( ! link . schema ) {
9094 urlText = state . md . normalizeLinkText ( `http://${ urlText } ` ) . replace ( / ^ h t t p : \/ \/ / , '' )
91- } else if ( links [ ln ] . schema === 'mailto:' && ! / ^ m a i l t o : / i. test ( urlText ) ) {
95+ } else if ( link . schema === 'mailto:' && ! / ^ m a i l t o : / i. test ( urlText ) ) {
9296 urlText = state . md . normalizeLinkText ( `mailto:${ urlText } ` ) . replace ( / ^ m a i l t o : / , '' )
9397 } else {
9498 urlText = state . md . normalizeLinkText ( urlText )
9599 }
96100
97- const pos = links [ ln ] . index
101+ const pos = link . index
98102
99103 if ( pos > lastPos ) {
100104 const token = new state . Token ( 'text' , '' , 0 )
@@ -121,7 +125,7 @@ export default function linkify(state: StateCore) {
121125 token_c . info = 'auto'
122126 nodes . push ( token_c )
123127
124- lastPos = links [ ln ] . lastIndex
128+ lastPos = link . lastIndex
125129 }
126130 if ( lastPos < text . length ) {
127131 const token = new state . Token ( 'text' , '' , 0 )
@@ -131,7 +135,7 @@ export default function linkify(state: StateCore) {
131135 }
132136
133137 // replace current node
134- blockTokens [ j ] . children = tokens = arrayReplaceAt ( tokens , i , nodes )
138+ tokens . splice ( i , 1 , ... nodes )
135139 }
136140 }
137141 }
0 commit comments