lightweight-charts-plugin-authoring について
lightweight-charts-plugin-authoringは、Lightweight Charts™のプラグイン開発向けスキルです。プラグイン種別の選択、ローカルAPIの確認、雛形作成、参考実装、検証の手順を案内します。
主な機能
- 01プラグイン種別の選択ガイド
- 02ローカル型定義を使ったAPI確認
- 03ウィザードによる雛形作成
- 04ツールキットと参考実装の案内
- 05段階的なビルドとテスト手順
活用シーン
- 01カスタムシリーズやプリミティブの設計
- 02実装前の利用可能なAPIの確認
- 03プラグインの雛形作成と検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ tradingview/ lightweight-charts --skill lightweight-charts-plugin-authoringインストール後、Claude Code で/lightweight-charts-plugin-authoringを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/official-plugins.mdpackage-contract.mdtoolkit.md詳細
Lightweight Charts™ プラグインの作成
このスキルでは、プラグインの 作成 について説明します。チャート自体の使い方(シリーズ、スケール、マーカー、データ、ラッパー)に関する質問には、関連する lightweight-charts スキルを使用してください。この2つのスキルは、あわせてインストールすることを想定しています。
現在の場所とソースの場所
このスキルは2つの場所で使用されます。同じ質問でも、場所によって答えが異なります。調べる前に、どちらにいるかを確認してください。
# upstream checkout of lightweight-charts itself?
test -f pnpm-workspace.yaml && test -d packages/lwc-toolkit && echo upstream || echo "a plugin project or other repo"
プラグインプロジェクトまたはその他のリポジトリの場合(一般的なケース):
| 調べたいもの | 場所 |
|---|---|
| ライブラリの API | node_modules/lightweight-charts/dist/typings.d.ts。インストールされていない場合は、リリース済みの型定義が https://tradingview.github.io/lightweight-charts/lightweight-charts.d.ts で公開されています |
| ツールキットの API | node_modules/@tradingview/lwc-toolkit/dist/<module>.d.ts。.d.ts にはドキュメントコメントが含まれているため、ドキュメントとして読むことができます |
| リファレンスプラグインのソース | node_modules にはありません(パッケージには dist/ のみが含まれます)。GitHub から取得してください:https://raw.githubusercontent.com/tradingview/lightweight-charts/master/packages/lwc-plugin-<name>/src/<file>。または一度クローンして、ローカルで読んでください:git clone --depth 1 https://github.com/tradingview/lightweight-charts /tmp/lightweight-charts |
| ドキュメント | 各ドキュメントページの URL に .md を追加すると、Markdown 形式で取得できます。例:https://tradingview.github.io/lightweight-charts/docs/plugins/custom_series.md。すべてのページは https://tradingview.github.io/lightweight-charts/llms.txt に一覧されており、隣にある docs_map.md には各ページの見出しも記載されています |
上流リポジトリのチェックアウト内の場合: ライブラリは dist/typings.d.ts(または src/)、ツールキットは packages/lwc-toolkit/src/、プラグインは packages/lwc-plugin-*/src/、ドキュメントは website/docs/plugins/*.md、概念実証用のサンプルは plugin-examples/ にあります。
# what version is installed, and does the hook I am about to rely on exist in it?
node -p "require('lightweight-charts/package.json').version"
rg -n "hitTest|conflationReducer|isHovered|ICustomSeriesPaneView|IPrimitivePaneRenderer" node_modules/lightweight-charts/dist/typings.d.ts
# the toolkit's custom-series surface
rg -n "export (declare )?(function|class|interface|type)" node_modules/@tradingview/lwc-toolkit/dist/custom-series/*.d.ts
# a reference implementation, without a checkout
curl -fsSL https://raw.githubusercontent.com/tradingview/lightweight-charts/master/packages/lwc-plugin-stacked-bars-series/src/renderer.ts
ローカルの型定義とドキュメントの内容が異なる場合は、ローカルの型定義を優先してください。ドキュメントには現在のリリースの内容が記載され、型定義にはユーザーが実際に使用している内容が記載されています。ファイルが見つからない場合は、何を確認できなかったかを明記してください。オプション、フック、ツールキットのエクスポートを決して捏造しないでください。想像上の API に対してコンパイルできるプラグインでは、ユーザーの型チェックに失敗します。また、チャートが無視するオプションに対してコンパイルできるプラグインでは、実行時に何も起きず、失敗が見過ごされます。
アイデアからプラグインの種類へ
最も重要な決定であり、最初に行うべきことです。アイデアがどのように見えるかではなく、アイデアの本質を考えてください。
| アイデアの内容… | 種類 | 理由 |
|---|---|---|
| シリーズ独自のデータを新しい方法で描画する(バー、バンド、積み上げ、ローソク足) | カスタムシリーズ | 独自のデータ、自動スケール、価格ライン、最終値、時間スケールとの連携が必要です |
| 1つのシリーズに関連付けられた装飾(ラベル、マーカー、バンド、データ上の描画ツール) | シリーズプリミティブ | そのシリーズの座標を読み取り、その範囲内でクリップされます |
| ペインに関連付けられた装飾(ウォーターマーク、凡例、タイトル、すべてのシリーズに重ねるオーバーレイ) | ペインプリミティブ | ペイン全体に広がり、特定のシリーズに依存せず存続します |
| DOM ベースのアクセシビリティ、ツールチップ、コントロールレイヤー | DOM オーバーレイを備えたペインプリミティブ | キャンバスは適切な描画領域ではありません。paneContentElement(pane) に追加してください |
基本的にはプリミティブを選んでください。カスタムシリーズは、より複雑な構成です。priceValueBuilder、isWhitespace、renderer、update を実装する必要があり、レンダラーにはシリーズのプロットデータが渡されます。アイデアの本質がシリーズである場合にのみ選択してください。ポインター処理が必要な描画ツールもプリミティブです。プリミティブ内で描画し、subscribeClick、subscribeCrosshairMove、座標変換 API を通じて反応します。
種類を選ぶ際は、ホバーとインタラクションも考慮してください。プリミティブには hitTest があり、チャートがクロスヘアイベントやクリックイベントでそれらを報告できます。カスタムシリーズでは、Lightweight Charts™ 5.2 以降でのみレンダラーに hitTest を実装できます。これにより、draw の isHovered 引数と hitTestData 引数でホバー状態が報告されます。
作業手順
次の順番で構築します。各ステップは、前のステップの間違いを見つけるのに最も手軽な場所です。
- コードを書く前に、データ項目とオプションを書き出します。データ項目によって
isWhitespace(どのフィールドがポイントを描画可能にするか)が決まり、オプションによってdefaultOptionsが決まります。README、型定義、デモのすべてがこれらを読み込むため、それぞれ独立したファイル(data.ts、options.ts)に記述します。 - スキャフォールドを作成します(下記)。空のファイルから始めないでください。
- オプションやインタラクションに触れる前に、スキャフォールドが生成するサンプルデータで、可視範囲だけを描画するレンダラーを動作させます。すべてを描画する、または何も描画しないレンダラーなら、まだ規模の小さいうちに修正しやすくなります。
applyOptionsを通じてオプションを接続し、requestUpdate()で再レンダリングします。デモページですべてのオプションが機能することを確認します。- カスタムシリーズの場合のみ:自動スケーリングと空白領域に対応します。価格スケールと最終値ラベルは
priceValueBuilderによって決まり、線を途切れさせる位置は空白領域によって決まります。どちらにも注意点があります(下のチェックリストを確認してください)。 - インタラクション:
hitTest、ホバー、ドラッグを実装します。描画とは分けてください。 - テスト、README、デモとプレビューページの順に進めます。各項目に含めるべき内容は、パッケージの契約書(
references/package-contract.md)に記載されています。
空の状態から始めず、スキャフォールドを作成する
npm create lwc-plugin@latest
ウィザードは対話形式です。まず、このスキルをインストールするか尋ねます(すでにインストール済みの場合や、ユーザーがウィザードを終了してあなたに引き継いだ場合は「いいえ」と答えてください)。次に、種類、名前、1文の説明、パッケージ名、クラス名、作成者、ライセンス、ライブラリの最小バージョン、タグ、ヒントコメントを残すかどうか、出力先フォルダーを尋ねます。誰かが実行する前に、ユーザーと相談して回答を決めてください。特に重要なのは、上記の種類の選択です。その後、環境からTTYを使ってプロンプトに自分で回答できない限り、ユーザーにターミナルでウィザードを実行してもらいます。ウィザードは次の内容を含むViteプロジェクトを作成します。
src/<entry>.ts— プラグインクラス(カスタムシリーズの場合はファクトリーも含む)。種類ごとに、src/options.ts、src/data.ts、レンダラーまたはビューのファイルも作成されますsrc/example/index.html+example.ts— 開発用デモ。pnpm devで配信されますdev、build、typecheck、check-packageスクリプト、lightweight-chartsのピア依存範囲、devDependencyとしての@tradingview/lwc-toolkit、カタログ用のlwcPluginブロックを含むpackage.json- カタログでレンダリングされる形式に整えられたREADME
「ヒントコメント」には「はい」と答えてください。テンプレートの各部分を説明する //* 行で、そうしないとウィザードによって削除されます。内容を読んでから、対応済みのコメントを削除してください。スキャフォールド独自のスクリプト(pnpm typecheck、pnpm build、pnpm check-package)を使ってビルドしてください。CIとリリースツールが実行するのはこれらのスクリプトです。
ツールキットを活用する
@tradingview/lwc-toolkit は、公式プラグインの構築に使われているもので、各サンプルで手作業によるコピーが繰り返されていたヘルパーを切り出したものです。これを使う目的は、コードの行数を減らすことではありません。ヘルパーには、微妙な間違いが起きやすいチャートの動作が実装されています。たとえば、特定のバー間隔で組み込みのローソク足が使う正確な幅、あらゆるデバイスピクセル比でピクセル単位まで正確な線の位置、LineStyle の破線パターン、コンフレーションによるバーの論理的なストライドの変化などです。各ヘルパーはサブパスからインポートしてください。
import { CustomSeriesRendererBase } from '@tradingview/lwc-toolkit/custom-series/renderer-base';
import { visibleSegments, extendRange, barCoordinate } from '@tradingview/lwc-toolkit/custom-series/visible-bars';
import { PluginBase } from '@tradingview/lwc-toolkit/plugin-base';
よくあるケースでは、「実現したいこと」から対応するモジュールを選べます。それ以外については、references/toolkit.md に各 API の形式と、それを使用している公式プラグインを記載しています。
| 必要なこと | 使用するもの |
|---|---|
| データや範囲のガードを作り直さずにカスタムシリーズレンダラーを書く | custom-series/renderer-base — CustomSeriesRendererBase を拡張し、drawImpl(scope, args) を実装します |
チャートの参照と requestUpdate() が処理されるシリーズまたはペインプリミティブを作成する | plugin-base(PluginBase)/pane-plugin-base(PanePluginBase) |
| 画面に表示されている部分だけを描画し、線をペインの端まで延ばす | custom-series/visible-bars — forEachVisibleBar、mapVisibleBars、extendRange、barCoordinate |
| 他のシリーズのタイムスタンプではなく、明示的な空白で線を途切れさせる | createWhitespaceSeries(custom-series/options-aware-series)+ visibleSegments |
priceValueBuilder 内でオプションを読み取る(オプションに追従する自動スケール) | プロット値に影響するオプション名を指定した createOptionsAwareSeries |
| 積み上げ値のバンド境界と自動スケールの極値を扱う | custom-series/stacking — stackLevels、stackedPlotValues |
| 組み込みと同じ幅で、ピクセルに整列した棒、ローソク足、または線を描画する | dimensions/* — calculateColumnPositions、candlestickWidth、positionsLine、positionsBox |
| 内側に境界線のある角丸長方形を描画する | canvas/round-rect |
| ポリライン、ステップ線、2 本の線の間の領域、色が変化する線を描画する | custom-series/line-paths |
| 価格軸または時間軸にラベルを表示する | axis-label-view(AxisLabelView) |
| ペイン内に DOM オーバーレイを表示する | dom/pane-element(paneContentElement) |
小さなイベント、またはタイムスタンプや表示文字列としての Time を扱う | delegate、time |
スキャフォールドのテンプレートですでにツールキットのヘルパーをインポートしている場合は、そのまま使用してください。テンプレートは、その種類のプラグインとして最小限かつ正しい構成になっています。
リファレンス実装を読む
公式パッケージは標準的な例です。メンテナンスされ、テストされ、公開され、このスキルの説明どおりに構築されています。設計する前に、自分のアイデアに最も近いものを読んでください。「ホバー中のアイテムを取得するには?」「積み上げを自動スケーリングするには?」といった疑問のほとんどは、そのいずれかにあるファイルで解決できます。上流リポジトリでは packages/lwc-plugin-*/src/ にあります。それ以外のリポジトリでは、公開済みの @tradingview/lwc-plugin-* パッケージから README と dist/*.d.ts を取得できますが、ソースは含まれていません。ソースは GitHub から取得してください(上記の raw URL または shallow clone を参照)。各プラグインは少数のファイルで構成されています。
| 作成するもの… | 読むもの |
|---|---|
| あらゆるカスタムシリーズ | stacked-bars-series(最もシンプルで完全なもの)、次に pretty-histogram-series |
| 1 点あたりに複数の値を持つシリーズ | stacked-area-series、stacked-bars-series |
| ギャップで途切れる、または融合に耐える必要のあるライン/エリア | hlc-area-series、brushable-area-series |
| 独自のポインター操作を持つシリーズ | brushable-area-series(BrushableAreaInteraction) |
| 組み込みシリーズの代替 | rounded-candles-series(ローソク足のオプションと幅に合わせたもの) |
| ピクセル単位の高さが固定されたオーバーレイシリーズ | dual-range-histogram-series(scaleMode、keepPixelSeriesInView) |
| 軸ラベルとドラッグ操作を持つシリーズプリミティブ | vertical-line |
| シリーズまたはペインの背後に置く画像や装飾 | image-watermark(シリーズプリミティブとペインプリミティブの両方) |
| ペインの端または隅に固定するテキストラベル | anchored-text(1 つのコア上に構築された、最小構成のシリーズとペインのペア) |
| ペイン上の DOM レイヤー、複数ペインのライフサイクル | accessibility |
references/official-plugins.md では、それぞれが実演する内容を詳しく説明しています。
リポジトリ内の plugin-examples/src/plugins/
(https://github.com/tradingview/lightweight-charts/tree/master/plugin-examples)
には、ツールチップ、描画ツール、セッションのハイライト表示、ヒートマップなど、さらに多くの概念実証プラグインがあります。幅広い事例やアイデアを得るには有用ですが、公開済みの出発点ではなく、準拠すべき標準でもありません。正式採用されたプラグインのフォルダーは、ここではパッケージへのリダイレクトになっています。
この順番でドキュメントを読む
HTML をスクレイピングするのではなく、URL に .md を付けてページを Markdown として取得してください。https://tradingview.github.io/lightweight-charts/docs/plugins/<page>.md を参照してください。
https://tradingview.github.io/lightweight-charts/llms.txt はすべてのページのインデックスであり、docs_map.md は見出し付きの同じインデックスです。また、隣にある lightweight-charts.d.ts は公開済みの型定義です。
intro— 3 種類のプラグインと、それらの取り付け方。series-primitivesまたはpane-primitives— 使用する種類のビュー/レンダラー/ライフサイクルの契約。attached/detached、updateAllViews、paneViews、priceAxisViews、timeAxisViews、hitTest。custom_series—ICustomSeriesPaneView:priceValueBuilder、isWhitespace、renderer、update、defaultOptions、5.1 の融合フック、5.2 のhitTest。canvas-rendering-target— 描画対象のCanvasRenderingTarget2Dと、2 つの座標空間。pixel-perfect-rendering— 幅と位置にdimensions/*ヘルパーを使う理由。
ページで説明されていない内容は、生成された API リファレンスではなく型定義を読んでください。型定義は完全であり、コードのコンパイル対象となるのは .d.ts です。ドキュメントには現行リリースの内容が記載されていますが、peer range がそれより前のバージョンから始まる場合、実際に利用できるのはインストール済みバージョンの型定義です。
正確性チェックリスト
ここに挙げる項目はどれも、公開済みのプラグインで問題になったものです。理由も記載しているのは、従来のケースで避けるだけでなく、新しい形で現れたときにも見分けられるようにするためです。
描画
- くっきり表示する必要があるもの(線、バー、境界線)は
useBitmapCoordinateSpaceで描画し、幅をhorizontalPixelRatio/verticalPixelRatioでスケーリングしてください。テキストやレイアウトには、CSS ピクセルを使うuseMediaCoordinateSpaceを使用してください。両者を混在させると、HiDPI ではぼやけます。dimensions/*ヘルパーがビットマップ座標を返すのも、まさにこのためです。 CanvasRenderingTarget2Dはライブラリではなくfancy-canvasの型です。カスタムシリーズがこの型に依存せずに済むよう、ツールキットはcustom-series/renderer-baseからこの型を再エクスポートしています。- コンテキストに設定したものは必ず元に戻してください(
save/restoreを使用するか、globalAlpha、lineCap、ダッシュパターンをリセットしてください)。次のレンダラーも同じコンテキストに描画します。 priceToCoordinateがnullを返す場合、その価格はスケール範囲外です。その点をスキップするか、そこで線を分割してください。NaNを使って描画すると、パス全体が失われます。
表示範囲と座標
data.visibleRangeの範囲だけを描画してください。シリーズには 100 万個の点が含まれることもあります。線やエリアではextendRangeを使って範囲を 1 本分広げ、最初と最後のセグメントがペインの端で途切れず、外にはみ出すようにしてください。- 表示範囲外のバーは、古い、または欠落した
xを持つ場合があります。表示範囲内のアンカーを使い、barCoordinate(bar, anchor, barSpacing)で座標を再構築してください。bar.timeは論理インデックスであり、間隔はインデックスごとに適用されます。 bar.time(論理インデックス)と配列インデックスiは、別のシリーズの開始位置が早い場合やデータにギャップがある場合に異なります。インデックスごとのオプション参照やブラシ範囲には、論理インデックスを使用します。
カスタムシリーズの詳細
priceValueBuilderは、チャートが自動スケーリングに使用するプロット値を返し、最後の値を現在値(価格ライン、最終値ラベル)として扱います。スタックの場合は[min, max, total](stackedPlotValues)、バンドの場合は極値、単一の値の場合は[value]を返してください。- この関数は
setDataの実行時、レンダリングより前に呼び出されるため、通常のビューにはまだオプションがありません。チャートがまだupdateを呼び出していないため、初回のデータ取り込みではpercent、base、scaleModeは無視されます。createOptionsAwareSeriesを使うと、ビルダーに最新のオプションを取得するゲッターが渡され、名前付きオプションの変更時にデータが再取り込みされます。そのため、公式シリーズではサポート対象のエントリーポイントとしてcreateXSeriesファクトリーを提供し、クラスは組み合わせて使えるようエクスポートしています。 - ホストはカスタムレンダラーに空白データを渡しません。バーは単にギャップを飛ばし、論理インデックスの飛びは別のシリーズのタイムスタンプである可能性もあります。線を分割するのは、受け入れた入力におけるシリーズ固有の空白データだけにしてください。
createWhitespaceSeriesはGapCheckを提供します。minGapとしてgetConflationFactor(data)を渡すと、1 つのコンフレーションバケットより狭い空白データの連続部分が吸収され、各バケットが単一点のセグメントに分割されるのを防げます。 conflationReducerとconflationFactorは 5.1 から、レンダラーのhitTestは 5.2 から利用できます。これにより、カスタムシリーズのホバリングをisHovered/hitTestData(5.0 から利用できるdraw引数)で通知するシリーズのヒットテストが導入されました。これらはオプションの追加機能として実装し、必要でない限りピア範囲は^5.0.0のままにして、必要な場合は README に記載してください。- 同じ項目がホバーされ続けている間、
hitTestは同じhitTestDataオブジェクトを返す必要があります。チャートは参照で比較し、新しいオブジェクトが返されると、ポインターを動かすたびにペインを再描画するためです。 conflationReducer(a, b)は、2 つのデータ項目のマージとして意味のある、自分の型のデータ項目を返す必要があります。スタックでは合計、OHLC では高値/安値/終値、レートでは後の値を使います。
プリミティブの詳細
- チャートからは確認できない変更(オプション、新しい時刻、デコード済みの画像)があった後は、
requestUpdate()を呼び出してください。チャートは状態をポーリングしません。 detached()では、attached()が行ったすべての処理を元に戻す必要があります。リスナー、DOM ノード、タイマー、読み込み中の画像をすべて解除してください。アタッチとデタッチのサイクルはよく発生します(React のエフェクト、ペインの並べ替え)。リークがあると、ゴースト描画や「disposed」エラーが発生します。- ペインプリミティブは、アタッチされたペインにのみ描画されます。コンストラクターに渡されたペインのインデックスはヒントにすぎず、誤っている場合があります。実際のペインは遅延して特定してください(最初の描画時の
context.canvasがそのペイン内にあります)。そして、インデックスではなく同一性で保持してください。ペインの追加、削除、移動に伴ってインデックスは変わります。 - DOM オーバーレイは
paneContentElement(pane)に追加し、オーバーレイのレイアウトがチャート自体のテーブルセルに依存しないようにしてください。
テスト
3 つの層があり、それぞれほかの層では検出できない問題を見つけます。公式パッケージには tests/ 以下にすべての層があり、スキャフォールドでは最初の層を設定します。
- ユニット(
tests/unit/*.spec.ts、node:test+chai):純粋関数をテストします。スタッキングの計算、オプションのマージ、データのパディング、ギャップの検出などが対象です。高速で、リポジトリのpnpm testから実行できます。 - グラフィックス(
tests/graphics/*.js):1 つの状態を描画するページです。CI ではスクリーンショットを前回のビルドと比較します。確認する価値のあるオプションごとに 1 ケースを用意し、空の表示範囲、スクロールで画面外に出た状態、空白の連続、コンフレーション、反転スケールなどのエッジケースも含めます。 - インタラクション(
tests/interactions/*.js):チャートを操作する非同期のbeforeInteractions(container)を備えたページです。期待どおりでない結果があればエラーをスローします。描画されたかどうかのピクセルサンプリング、DOM チェック、ヒットテストを行います。空白、更新、pop、ポインターの動作をテストするのはここです。
上流では、pnpm build:prod と pnpm --filter "@tradingview/lwc-plugin-*" build の後に、pnpm test、pnpm e2e:graphics:plugins、GREP="lwc-plugin-<name>/" pnpm e2e:interactions を実行してください。
公開とカタログ
上流で pnpm plugins:validate が成功するか、手動で同等の確認を行えば、プラグインを公開できます。具体的には、lwc-plugin-* という名前、publishConfig.access: public、lightweight-charts のピア依存関係の範囲、lightweight-charts-plugin キーワード、完全な lwcPlugin ブロック、## Installation(### npm タブと ### CDN タブを含む)および ## Usage のある README、さらに宣言されたデモページが必要です。スキャフォールドはこれらすべてを満たしています。ドキュメントサイトのプラグインカタログは README を表示し、パッケージからビルドしたプレビューページをフレーム内に表示します。references/package-contract.md には各フィールド、ページ、初回リリース時の変更履歴の慣例が記載されています(簡潔にまとめ、Added のリストを用意し、Fixed は含めません。まだ修正すべきものはないためです)。
回答の要件
プラグインについて回答するときは、次の要件を満たしてください。
- プラグインの種類を示し、その理由を 1 文で説明するか、もう一方の種類ではユーザーのアイデアの何が失われるかを説明してください。
- 回答の根拠とするツールキットのモジュールと公式プラグインを示してください。実装パターンを引用する前に、プラグインのファイルを読んでください。
- すべてのライブラリ名とツールキット名をローカルの型定義で確認してください。確認できなかったものがあれば、その旨を伝えてください。
- スキャフォールド独自のスクリプトで受け入れられるコードを作成してください。
pnpm typecheck、pnpm buildを通過し、pnpm devでデモページに表示される必要があります。 - 変更がオートスケール、空白、表示範囲、ホバーに関わる場合は、リグレッションを検出できたはずのテストを示し、そのテストを書いてください。