import MarkdownIt from 'markdown-it' ; import { MarkdownRenderer } from '../markdown' ; import { URL } from 'url' ; import { EXTERNAL_URL_RE } from '../../shared' ; const indexRE = /(^|.*\/)index.md(#?.*)$/i ; export const linkPlugin = ( md , externalAttrs ) => { md . renderer . rules . link_open = ( tokens , idx , options , env , self ) => { const token = tokens [ idx ] ; const hrefIndex = token . attrIndex ( 'href' ) ; if ( hrefIndex >= 0 ) { const hrefAttr = token . attrs ! [ hrefIndex ] ; const url = hrefAttr [ 1 ] ; const isExternal = EXTERNAL_URL_RE . test ( url ) ; if ( isExternal ) { Object . entries ( externalAttrs ) . forEach ( ( [ key , val ] ) => { token . attrSet ( key , val ) ; } ) ; if ( url . replace ( EXTERNAL_URL_RE , '' ) . startsWith ( '//localhost:' ) ) { pushLink ( url ) ; } } else if ( ! url . startsWith ( '#' ) && ! url . startsWith ( 'mailto:' ) ) { normalizeHref ( hrefAttr ) ; } hrefAttr [ 1 ] = hrefAttr [ 1 ] . replace ( /\bimport\.meta/g , 'import%2Emeta' ) . replace ( /\bprocess\.env/g , 'process%2Eenv' ) ; } return self . renderToken ( tokens , idx , options ) ; } ; function normalizeHref ( hrefAttr ) { let url = hrefAttr [ 1 ] ; const indexMatch = url . match ( indexRE ) ; if ( indexMatch ) { const [ , path , hash ] = indexMatch ; url = path + hash ; } else { let cleanUrl = url . replace ( /\#.*$/ , '' ) . replace ( /\?.*$/ , '' ) ; if ( cleanUrl . endsWith ( '.md' ) ) { cleanUrl = cleanUrl . replace ( /\.md$/ , '.html' ) ; } if ( ! cleanUrl . endsWith ( '.html' ) && ! cleanUrl . endsWith ( '/' ) ) { cleanUrl += '.html' ; } const parsed = new URL ( url , 'http://a.com' ) ; url = cleanUrl + parsed . search + parsed . hash ; } if ( ! url . startsWith ( '/' ) && ! /^\.\// . test ( url ) ) { url = './' + url ; } pushLink ( url . replace ( /\.html$/ , '' ) ) ; hrefAttr [ 1 ] = decodeURI ( url ) ; } function pushLink ( link ) { const data = ( md as MarkdownRenderer ) . __data ; const links = data . links || ( data . links = [ ] ) ; links . push ( link ) ; } } ;