1- import { useEffect , useState } from "react" ;
1+ import React , { useEffect , useState } from "react" ;
22import { Fragment , jsx , jsxs } from "react/jsx-runtime" ;
33import { unified } from "unified" ;
44import remarkParse from "remark-parse" ;
@@ -7,8 +7,11 @@ import remarkToRehype from "remark-rehype";
77import rehypeReact , { Options as RehypeReactOptions } from "rehype-react" ;
88import type { Components } from "hast-util-to-jsx-runtime" ;
99import rehypeShikiFromHighlighter from "@shikijs/rehype/core" ;
10- import { getSingletonHighlighter } from "@next-shared/shiki" ;
10+ import type { Element } from "hast" ;
11+ import { visit } from "unist-util-visit" ;
12+ import { getSingletonHighlighter , bundledLanguages } from "@next-shared/shiki" ;
1113import { rehypeMermaid } from "./rehypeMermaid.js" ;
14+ import { getCodeLanguage } from "./utils.js" ;
1215
1316const production = { Fragment, jsx, jsxs } ;
1417
@@ -29,6 +32,31 @@ export async function preloadHighlighter(
2932 } ) ;
3033}
3134
35+ function rehypeFallbackLanguage ( ) {
36+ return ( tree : Element ) => {
37+ visit ( tree , "element" , ( node , index , parent ) => {
38+ if (
39+ ! parent ||
40+ parent . type !== "element" ||
41+ parent . tagName !== "pre" ||
42+ node . tagName !== "code"
43+ ) {
44+ return ;
45+ }
46+
47+ const lang = getCodeLanguage ( node ) ;
48+ if (
49+ lang &&
50+ ! Object . prototype . hasOwnProperty . call ( bundledLanguages , lang )
51+ ) {
52+ node . properties . className = ( node . properties . className as string [ ] ) . map (
53+ ( c ) => ( c . startsWith ( "language-" ) ? "language-text" : c )
54+ ) ;
55+ }
56+ } ) ;
57+ } ;
58+ }
59+
3260// Reference https://github.com/remarkjs/react-remark/blob/39553e5f5c9e9b903bebf261788ff45130668de0/src/index.ts
3361export function MarkdownComponent ( {
3462 content,
@@ -53,6 +81,7 @@ export function MarkdownComponent({
5381 . use ( remarkGfm )
5482 . use ( remarkToRehype )
5583 . use ( rehypeMermaid )
84+ . use ( rehypeFallbackLanguage )
5685 . use ( rehypeShikiFromHighlighter , highlighter as any , {
5786 theme,
5887 lazy : true ,
@@ -71,7 +100,11 @@ export function MarkdownComponent({
71100 if ( ! ignore ) {
72101 // eslint-disable-next-line no-console
73102 console . error ( "Convert markdown failed:" , error ) ;
74- setReactContent ( null ) ;
103+ setReactContent (
104+ < div style = { { color : "var(--color-error)" } } >
105+ Convert markdown failed: { String ( error ) }
106+ </ div >
107+ ) ;
75108 }
76109 }
77110 } ) ( ) ;
0 commit comments