- Início
- Construtor de docs
- Sistema de Placeholders
Sistema de Placeholders
O sistema de placeholders permite que os leitores personalizem endereços IP, ASNs e outros valores específicos de implantação ao longo da documentação. Os autores escrevem tokens em seus arquivos Markdown; o navegador os substitui por valores fornecidos pelo usuário em tempo de execução.
Formato dos Tokens
Seção intitulada “Formato dos Tokens”Os tokens seguem o padrão regex:
x([A-Z][A-Z0-9_]+)xUm token começa e termina com um x minúsculo e contém um identificador em maiúsculas. Por exemplo, xCUSTOMER_ASNx referencia o placeholder CUSTOMER_ASN.
O regex é definido em src/scripts/placeholder-dom.ts:
const PH_REGEX = /x([A-Z][A-Z0-9_]+)x/g;Definições de Placeholders
Seção intitulada “Definições de Placeholders”Todos os placeholders são declarados em src/data/placeholders.json. Cada entrada possui o seguinte formato:
{ "CUSTOMER_ASN": { "type": "text", "default": "64496", "description": "Your public ASN (registered with ARIN/RIR)" }}| Campo | Obrigatório | Descrição |
|---|---|---|
type | sim | "text" para entrada de texto livre, "dropdown" para menus de seleção |
default | sim | Valor inicial exibido antes de o leitor alterar qualquer coisa |
description | sim | Rótulo exibido no formulário |
options | apenas para dropdown | Array de valores permitidos |
Gerenciamento de Estado
Seção intitulada “Gerenciamento de Estado”src/lib/placeholder-store.ts gerencia todo o estado dos placeholders.
Armazenamento
Seção intitulada “Armazenamento”Os valores são persistidos no localStorage sob a chave f5xc-placeholders. O store expõe quatro funções:
| Função | Propósito |
|---|---|
getDefaults() | Retorna um mapa de cada chave de placeholder para seu valor default do JSON |
loadValues() | Lê do localStorage, recorre a getDefaults() como fallback |
saveValues(values) | Grava o mapa atual no localStorage |
clearValues() | Remove a entrada do localStorage |
Grupos de Campos
Seção intitulada “Grupos de Campos”FIELD_GROUPS organiza as chaves dos placeholders em seções rotuladas para a interface do formulário:
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'] }, // ... mais grupos];Valores Computados
Seção intitulada “Valores Computados”Alguns valores são derivados da entrada do usuário em vez de inseridos diretamente. getComputedValues() calcula esses valores a partir de tabelas de consulta:
const cidrToMask: Record<string, string> = { '/24 (256 IPs)': '255.255.255.0', '/23 (512 IPs)': '255.255.254.0', // ...};Dois placeholders computados são produzidos:
| Chave Computada | Derivado De | Exemplo |
|---|---|---|
PROTECTED_MASK_V4 | PROTECTED_CIDR_V4 via consulta em cidrToMask | 255.255.255.0 |
PROTECTED_PREFIX_V4 | PROTECTED_NET_V4 + PROTECTED_CIDR_V4 via cidrToShort | 192.0.2.0/24 |
getAllValues() mescla os valores inseridos pelo usuário com os valores computados, fornecendo um mapa completo para substituição.
Emissão de Eventos
Seção intitulada “Emissão de Eventos”emitChange() despacha um CustomEvent placeholder-change no document com o mapa completo de valores como detail:
export function emitChange(values: Record<string, string>) { document.dispatchEvent( new CustomEvent('placeholder-change', { detail: getAllValues(values) }), );}Este evento aciona tanto as atualizações dos spans no DOM quanto a re-renderização dos diagramas Mermaid.
Componente React do Formulário
Seção intitulada “Componente React do Formulário”src/components/PlaceholderForm.tsx fornece a interface de edição.
- Estado:
useStateinicializado a partir deloadValues() - Na montagem:
useEffectchamaemitChange()para acionar a substituição inicial no DOM - handleChange: Atualiza o estado do React, chama
saveValues()eemitChange() - handleReset: Chama
clearValues(), redefine o estado paragetDefaults(), emite a mudança - Renderização: Itera sobre
FIELD_GROUPS, renderizando um<fieldset>por grupo. Cada chave recebe um<input>(tipo text) ou<select>(tipo dropdown) - Layout: O formulário é envolvido em um elemento
<details>, recolhido por padrão
Wrapper Astro
Seção intitulada “Wrapper Astro”src/components/PlaceholderFormWrapper.astro conecta o componente React à página Astro:
<PlaceholderForm client:only="react" />
<script> import '../scripts/placeholder-dom.ts';</script>client:only="react" instrui o Astro a hidratar o componente puramente no cliente (sem SSR). A tag <script> importa o DOM walker para que ele seja executado em toda página que inclua este wrapper.
O wrapper também injeta CSS global para estilização do formulário (.ph-form-wrapper, .ph-grid, .ph-value, etc.).
DOM Walker
Seção intitulada “DOM Walker”src/scripts/placeholder-dom.ts gerencia a substituição de tokens no lado do cliente.
Caminhada Inicial
Seção intitulada “Caminhada Inicial”No carregamento da página, init() é executado:
- Seleciona
.sl-markdown-contentcomo raiz (recorre adocument.bodycomo fallback) - Chama
walkTextNodes(root, values)que utilizadocument.createTreeWalkercomNodeFilter.SHOW_TEXT - Para cada nó de texto que corresponda ao regex do token, divide-o em um fragmento de documento contendo nós de texto simples e elementos
<span data-ph="KEY" class="ph-value"> - Substitui o nó de texto original pelo fragmento
Após a caminhada, o DOM contém spans com atributos data-ph em vez de tokens brutos.
Atualizações Subsequentes
Seção intitulada “Atualizações Subsequentes”Quando o formulário emite um evento placeholder-change, updateSpans() é executado:
document.querySelectorAll<HTMLSpanElement>('span[data-ph]').forEach((span) => { const name = span.getAttribute('data-ph')!; if (values[name] !== undefined) { span.textContent = values[name]; }});Isso evita percorrer a árvore novamente — atualiza diretamente o conteúdo de texto dos spans.
Listeners de Eventos
Seção intitulada “Listeners de Eventos”O script registra dois listeners:
| Evento | Handler | Propósito |
|---|---|---|
placeholder-change | handleChange | Atualiza os spans e re-renderiza os diagramas Mermaid |
astro:page-load | init | Percorre novamente o DOM após a navegação client-side do Astro |
Como Fazer: Adicionar um Novo Placeholder
Seção intitulada “Como Fazer: Adicionar um Novo Placeholder”-
Adicione a entrada no JSON em
src/data/placeholders.json:"MY_NEW_VALUE": {"type": "text","default": "example","description": "Description shown in the form"} -
Adicione a chave a um grupo de campos em
src/lib/placeholder-store.ts. Adicione-a ao arraykeysde um grupo existente ou crie um novo grupo emFIELD_GROUPS. -
Use o token no conteúdo: Escreva
xMY_NEW_VALUExem qualquer arquivo.mdx. O DOM walker o substituirá em tempo de execução.
Como Fazer: Adicionar um Valor Computado
Seção intitulada “Como Fazer: Adicionar um Valor Computado”Valores computados são derivados de outros placeholders. Para adicionar um:
-
Adicione uma tabela de consulta (se necessário) em
src/lib/placeholder-store.ts, seguindo o padrão decidrToMask. -
Estenda
getComputedValues()para incluir a nova chave derivada:export function getComputedValues(values: Record<string, string>): Record<string, string> {// ... lógica existentereturn {PROTECTED_MASK_V4: mask,PROTECTED_PREFIX_V4: `${net}${short}`,MY_COMPUTED: derivedValue, // adicione aqui};} -
Use
xMY_COMPUTEDxno conteúdo como qualquer outro token. Valores computados não precisam de uma entrada emplaceholders.jsonnem de um grupo de campos — eles são invisíveis para o formulário.