11import { isExternalLink } from 'hexo-util' ;
2- import Hexo from '../../../hexo' ;
2+ import type Hexo from '../../../hexo' ;
33
44let EXTERNAL_LINK_SITE_ENABLED = true ;
55const rATag = / < a (?: \s + ?| \s + ?[ ^ < > ] + ?\s + ?) h r e f = [ " ' ] ( (?: h t t p s ? : | \/ \/ ) [ ^ < > " ' ] + ) [ " ' ] [ ^ < > ] * > / gi;
66const rTargetAttr = / t a r g e t = / i;
77const rRelAttr = / r e l = / i;
88const rRelStrAttr = / r e l = [ " ' ] ( [ ^ < > " ' ] * ) [ " ' ] / i;
99
10+ const addNoopener = ( relStr : string , rel : string ) => {
11+ return rel . includes ( 'noopenner' ) ? relStr : `rel="${ rel } noopener"` ;
12+ } ;
13+
1014function externalLinkFilter ( this : Hexo , data : string ) : string {
1115 if ( ! EXTERNAL_LINK_SITE_ENABLED ) return ;
1216
@@ -17,18 +21,30 @@ function externalLinkFilter(this: Hexo, data: string): string {
1721 return ;
1822 }
1923
20- return data . replace ( rATag , ( str , href ) => {
21- if ( ! isExternalLink ( href , url , external_link . exclude as any ) || rTargetAttr . test ( str ) ) return str ;
24+ let result = '' ;
25+ let lastIndex = 0 ;
26+ let match ;
27+
28+ while ( ( match = rATag . exec ( data ) ) !== null ) {
29+ result += data . slice ( lastIndex , match . index ) ;
2230
23- if ( rRelAttr . test ( str ) ) {
24- str = str . replace ( rRelStrAttr , ( relStr , rel ) => {
25- return rel . includes ( 'noopenner' ) ? relStr : `rel="${ rel } noopener"` ;
26- } ) ;
27- return str . replace ( 'href=' , 'target="_blank" href=' ) ;
31+ const str = match [ 0 ] ;
32+ const href = match [ 1 ] ;
33+
34+ if ( ! isExternalLink ( href , url , external_link . exclude as any ) || rTargetAttr . test ( str ) ) {
35+ result += str ;
36+ } else {
37+ if ( rRelAttr . test ( str ) ) {
38+ result += str . replace ( rRelStrAttr , addNoopener ) . replace ( 'href=' , 'target="_blank" href=' ) ;
39+ } else {
40+ result += str . replace ( 'href=' , 'target="_blank" rel="noopener" href=' ) ;
41+ }
2842 }
43+ lastIndex = rATag . lastIndex ;
44+ }
45+ result += data . slice ( lastIndex ) ;
2946
30- return str . replace ( 'href=' , 'target="_blank" rel="noopener" href=' ) ;
31- } ) ;
47+ return result ;
3248}
3349
3450export = externalLinkFilter ;
0 commit comments