@@ -59,7 +59,7 @@ function escapeVueSyntax(src: string): string {
5959 } ) . join ( '\n' )
6060}
6161
62- const KNOWN_TAGS = / ^ < \/ ? (?: a | a b b r | a d d r e s s | a r e a | a r t i c l e | a s i d e | a u d i o | b | b a s e | b d i | b d o | b l o c k q u o t e | b o d y | b r | b u t t o n | c a n v a s | c a p t i o n | c i t e | c o d e | c o l | c o l g r o u p | d a t a | d a t a l i s t | d d | d e l | d e t a i l s | d f n | d i a l o g | d i v | d l | d t | e m | e m b e d | f i e l d s e t | f i g c a p t i o n | f i g u r e | f o o t e r | f o r m | h [ 1 - 6 ] | h e a d | h e a d e r | h g r o u p | h r | h t m l | i | i f r a m e | i m g | i n p u t | i n s | k b d | l a b e l | l e g e n d | l i | l i n k | m a i n | m a p | m a r k | m e n u | m e t a | m e t e r | n a v | n o s c r i p t | o b j e c t | o l | o p t g r o u p | o p t i o n | o u t p u t | p | p a r a m | p i c t u r e | p r e | p r o g r e s s | q | r p | r t | r u b y | s | s a m p | s c r i p t | s e a r c h | s e c t i o n | s e l e c t | s l o t | s m a l l | s o u r c e | s p a n | s t r o n g | s t y l e | s u b | s u m m a r y | s u p | t a b l e | t b o d y | t d | t e m p l a t e | t e x t a r e a | t f o o t | t h | t h e a d | t i m e | t i t l e | t r | t r a c k | u | u l | v a r | v i d e o | w b r | s v g | p a t h | g | c i r c l e | r e c t | l i n e | p o l y l i n e | p o l y g o n | t e x t | d e f s | u s e | s y m b o l ) [ \s > \ /! ] / i
62+ const KNOWN_TAGS = / ^ < \/ ? (?: a | a b b r | a d d r e s s | a r e a | a r t i c l e | a s i d e | a u d i o | b | b a s e | b d i | b d o | b l o c k q u o t e | b o d y | b r | b u t t o n | c a n v a s | c a p t i o n | c i t e | c o d e | c o l | c o l g r o u p | d a t a | d a t a l i s t | d d | d e l | d e t a i l s | d f n | d i a l o g | d i v | d l | d t | e m | e m b e d | f i e l d s e t | f i g c a p t i o n | f i g u r e | f o o t e r | f o r m | h [ 1 - 6 ] | h e a d | h e a d e r | h g r o u p | h r | h t m l | i | i f r a m e | i m g | i n p u t | i n s | k b d | l a b e l | l e g e n d | l i | l i n k | m a i n | m a p | m a r k | m e n u | m e t a | m e t e r | n a v | n o s c r i p t | o b j e c t | o l | o p t g r o u p | o p t i o n | o u t p u t | p | p a r a m | p i c t u r e | p r e | p r o g r e s s | q | r p | r t | r u b y | s | s a m p | s c r i p t | s e a r c h | s e c t i o n | s e l e c t | s l o t | s m a l l | s o u r c e | s p a n | s t r o n g | s t y l e | s u b | s u m m a r y | s u p | t a b l e | t b o d y | t d | t e m p l a t e | t e x t a r e a | t f o o t | t h | t h e a d | t i m e | t i t l e | t r | t r a c k | u | u l | v a r | v i d e o | w b r | s v g | p a t h | g | c i r c l e | r e c t | l i n e | p o l y l i n e | p o l y g o n | t e x t | d e f s | u s e | s y m b o l ) [ \s > / ! ] / i
6363
6464function escapeLine ( line : string ) : string {
6565 let result = ''
@@ -316,7 +316,7 @@ export default defineConfig({
316316 } ,
317317 preConfig : ( md ) => {
318318 const defaultParse = md . parse . bind ( md )
319- md . parse = ( src : string , env : any ) => {
319+ md . parse = ( src : string , env : Record < string , unknown > ) => {
320320 return defaultParse ( escapeVueSyntax ( src ) , env )
321321 }
322322 } ,
@@ -330,6 +330,41 @@ export default defineConfig({
330330 return defaultCodeInline ( tokens , idx , options , env , self )
331331 }
332332
333+ // Rewrite relative links that escape the docs/ directory to GitHub
334+ // source URLs, and rewrite README.md links to directory index paths
335+ // (only for links that stay within docs/).
336+ md . core . ruler . push ( 'rewrite-links' , ( state ) => {
337+ for ( const token of state . tokens ) {
338+ if ( ! token . children ) continue
339+ for ( const child of token . children ) {
340+ if ( child . type !== 'link_open' ) continue
341+ const href = child . attrGet ( 'href' )
342+ if ( ! href || href . startsWith ( 'http' ) || href . startsWith ( '#' ) || href . startsWith ( 'mailto:' ) ) continue
343+
344+ // Check if the link escapes docs/ (more ../ than directory depth)
345+ const docPath = state . env ?. relativePath || ''
346+ const docDir = docPath . split ( '/' ) . slice ( 0 , - 1 )
347+ const parts = href . split ( '#' )
348+ const linkPath = parts [ 0 ]
349+ const anchor = parts [ 1 ] ? '#' + parts [ 1 ] : ''
350+ const segments = linkPath . split ( '/' )
351+ let depth = 0
352+ for ( const s of segments ) { if ( s === '..' ) depth ++ ; else break }
353+ if ( depth > docDir . length ) {
354+ const remainder = segments . slice ( depth ) . join ( '/' )
355+ const prefix = / \. [ a - z A - Z 0 - 9 ] + $ / . test ( remainder ) && ! remainder . endsWith ( '/' ) ? 'blob' : 'tree'
356+ child . attrSet ( 'href' , `https://github.com/fullsend-ai/fullsend/${ prefix } /main/${ remainder } ${ anchor } ` )
357+ continue
358+ }
359+
360+ // For links staying within docs/, rewrite README.md to directory index
361+ if ( / R E A D M E \. m d ( # .* ) ? $ / . test ( href ) ) {
362+ child . attrSet ( 'href' , href . replace ( / R E A D M E \. m d ( # .* ) ? $ / , ( _ : string , a : string ) => a || './' ) )
363+ }
364+ }
365+ }
366+ } )
367+
333368 const defaultFence = md . renderer . rules . fence ! . bind ( md . renderer . rules )
334369 md . renderer . rules . fence = ( tokens , idx , options , env , self ) => {
335370 if ( tokens [ idx ] . info . trim ( ) === 'mermaid' ) {
0 commit comments