マークダウンでのエスケープの修正

守矢諏訪子 <suwako@076.moe>、2026-04-24 19:53
コミット 7492790a9cd32ec1c2a38724567bfc6cecb1aef1 ・親 119f9f4 ・ファイルを見る

1個のファイル、+17 -15

@@ -275,39 +275,39 @@
275275
276276 $patterns = [
277277 // 数式
278- '/\$\$([^$]+)\$\$/u' => function($matches): string {
278+ '/(?<!\\\\)\$\$([^$]+)\$\$/u' => function($matches): string {
279279 $placeholder = "{{ALG".count($this->algebraicPlaceholder).'ALG}}';
280280 $this->algebraicPlaceholder[$placeholder] = $matches[1];
281281 return $placeholder;
282282 },
283283 // 太字
284- '/\*\*(.+?)\*\*/u' => '<strong>$1</strong>',
284+ '/(?<!\\\\)\*\*(.+?)\*\*/u' => '<strong>$1</strong>',
285285 // 斜体
286- '/\*(.+?)\*/u' => '<em>$1</em>',
286+ '/(?<!\\\\)\*(.+?)\*/u' => '<em>$1</em>',
287287 // 下線
288- '/\_(.+?)\_/u' => '<u>$1</u>',
288+ '/(?<!\\\\)_(.+?)_/u' => '<u>$1</u>',
289289 // 取り消し線
290- '/\~(.+?)\~/u' => '<s>$1</s>',
290+ '/(?<!\\\\)~(.+?)~/u' => '<s>$1</s>',
291291 // Blink (with speed)
292- '/!:\((.+?)\)(.+?):!/u' => '<span class="blink" style="animation-duration: $1s;">$2</span>',
292+ '/(?<!\\\\)!:\((.+?)\)(.+?):!/u' => '<span class="blink" style="animation-duration: $1s;">$2</span>',
293293 // Blink
294- '/!:(.+?):!/u' => '<span class="blink">$1</span>',
294+ '/(?<!\\\\)!:(.+?):!/u' => '<span class="blink">$1</span>',
295295 // フォントの大きさ
296- '/\^\((.+?)\)(.+?)\^/u' => '<span style="font-size: $1px;">$2</span>',
296+ '/(?<!\\\\)\^\((.+?)\)(.+?)\^/u' => '<span style="font-size: $1px;">$2</span>',
297297 // フォントカラー
298- '/\%\((.+?)\)(.+?)\%/u' => '<span style="color: #$1;">$2</span>',
298+ '/(?<!\\\\)\%\((.+?)\)(.+?)\%/u' => '<span style="color: #$1;">$2</span>',
299299 // 画像
300- '/\!\[(.*?)(?:#([^\]]*))?\]\((.+?)\)/u' => '<img style="width: 100%; $2" src="$3" alt="$1" />',
300+ '/(?<!\\\\)\!\[(.*?)(?:#([^\]]*))?\]\((.+?)\)/u' => '<img style="width: 100%; $2" src="$3" alt="$1" />',
301301 // 音楽
302- '/\$\[([^\]]+)\]\(([^\)]+)\)/u' => '<audio controls><source src="$2" type="$1" /></audio>',
302+ '/(?<!\\\\)\$\[([^\]]+)\]\(([^\)]+)\)/u' => '<audio controls><source src="$2" type="$1" /></audio>',
303303 // 動画
304- '/\#\[([^\]]+)\]\(([^\)]+)\)/u' => '<video style="max-width: 100%;" controls><source src="$2" type="$1" /></video>',
304+ '/(?<!\\\\)\#\[([^\]]+)\]\(([^\)]+)\)/u' => '<video style="max-width: 100%;" controls><source src="$2" type="$1" /></video>',
305305 // リンク
306- '/\[(.+?)\]\((.+?)\)/u' => '<a href="$2">$1</a>',
306+ '/(?<!\\\\)\[(.+?)\]\((.+?)\)/u' => '<a href="$2">$1</a>',
307307 // 振り仮名
308- '/\&lt;(.+?)\&gt;\((.+?)\)/u' => '<ruby>$1<rp>(</rp><rt>$2</rt><rp>)</rp></ruby>',
308+ '/(?<!\\\\)&lt;(.+?)&gt;\((.+?)\)/u' => '<ruby>$1<rp>(</rp><rt>$2</rt><rp>)</rp></ruby>',
309309 // インラインコード
310- '/`(.+?)`/u' => '<code>$1</code>',
310+ '/(?<!\\\\)`(.+?)`/u' => '<code>$1</code>',
311311 ];
312312
313313 foreach ($patterns as $pattern => $replacement) {
@@ -324,6 +324,8 @@
324324 foreach ($this->algebraicPlaceholder as $placeholder => $expr) {
325325 $text = str_replace($placeholder, $this->parseAlgebraic($expr), $text);
326326 }
327+
328+ $text = preg_replace('/\\\\(.)/u', '$1', $text);
327329
328330 return $text;
329331 }