1- const escapeMarkdownRegex = / [ \\ * _ { } [ \] ( ) # + \- . ! ] / g;
2- const unescapeMarkdownRegex = / \\ ( [ \\ ` * _ { } [ \] ( ) # + \- . ! ] ) / g;
1+ const escapeMarkdownRegex = / [ \\ * _ { } [ \] ( ) # + \- . ! < > ] / g;
2+ const unescapeMarkdownRegex = / \\ ( [ \\ ` * _ { } [ \] ( ) # + \- . ! < > ] ) / g;
3+ // Regex to find markdown links: [text](url) allowing for escaped brackets/parens within text/url
4+ const markdownLinkRegex = / ( \[ ( (?: \\ .| [ ^ [ \] \\ ] ) + ) \] \( ( (?: \\ .| [ ^ ( ) \\ ] ) + ) \) ) / g;
35
46const escapeMarkdownHeaderRegex = / ^ = = = / gm;
57const unescapeMarkdownHeaderRegex = / ^ \u200b = = = / gm;
@@ -8,19 +10,46 @@ const unescapeMarkdownHeaderRegex = /^\u200b===/gm;
810const markdownQuotedRegex = / \r ? \n / g;
911const markdownBacktickRegex = / ` / g;
1012
11- export function escapeMarkdown ( s : string , options : { quoted ?: boolean ; inlineBackticks ?: boolean } = { } ) : string {
12- s = s
13- // Escape markdown
14- . replace ( escapeMarkdownRegex , '\\$&' )
15- // Escape markdown header (since the above regex won't match it)
16- . replace ( escapeMarkdownHeaderRegex , '\u200b===' ) ;
13+ export function escapeMarkdown (
14+ s : string ,
15+ options ?: { quoted ?: boolean ; inlineBackticks ?: boolean ; preserveLinks ?: boolean } ,
16+ ) : string {
17+ // If preserving links, replace them with placeholders first
18+ if ( options ?. preserveLinks ) {
19+ const links = new Map < string , string > ( ) ;
20+ let linkIndex = 0 ;
1721
18- if ( options . inlineBackticks ) {
22+ s = s . replace ( markdownLinkRegex , match => {
23+ // Create a unique, unlikely-to-occur placeholder
24+ const placeholder = `$$$GLLINK${ linkIndex ++ } GLLINK$$$` ;
25+ links . set ( placeholder , match ) ;
26+ return placeholder ;
27+ } ) ;
28+
29+ // Escape markdown characters
30+ s = s . replace ( escapeMarkdownRegex , '\\$&' ) ;
31+
32+ // Restore the original links if they were preserved
33+ if ( options ?. preserveLinks && links . size ) {
34+ for ( const [ placeholder , originalLink ] of links ) {
35+ s = s . replace ( placeholder , originalLink ) ;
36+ }
37+ }
38+ } else {
39+ // Escape markdown characters
40+ s = s . replace ( escapeMarkdownRegex , '\\$&' ) ;
41+ }
42+
43+ // Escape markdown header (since the above regex won't match it)
44+ s = s . replace ( escapeMarkdownHeaderRegex , '\u200b===' ) ;
45+
46+ if ( options ?. inlineBackticks ) {
1947 s = escapeMarkdownCodeBlocks ( s ) ;
2048 } else {
2149 s = s . replace ( markdownBacktickRegex , '\\$&' ) ;
2250 }
23- if ( ! options . quoted ) return s ;
51+
52+ if ( ! options ?. quoted ) return s ;
2453
2554 // Keep under the same block-quote but with line breaks
2655 return s . trim ( ) . replace ( markdownQuotedRegex , '\t\\\n> ' ) ;
0 commit comments