Skip to content

Rendering Pipeline ja

Hermes Agent edited this page Oct 1, 2026 · 1 revision

レンダリングパイプライン

English | 中文 | 日本語 | 한국어 | Español | Português | Русский

アシスタントバブルのための Markdown → 信頼できる HTML パイプラインは lib/sidepanel/render.js にある。処理順序そのものが前提条件:

  1. fixCjkEmphasisSpacing(CJK 隣接 ** パッチ — 文字クラスは marked の flanking 規則を意図的にミラーする: 句読点 = \p{P}∪\p{S}、隣接文字 = 任意の文字/数字)
  2. <think> ブロックを抽出 → プレースホルダへ
  3. ブロック数式 $$…$$ / \[…\] を抽出
  4. インライン数式 $…$ / \(…\) を抽出 — ガードが 2 つ:
    • markdown のエスケープ \\ と \$ を先にそのまま消費する(\$8K はリテラルのドル記号 — 2026-09-30 の MRR 表レポート);
    • インライン $ は Pandoc のデリミタ規則に従う: 開き/閉じは密着(タイト)であり、数字が続く閉じは拒否される(从**$8K**、**$20K** で素の $ 同士が KaTeX にペアリングされ、* が ∗ として描画されたことがある — 2026-10-01 レポート)。拒否された候補はそのまま marked へ返す。
  5. marked.parse → 6. DOMPurify → 7. KaTeX ワーカーで一括描画 + 復元(サニタイズの「後」。MathML 属性が DOMPurify に触れないように) → 8. think 折りたたみを復元。

ストリーミング: ブロックコミット(ADR-0011)

  • renderStreamingSafe(同期)は各フレームで末尾だけを処理する。完了した markdown ブロックは 1 回だけコミットされ(findStreamingBlockBoundary: 空行境界、フェンスの外、次行はリスト項目でない)、開いたままの末尾だけが再パースされる — O(n²) が O(n) になる。開いたフェンスは高速パスを通る(textContent 経由の <pre><code>、marked 呼び出しゼロ)。
  • リビールペーサーはベンダー入りの markstream-core(makeStreamRenderer はクロージャを返す。付け替える前に .destroy() を呼ぶ)。DONE は renderSafe で全文を再描画し(KaTeX + 最終 think ブロック)、ストリーミング近似の揺れを修正する。
  • 履歴は遅延描画: IntersectionObserver がスクロールポートに近づいたバブルをアップグレードする。content-visibility:auto は .cv-settled の下(double-rAF)でのみ — 初期レイアウト/スクロール中は決して使わない。
  • KaTeX オフロード: katex-threshold.js がワーカーか同期かを判断する。ワーカーはメッセージ単位でバッチ化し、キャッシュし、失敗時は同期へフォールバックする。

6 つのフェンス型レンダラ(```lang → ライブ描画への差し替え、ボタンなし)

フェンス レンダラ ベンダー 備考
```mermaid renderMermaid mermaid securityLevel:'loose'(foreignObject 内の KaTeX)+ sanitizeMermaidSvg(ロードベアリングなセキュリティ)。パース失敗時は AI 修復カード(REPAIR_MERMAID)
```echarts renderEcharts echarts モデルが自分の backgroundColor を名指さない限り、内蔵 'dark' テーマ + 透明キャンバス
```markmap renderMarkmap markmap lib+view Markmap.create() の前に pre.replaceWith(wrapper)(レイアウトがテキストを測定するため)。mm.rescale() は「相対」乗数 — ズームは _markmapZoomBy の絶対値変換を通す
```smiles renderSmiles RDKit MinimalLib WASM get_mol/get_rxn。RDKit が検証器も兼ねる(化学的に不可能な入力 → 明示的なエラー注記、素のブロックは保持)。記述子行(MW/logP/TPSA…)。ダークモードはストロークを描き直すが CPK のヘテロ原子色は「保持」する(化学的セマンティクス — CSS 反転は絶対にしない)
```pdb renderPdb Mol*(RAW コピーの IIFE) parsePdbBlock が分類: RCSB ID / AlphaFold AF-…-F1(現行モデルを API で解決)/ インライン座標。表現プリセットは必ず representationPreset に乗せる。ライブビューアは追跡され破棄される(ブラウザは約 16 WebGL コンテキストで上限)
```dot renderDot @viz-js/viz(base64 インライン WASM) デフォルト黒インクの再マップ + コントラスト救済。無効な DOT → エラー注記 + 素のコード保持(AI 修復なし)。モデル契約: ID [label="…"] のみ

描画契約(モデルに教え込む出力フォーマット)のテキストソースは 1 つだけ: lib/prompt-assembly.js の CAPABILITY_HINTS_ENTRIES。CAPABILITY_HINTS(LLM/Hermes のシステムチャネル)と AGENT_RENDER_HINT(エージェントの最初のターン)は、どちらもそれを組み立てたもの。手書きミラーの再発は許されない(かつての ```nn ミラーは 1 日アップデートを取り逃した)。

ベンダー読み込みと CSP(ADR-0008 / セキュリティモデル参照)

  • 図ベンダーは、フェンスが実際に見られたときにだけ遅延読み込み+プリウォームする(wantsChartVendors のスニフが 1 回限りのゲートの後ろに置かれる)— 図なしのセッションは約 7MB のパースを払わない。
  • Mol の dist は esbuild を通さない*(RAW コピーの既製 IIFE)。Mol*/RDKit の embind グルーには、build.mjs がコピー時に CSP パッチを当てる(手書きインボーカが new Function を置き換え、先行初期化だった h264 は遅延化)— パッチ正規表現は安定した文字列にアンカーし、molstar のアップグレードでマッチしなくなったらビルドが例外で落ちる。
  • ベンダー交換後の検証ゲートは実拡張でのロード(launchPersistentContext --load-extension、xvfb): dev-preview は eval を許す素の http ページであり、CSP 違反を捕捉できない(2026-09-30 の教訓)。

破棄

_chartObservers(ResizeObserver 登録簿)/ _renderDisposers(要素毎)/ disposeMolstarViewers() は、バブル削除・履歴再描画・履歴全消去の前に必ず走る。古典的なリーク症状は、切り離された WebGL コンテキストが描画し続けること(ブラウザは約 16 コンテキストで上限)。


権威版: Rendering-Pipeline(英語) / Rendering-Pipeline-zh(中文) — AI による初翻スナップショット、同期日 2026-10-01。

Clone this wiki locally