コードブロック内の@メンションは変換しない
コメント本文中の @userId を @displayName に変換するとき、コードブロック内のトークンまで置換してしまうと表示が崩れる。マークダウンをコードブロック境界で分割してから、非コード部分だけ変換するとうまくいった。
具体的には、コードブロックのパターンで本文を split し、セグメントがコードかどうかで処理を切り替える。
const CODE_SEGMENT_PATTERN = /(```[\s\S]*?```|`[^`\n]*`)/g;
function renderWithDisplayMentions(body: string, members: Member[]): string {
const idToName = new Map(members.map(m => [m.id, m.displayName]));
return body
.split(CODE_SEGMENT_PATTERN)
.map(segment =>
isCodeSegment(segment)
? segment // コードはそのまま
: replaceMentions(segment, idToName) // テキストだけ変換
)
.join("");
}
function isCodeSegment(s: string) {
return (s.startsWith("```") && s.endsWith("```")) ||
(s.startsWith("`") && s.endsWith("`"));
}
split に capture group を使うことで、コードブロック自体も配列の要素として残るのがポイント。capture group がないと区切り文字が消えてしまう。
メンションの置換時は displayName にマークダウン特殊文字が含まれうるのでエスケープも忘れずに。