作ったもの
Markdown Live — https://sen.ltd/portfolio/markdown-live/
- Markdown パーサをゼロから実装(CommonMark サブセット)
- 3 プレビューテーマ: GitHub / Qiita / Zenn
- 分割ペイン、リサイズ可能
- localStorage で自動保存
- HTML ダウンロード / コピー
- 文字数・単語数・行数カウント
- ペイン間スクロール同期
vanilla JS、ゼロ依存、ビルド不要。node --test で 61 ケース。
行ベースのブロックパーサ
ヘッダ・コードフェンス・リスト・引用はすべて行頭の文字で判定可能。行番号 i を各ハンドラが消費する形で進める。
インラインは順序付き regex 置換
// コードスパン最優先(中を保護)
result = result.replace(/`([^`]+)`/g, '<code>$1</code>');
// 画像 → リンク(! が失われないように)
result = result.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img alt="$1" src="$2">');
result = result.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
// ** を先、* を後
result = result.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
result = result.replace(/\*([^*]+)\*/g, '<em>$1</em>');
順序が命。完全な CommonMark は AST ベースで 1 万行級だが、99% の実用ケースはこれで足りる。
テーマ切替はインライン <style> 置換
3 テーマを CSS 文字列として持ち、<style id="theme-style"> の textContent を書き換えるだけ。外部 CSS の再ロードなし、ちらつきなし。
スクロール同期の無限ループ回避
両ペインの scroll イベントが互いに発火する無限ループを requestAnimationFrame + フラグで防ぐ。
シリーズ
100+ 公開ポートフォリオ シリーズの #55 です。
