Skip to content

機能全覧:自動フォーマットの魔法

このレッスンでできること

  • プラグインの8つのコア機能を理解する
  • どのシーンでこのプラグインを使うべきか知る
  • プラグインの境界線を理解する(何ができないか)

現在の課題

プラグイン情報

本プラグインの正式名称は @franlol/opencode-md-table-formatter、以下「テーブルフォーマットプラグイン」と呼びます。

AIが生成するMarkdownテーブルは、よくこんな感じです:

markdown
| 名称 | 描述 | 状态 |
|--- | --- | ---|
| **用户管理** | 管理系统用户 | ✅ 完成 |
| API | 接口文档 | 🚧 进行中 |

列幅がバラバラで、見づらいです。手動で調整?AIが新しいテーブルを生成するたびに調整するのは、あまりに面倒です。

いつ使うか

  • AIがMarkdownテーブルを生成したので、もっときれいにしたい
  • OpenCodeの非表示モード(Concealment Mode)を有効にしているが、テーブルの整列がいつも問題になる
  • 手動でテーブルの列幅を調整するのが面倒

コアアイデア

このプラグインの動作原理はとてもシンプルです:

AIがテキストを生成 → プラグインがテーブルを検出 → 構造を検証 → フォーマット → 美化されたテキストを返す

OpenCodeの experimental.text.complete フックにマウントされており、AIがテキストを生成するたびに自動的に処理します。手動でトリガーする必要はなく、完全に意識しません。

8つのコア機能

1. 自動テーブルフォーマット

プラグインはAIが生成したテキスト内のMarkdownテーブルを自動的に検出し、列幅を統一してテーブルを整列美しくします。

フォーマット前

markdown
| 名称 | 描述 | 状态 |
|--- | --- | ---|
| **用户管理** | 管理系统用户 | ✅ 完成 |
| API | 接口文档 | 🚧 进行中 |

フォーマット後

markdown
| 名称         | 描述         | 状态       |
|--- | --- | ---|
| **用户管理** | 管理系统用户 | ✅ 完成    |
| API          | 接口文档     | 🚧 进行中  |

トリガー条件

プラグインは experimental.text.complete フックにマウントされており、AIがテキストを生成した後に自動的にトリガーされます。手動操作は不要です。

2. 非表示モード互換

OpenCodeはデフォルトで非表示モード(Concealment Mode)を有効にしており、Markdown記号(***~~ など)を非表示にします。

通常のテーブルフォーマットツールはこれを考慮せず、幅を計算する際に ** も含めて計算するため、整列がずれます。

このプラグインは非表示モード向けに最適化されています:

  • 幅を計算する際、**太字***斜体*~~取り消し線~~ などの記号を剥離
  • 出力時は元のMarkdown構文を保持
  • 最終的な効果:非表示モードでテーブルが完璧に整列
技術詳細:幅計算ロジック
typescript
// Markdown記号を剥離(幅計算用)
visualText = visualText
  .replace(/\*\*\*(.+?)\*\*\*/g, "$1") // ***太斜体*** → テキスト
  .replace(/\*\*(.+?)\*\*/g, "$1")     // **太字** → 太字
  .replace(/\*(.+?)\*/g, "$1")         // *斜体* → 斜体
  .replace(/~~(.+?)~~/g, "$1")         // ~~取り消し線~~ → 取り消し線

ソースコード位置:index.ts:181-185

3. 整列サポート

Markdownテーブルの3つの整列方式をサポートします:

構文整列方式効果
--- または :---左揃えテキストを左に寄せる(2つの構文は同じ効果)
:---:中央揃えテキストを中央に配置
---:右揃えテキストを右に寄せる

markdown
| 左揃え | 中央揃え | 右揃え |
|--- | --- | ---|
| テキスト | テキスト | テキスト |

フォーマット後、各列は指定された方法で整列され、区切り行は整列方式に応じて再生成されます。

4. ネストされたMarkdown処理

テーブルセル内にはネストされたMarkdown構文が含まれる場合があります。例えば ***太斜体*** など。

プラグインは複数回の正規表現アルゴリズムを使用し、外側から内側へと逐次的に剥離します:

***太斜体*** → **太斜体** → *太斜体* → 太斜体

これにより、ネストが何層になっても幅計算は正確です。

5. コードブロック保護

インラインコード(バッククォートで囲まれたもの)内のMarkdown記号は、そのまま保持され、剥離されません。

例えば `**bold**`、ユーザーが見るのは bold という4文字ではなく、**bold** という8文字です。

プラグインはまずコードブロックの内容を抽出し、他の部分のMarkdown記号を剥離した後、コードブロックの内容を元に戻します。

技術詳細:コードブロック保護ロジック
typescript
// ステップ1:インラインコードを抽出して保護
const codeBlocks: string[] = []
let textWithPlaceholders = text.replace(/`(.+?)`/g, (match, content) => {
  codeBlocks.push(content)
  return `\x00CODE${codeBlocks.length - 1}\x00`
})

// ステップ2:コード以外の部分のMarkdown記号を剥離
// ...

// ステップ3:インラインコードの内容を復元
visualText = visualText.replace(/\x00CODE(\d+)\x00/g, (match, index) => {
  return codeBlocks[parseInt(index)]
})

ソースコード位置:index.ts:168-193

6. 境界ケース処理

プラグインは様々な境界ケースを正しく処理できます:

シーン処理方法
Emoji絵文字Bun.stringWidth を使用して表示幅を正しく計算
Unicode文字中国語、日本語などの等幅文字を正しく整列
空セル最小幅(3文字)までスペースで埋める
超長コンテンツ通常通り処理、切り捨てなし

7. サイレント操作

プラグインはバックグラウンドで静かに動作します:

  • ログ出力なし:コンソールに何も出力しません
  • エラーによる中断なし:フォーマットに失敗しても、AIの通常の出力に影響しません

フォーマット中にエラーが発生した場合、プラグインは元のテキストを保持し、末尾にHTMLコメントを追加します:

markdown
<!-- table formatting failed: [エラー情報] -->

8. 検証フィードバック

プラグインはテーブル構造が有効かどうかを検証します。無効なテーブルはフォーマットされず、そのまま保持され、ヒントが追加されます:

markdown
<!-- table not formatted: invalid structure -->

有効なテーブルの要件

  • 少なくとも2行(区切り行を含む)
  • すべての行の列数が一致している
  • 区切り行が必要(形式:|---|---|

プラグインの境界

サポートされないシーン

  • HTMLテーブル:Markdownパイプテーブル(| ... |)のみ処理
  • 複数行セル<br> タグを含むセルはサポートしない
  • 区切り行なしテーブル|---|---| 区切り行が必要
  • ヘッダーなしテーブル:ヘッダー行が必要

チェックポイント

このレッスンを完了したら、以下の質問に答えられるはずです:

  • [ ] プラグインはどのように自動的にトリガーされますか?(答え:experimental.text.complete フック)
  • [ ] なぜ「非表示モード互換」が必要ですか?(答え:非表示モードはMarkdown記号を非表示にするため、幅計算に影響する)
  • [ ] インラインコード内のMarkdown記号は剥離されますか?(答え:いいえ、コード内のMarkdown記号は完全に保持されます)
  • [ ] 無効なテーブルはどう処理されますか?(答え:そのまま保持し、エラーコメントを追加)

このレッスンのまとめ

機能説明
自動フォーマットAIがテキストを生成した後に自動的にトリガー、手動操作不要
非表示モード互換Markdown記号が非表示になった後の表示幅を正しく計算
整列サポート左揃え、中央揃え、右揃え
ネストされたMarkdown複数回の正規表現剥離、ネスト構文をサポート
コードブロック保護インラインコード内の記号はそのまま保持
境界ケースEmoji、Unicode、空セル、超長コンテンツ
サイレント操作ログなし、エラーによる中断なし
検証フィードバック無効なテーブルにエラーコメントを追加

次のレッスンの予告

次のレッスンでは 非表示モードの原理 を深掘りします。

学べること:

  • OpenCode非表示モードの動作原理
  • プラグインが表示幅を正しく計算する方法
  • Bun.stringWidth の役割

付録:ソースコード参照

クリックしてソースコードの場所を表示

更新日時:2026-01-26

機能ファイルパス行番号
プラグインエントリindex.ts9-23
テーブル検出index.ts58-61
テーブル検証index.ts70-88
幅計算(非表示モード)index.ts161-196
整列方式解析index.ts141-149
コードブロック保護index.ts168-173

重要な定数

  • colWidths[col] = 3:列の最小幅は3文字(index.ts:115

重要な関数

  • formatMarkdownTables():メイン処理関数、テキスト内のすべてのテーブルをフォーマット
  • getStringWidth():文字列の表示幅を計算、Markdown記号を剥離
  • isValidTable():テーブル構造が有効か検証