({ children, className, ...props })
| 82 | ); |
| 83 | }, |
| 84 | code({ children, className, ...props }) { |
| 85 | // react-markdown v9 移除了 inline prop。需要自己判断: |
| 86 | // 1) 带 language- className → 一定是 fenced code block |
| 87 | // 2) children 含换行 → 即使 fenced code 不带语言也是 block |
| 88 | // 3) 否则才是 inline code(单反引号 `...` 形式) |
| 89 | // 之前的 `inline = !className` 错判:fenced code 不指定语言时 className 也是 |
| 90 | // undefined,被当成 inline 渲染,于是每行套了浅底样式与黑色 pre 容器分离。 |
| 91 | const childText = |
| 92 | typeof children === "string" |
| 93 | ? children |
| 94 | : Array.isArray(children) |
| 95 | ? children.join("") |
| 96 | : ""; |
| 97 | const hasLanguage = !!className && /\blanguage-/.test(className); |
| 98 | const isBlock = hasLanguage || childText.includes("\n"); |
| 99 | |
| 100 | if (!isBlock) { |
| 101 | // inline code:浅灰底 + 前景色字 |
| 102 | return ( |
| 103 | <code |
| 104 | className="rounded bg-muted px-1 py-0.5 font-mono text-sm text-foreground" |
| 105 | {...props} |
| 106 | > |
| 107 | {children} |
| 108 | </code> |
| 109 | ); |
| 110 | } |
| 111 | |
| 112 | // fenced code block 内的 <code>:让 pre 提供背景,code 自己只负责字色, |
| 113 | // 强制透明背景 + 0 padding 防止 typography / 其它来源的样式渗入。 |
| 114 | // 末行若是下沉的代码块锚点(^c-...,见 relocateCodeFenceAnchors),抽成 id 让 |
| 115 | // [[raw/...#^c-...]] 引用能 HashScroller 跳转,并从可见代码里剥掉锚点噪音。 |
| 116 | const { display, id } = extractCodeBlockAnchor(childText); |
| 117 | return ( |
| 118 | <code |
| 119 | id={id} |
| 120 | className={`${className ?? ""} !bg-transparent !p-0 !text-zinc-100`} |
| 121 | {...props} |
| 122 | > |
| 123 | {display} |
| 124 | </code> |
| 125 | ); |
| 126 | }, |
| 127 | }; |
| 128 | |
| 129 | /** |
nothing calls this directly
no test coverage detected