- ホーム
- ドキュメントビルダー
- プレースホルダーシステム
プレースホルダーシステム
プレースホルダーシステムにより、読者はドキュメント全体でIPアドレス、ASN、およびその他のデプロイ固有の値をカスタマイズできます。著者はMarkdownにトークンを記述し、ブラウザが実行時にそれらをユーザーが指定した値に置き換えます。
トークン形式
Section titled “トークン形式”トークンは以下の正規表現パターンに従います:
x([A-Z][A-Z0-9_]+)xトークンは小文字の x で始まり、小文字の x で終わり、大文字の識別子を含みます。例えば、xCUSTOMER_ASNx は CUSTOMER_ASN プレースホルダーを参照します。
正規表現は src/scripts/placeholder-dom.ts で定義されています:
const PH_REGEX = /x([A-Z][A-Z0-9_]+)x/g;プレースホルダー定義
Section titled “プレースホルダー定義”すべてのプレースホルダーは src/data/placeholders.json で宣言されています。各エントリは以下の形式を持ちます:
{ "CUSTOMER_ASN": { "type": "text", "default": "64496", "description": "Your public ASN (registered with ARIN/RIR)" }}| フィールド | 必須 | 説明 |
|---|---|---|
type | はい | 自由入力の場合は "text"、選択メニューの場合は "dropdown" |
default | はい | 読者が変更する前に表示される初期値 |
description | はい | フォームに表示されるラベル |
options | ドロップダウンの場合のみ | 許可される値の配列 |
src/lib/placeholder-store.ts がすべてのプレースホルダーの状態を管理します。
値は localStorage の f5xc-placeholders キーに永続化されます。ストアは4つの関数を公開しています:
| 関数 | 目的 |
|---|---|
getDefaults() | JSONからすべてのプレースホルダーキーとその default 値のマップを返します |
loadValues() | localStorageから読み取り、失敗した場合は getDefaults() にフォールバックします |
saveValues(values) | 現在のマップをlocalStorageに書き込みます |
clearValues() | localStorageのエントリを削除します |
フィールドグループ
Section titled “フィールドグループ”FIELD_GROUPS はフォームUIのラベル付きセクションにプレースホルダーキーを整理します:
export const FIELD_GROUPS: FieldGroup[] = [ { label: 'Data Center & Scrubbing Centers', keys: ['DC_NAME', 'CENTER_1', 'CENTER_2'] }, { label: 'Protected Prefixes', keys: ['PROTECTED_CIDR_V4', 'PROTECTED_NET_V4', ...] }, { label: 'BGP', keys: ['CUSTOMER_ASN', 'F5_XC_ASN', 'BGP_PASSWORD'] }, // ... その他のグループ];一部の値は直接入力されるのではなく、ユーザー入力から導出されます。getComputedValues() はルックアップテーブルからこれらを計算します:
const cidrToMask: Record<string, string> = { '/24 (256 IPs)': '255.255.255.0', '/23 (512 IPs)': '255.255.254.0', // ...};2つの算出プレースホルダーが生成されます:
| 算出キー | 導出元 | 例 |
|---|---|---|
PROTECTED_MASK_V4 | cidrToMask ルックアップによる PROTECTED_CIDR_V4 | 255.255.255.0 |
PROTECTED_PREFIX_V4 | PROTECTED_NET_V4 + cidrToShort による PROTECTED_CIDR_V4 | 192.0.2.0/24 |
getAllValues() はユーザー入力値と算出値をマージし、置換用の完全なマップを提供します。
イベントの発行
Section titled “イベントの発行”emitChange() は document 上で placeholder-change CustomEventをディスパッチし、完全な値マップを detail として含みます:
export function emitChange(values: Record<string, string>) { document.dispatchEvent( new CustomEvent('placeholder-change', { detail: getAllValues(values) }), );}このイベントは、DOMのspan更新とMermaidの再レンダリングの両方を駆動します。
Reactフォームコンポーネント
Section titled “Reactフォームコンポーネント”src/components/PlaceholderForm.tsx が編集UIを提供します。
- 状態:
loadValues()から初期化されたuseState - マウント時:
useEffectがemitChange()を呼び出して初回のDOM置換をトリガーします - handleChange: Reactの状態を更新し、
saveValues()とemitChange()を呼び出します - handleReset:
clearValues()を呼び出し、状態をgetDefaults()にリセットし、変更を発行します - レンダリング:
FIELD_GROUPSを反復し、グループごとに<fieldset>をレンダリングします。各キーは<input>(テキスト型)または<select>(ドロップダウン型)のいずれかを取得します - レイアウト: フォームは
<details>要素でラップされ、デフォルトでは折りたたまれています
Astroラッパー
Section titled “Astroラッパー”src/components/PlaceholderFormWrapper.astro がReactコンポーネントをAstroページに接続します:
<PlaceholderForm client:only="react" />
<script> import '../scripts/placeholder-dom.ts';</script>client:only="react" はAstroにコンポーネントを純粋にクライアント側でハイドレーションするよう指示します(SSRなし)。<script> タグはDOMウォーカーをインポートし、このラッパーを含むすべてのページで実行されるようにします。
ラッパーはフォームスタイリング用のグローバルCSS(.ph-form-wrapper、.ph-grid、.ph-value など)も挿入します。
DOMウォーカー
Section titled “DOMウォーカー”src/scripts/placeholder-dom.ts がクライアント側のトークン置換を処理します。
初回ウォーク
Section titled “初回ウォーク”ページ読み込み時に init() が実行されます:
.sl-markdown-contentをルートとして選択します(フォールバックとしてdocument.body)walkTextNodes(root, values)を呼び出し、NodeFilter.SHOW_TEXTを使用したdocument.createTreeWalkerを使用します- トークン正規表現に一致する各テキストノードについて、プレーンテキストノードと
<span data-ph="KEY" class="ph-value">要素のドキュメントフラグメントに分割します - 元のテキストノードをフラグメントで置き換えます
ウォーク後、DOMには生のトークンの代わりに data-ph 属性を持つspanが含まれます。
フォームが placeholder-change イベントを発行すると、updateSpans() が実行されます:
document.querySelectorAll<HTMLSpanElement>('span[data-ph]').forEach((span) => { const name = span.getAttribute('data-ph')!; if (values[name] !== undefined) { span.textContent = values[name]; }});これによりツリーの再ウォークを回避し、spanのテキストコンテンツを直接更新します。
イベントリスナー
Section titled “イベントリスナー”スクリプトは2つのリスナーを登録します:
| イベント | ハンドラー | 目的 |
|---|---|---|
placeholder-change | handleChange | spanを更新し、Mermaidダイアグラムを再レンダリングします |
astro:page-load | init | Astroクライアント側ナビゲーション後にDOMを再ウォークします |
手順:新しいプレースホルダーの追加
Section titled “手順:新しいプレースホルダーの追加”-
src/data/placeholders.jsonにJSONエントリを追加します:"MY_NEW_VALUE": {"type": "text","default": "example","description": "Description shown in the form"} -
src/lib/placeholder-store.tsでフィールドグループにキーを追加します。既存グループのkeys配列に追加するか、FIELD_GROUPSに新しいグループを作成します。 -
コンテンツでトークンを使用します:任意の
.mdxファイルにxMY_NEW_VALUExと記述します。DOMウォーカーが実行時にそれを置き換えます。
手順:算出値の追加
Section titled “手順:算出値の追加”算出値は他のプレースホルダーから導出されます。追加するには:
-
必要に応じて
src/lib/placeholder-store.tsにcidrToMaskのパターンに従ってルックアップテーブルを追加します。 -
getComputedValues()を拡張して新しい導出キーを含めます:export function getComputedValues(values: Record<string, string>): Record<string, string> {// ... 既存のロジックreturn {PROTECTED_MASK_V4: mask,PROTECTED_PREFIX_V4: `${net}${short}`,MY_COMPUTED: derivedValue, // ここに追加};} -
他のトークンと同様に、コンテンツで
xMY_COMPUTEDxを使用します。算出値はplaceholders.jsonのエントリやフィールドグループは不要です — フォームからは見えません。