@@ -14,6 +14,34 @@ let cachedPandocAvailable: boolean | null = null;
1414let cachedMmdcAvailable : boolean | null = null ;
1515let cachedMarkdownIt : MarkdownIt | null = null ;
1616
17+ function stripAnsi ( input : string ) : string {
18+ return input . replace ( / \u001b \[ [ 0 - 9 ; ] * m / g, "" ) ;
19+ }
20+
21+ function formatMermaidError ( error : unknown ) : string {
22+ if ( ! error || typeof error !== "object" ) return "未知错误" ;
23+ const err = error as { message ?: string ; stderr ?: unknown ; stdout ?: unknown } ;
24+ const parts : string [ ] = [ ] ;
25+ if ( err . message ) {
26+ parts . push ( stripAnsi ( err . message ) . trim ( ) ) ;
27+ }
28+ const extra = [ err . stderr , err . stdout ] . find (
29+ ( value ) => typeof value === "string" || Buffer . isBuffer ( value ) ,
30+ ) ;
31+ if ( extra ) {
32+ const text = stripAnsi (
33+ typeof extra === "string" ? extra : Buffer . from ( extra as Buffer ) . toString ( "utf8" ) ,
34+ ) ;
35+ const line = text . split ( / \r ? \n / ) . map ( ( item ) => item . trim ( ) ) . find ( Boolean ) ;
36+ if ( line && ! parts . join ( " " ) . includes ( line ) ) {
37+ parts . push ( line ) ;
38+ }
39+ }
40+ const merged = parts . join ( " | " ) . trim ( ) ;
41+ if ( ! merged ) return "未知错误" ;
42+ return merged . length > 300 ? `${ merged . slice ( 0 , 300 ) } ...` : merged ;
43+ }
44+
1745export function isPandocAvailable ( ) : boolean {
1846 if ( cachedPandocAvailable !== null ) return cachedPandocAvailable ;
1947 try {
@@ -96,15 +124,22 @@ function renderMermaidToSvg(source: string): MermaidRenderResult {
96124 const attempts : Array < { text : string ; normalized : boolean } > = [ { text : source , normalized : false } ] ;
97125 if ( normalized !== source ) attempts . push ( { text : normalized , normalized : true } ) ;
98126 let lastError : unknown ;
127+ let normalizedTried = false ;
99128 for ( const attempt of attempts ) {
100129 try {
101130 return { svg : renderMermaidWithMmdc ( attempt . text ) , normalized : attempt . normalized } ;
102131 } catch ( error ) {
132+ if ( attempt . normalized ) normalizedTried = true ;
103133 lastError = error ;
104134 }
105135 }
106- if ( lastError instanceof Error ) throw lastError ;
107- throw new Error ( "Failed to render mermaid diagram." ) ;
136+ if ( lastError instanceof Error ) {
137+ const suffix = normalizedTried ? " (auto label normalization attempted)" : "" ;
138+ throw new Error ( `${ lastError . message } ${ suffix } ` ) ;
139+ }
140+ throw new Error (
141+ normalizedTried ? "Failed to render mermaid diagram after label normalization." : "Failed to render mermaid diagram." ,
142+ ) ;
108143}
109144
110145export function preprocessMarkdown ( markdown : string , options : MarkdownRenderOptions = { } ) : string {
@@ -129,9 +164,10 @@ export function preprocessMarkdown(markdown: string, options: MarkdownRenderOpti
129164 }
130165 }
131166 return `<div class="mermaid-diagram">\n${ result . svg } \n</div>` ;
132- } catch {
167+ } catch ( error ) {
133168 if ( shouldLog ) {
134- logger ( `Mermaid 块 #${ index } 渲染失败,保持代码块原样。` ) ;
169+ const message = formatMermaidError ( error ) ;
170+ logger ( `Mermaid 块 #${ index } 渲染失败,保持代码块原样。原因: ${ message } ` ) ;
135171 }
136172 return match ;
137173 }
0 commit comments