@@ -10,6 +10,7 @@ import type { SanitizeOptions } from 'src/utilities/sanitizeHTML';
1010
1111export interface HighlightedMarkdownProps {
1212 className ?: string ;
13+ openLinksInNewTab ?: boolean ;
1314 sanitizeOptions ?: SanitizeOptions ;
1415 textOrMarkdown : string ;
1516}
@@ -20,7 +21,8 @@ export interface HighlightedMarkdownProps {
2021 * - Will perform syntax highlighting on any fenced code blocks
2122 */
2223export const Markdown = ( props : HighlightedMarkdownProps ) => {
23- const { className, sanitizeOptions, textOrMarkdown } = props ;
24+ const { className, openLinksInNewTab, sanitizeOptions, textOrMarkdown } =
25+ props ;
2426
2527 const theme = useTheme ( ) ;
2628
@@ -36,7 +38,7 @@ export const Markdown = (props: HighlightedMarkdownProps) => {
3638 lang,
3739 theme : getHighlighterTheme ( theme . palette . mode ) ,
3840 } ) ;
39- } catch ( error ) {
41+ } catch {
4042 return shiki . codeToHtml ( str , {
4143 lang : 'js' ,
4244 theme : getHighlighterTheme ( theme . palette . mode ) ,
@@ -48,6 +50,28 @@ export const Markdown = (props: HighlightedMarkdownProps) => {
4850 linkify : true ,
4951 } ) ;
5052
53+ if ( openLinksInNewTab ) {
54+ const defaultRender =
55+ unsafeMarkdownIt . renderer . rules . link_open ||
56+ function ( tokens , idx , options , env , self ) {
57+ return self . renderToken ( tokens , idx , options ) ;
58+ } ;
59+
60+ unsafeMarkdownIt . renderer . rules . link_open = function (
61+ tokens ,
62+ idx ,
63+ options ,
64+ env ,
65+ self
66+ ) {
67+ tokens [ idx ] . attrSet ( 'target' , '_blank' ) ;
68+ // Adding rel="noopener noreferrer" directly here just as backup,
69+ // although sanitizeHTML will already add it when it sees target="_blank"
70+ tokens [ idx ] . attrSet ( 'rel' , 'noopener noreferrer' ) ;
71+ return defaultRender ( tokens , idx , options , env , self ) ;
72+ } ;
73+ }
74+
5175 const unsafeParsedMarkdown = unsafeMarkdownIt . render ( textOrMarkdown ) ;
5276
5377 const sanitizedHtml = sanitizeHTML ( {
0 commit comments