- Inicio
- Constructor de docs
- Sistema de Marcadores de Posición
Sistema de Marcadores de Posición
El sistema de marcadores de posición permite a los lectores personalizar direcciones IP, ASNs y otros valores específicos de despliegue a lo largo de la documentación. Los autores escriben tokens en su Markdown; el navegador los reemplaza con valores proporcionados por el usuario en tiempo de ejecución.
Formato de Tokens
Sección titulada «Formato de Tokens»Los tokens siguen el patrón regex:
x([A-Z][A-Z0-9_]+)xUn token comienza y termina con una x minúscula y contiene un identificador en mayúsculas. Por ejemplo, xCUSTOMER_ASNx hace referencia al marcador de posición CUSTOMER_ASN.
La expresión regular está definida en src/scripts/placeholder-dom.ts:
const PH_REGEX = /x([A-Z][A-Z0-9_]+)x/g;Definiciones de Marcadores de Posición
Sección titulada «Definiciones de Marcadores de Posición»Todos los marcadores de posición se declaran en src/data/placeholders.json. Cada entrada tiene esta estructura:
{ "CUSTOMER_ASN": { "type": "text", "default": "64496", "description": "Your public ASN (registered with ARIN/RIR)" }}| Campo | Requerido | Descripción |
|---|---|---|
type | sí | "text" para entrada libre, "dropdown" para menús de selección |
default | sí | Valor inicial mostrado antes de que el lector realice cambios |
description | sí | Etiqueta mostrada en el formulario |
options | solo para dropdown | Array de valores permitidos |
Gestión de Estado
Sección titulada «Gestión de Estado»src/lib/placeholder-store.ts maneja todo el estado de los marcadores de posición.
Almacenamiento
Sección titulada «Almacenamiento»Los valores se persisten en localStorage bajo la clave f5xc-placeholders. El almacén expone cuatro funciones:
| Función | Propósito |
|---|---|
getDefaults() | Devuelve un mapa de cada clave de marcador de posición con su valor default del JSON |
loadValues() | Lee desde localStorage, recurre a getDefaults() como respaldo |
saveValues(values) | Escribe el mapa actual en localStorage |
clearValues() | Elimina la entrada de localStorage |
Grupos de Campos
Sección titulada «Grupos de Campos»FIELD_GROUPS organiza las claves de marcadores de posición en secciones etiquetadas para la interfaz del formulario:
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'] }, // ... más grupos];Valores Calculados
Sección titulada «Valores Calculados»Algunos valores se derivan de la entrada del usuario en lugar de ingresarse directamente. getComputedValues() los calcula a partir de tablas de búsqueda:
const cidrToMask: Record<string, string> = { '/24 (256 IPs)': '255.255.255.0', '/23 (512 IPs)': '255.255.254.0', // ...};Se producen dos marcadores de posición calculados:
| Clave Calculada | Derivado De | Ejemplo |
|---|---|---|
PROTECTED_MASK_V4 | PROTECTED_CIDR_V4 mediante búsqueda en cidrToMask | 255.255.255.0 |
PROTECTED_PREFIX_V4 | PROTECTED_NET_V4 + PROTECTED_CIDR_V4 mediante cidrToShort | 192.0.2.0/24 |
getAllValues() fusiona los valores ingresados por el usuario con los valores calculados, proporcionando un mapa completo para la sustitución.
Emisión de Eventos
Sección titulada «Emisión de Eventos»emitChange() despacha un CustomEvent placeholder-change en document con el mapa completo de valores como detail:
export function emitChange(values: Record<string, string>) { document.dispatchEvent( new CustomEvent('placeholder-change', { detail: getAllValues(values) }), );}Este evento impulsa tanto las actualizaciones de los spans en el DOM como el re-renderizado de Mermaid.
Componente React del Formulario
Sección titulada «Componente React del Formulario»src/components/PlaceholderForm.tsx proporciona la interfaz de edición.
- Estado:
useStateinicializado desdeloadValues() - Al montar:
useEffectllama aemitChange()para activar la sustitución inicial del DOM - handleChange: Actualiza el estado de React, llama a
saveValues()yemitChange() - handleReset: Llama a
clearValues(), restablece el estado agetDefaults(), emite el cambio - Renderizado: Itera
FIELD_GROUPS, renderizando un<fieldset>por grupo. Cada clave obtiene un<input>(tipo text) o un<select>(tipo dropdown) - Diseño: El formulario está envuelto en un elemento
<details>, colapsado por defecto
Envoltorio Astro
Sección titulada «Envoltorio Astro»src/components/PlaceholderFormWrapper.astro conecta el componente React con la página Astro:
<PlaceholderForm client:only="react" />
<script> import '../scripts/placeholder-dom.ts';</script>client:only="react" le indica a Astro que hidrate el componente puramente en el cliente (sin SSR). La etiqueta <script> importa el recorredor del DOM para que se ejecute en cada página que incluya este envoltorio.
El envoltorio también inyecta CSS global para el estilo del formulario (.ph-form-wrapper, .ph-grid, .ph-value, etc.).
Recorredor del DOM
Sección titulada «Recorredor del DOM»src/scripts/placeholder-dom.ts maneja el reemplazo de tokens del lado del cliente.
Recorrido Inicial
Sección titulada «Recorrido Inicial»Al cargar la página, init() se ejecuta:
- Selecciona
.sl-markdown-contentcomo raíz (recurre adocument.bodycomo respaldo) - Llama a
walkTextNodes(root, values)que utilizadocument.createTreeWalkerconNodeFilter.SHOW_TEXT - Para cada nodo de texto que coincida con la expresión regular del token, lo divide en un fragmento de documento con nodos de texto plano y elementos
<span data-ph="KEY" class="ph-value"> - Reemplaza el nodo de texto original con el fragmento
Después del recorrido, el DOM contiene spans con atributos data-ph en lugar de tokens sin procesar.
Actualizaciones Posteriores
Sección titulada «Actualizaciones Posteriores»Cuando el formulario emite un evento placeholder-change, updateSpans() se ejecuta:
document.querySelectorAll<HTMLSpanElement>('span[data-ph]').forEach((span) => { const name = span.getAttribute('data-ph')!; if (values[name] !== undefined) { span.textContent = values[name]; }});Esto evita recorrer el árbol nuevamente — actualiza directamente el contenido de texto del span.
Escuchadores de Eventos
Sección titulada «Escuchadores de Eventos»El script registra dos escuchadores:
| Evento | Manejador | Propósito |
|---|---|---|
placeholder-change | handleChange | Actualiza los spans y re-renderiza los diagramas Mermaid |
astro:page-load | init | Recorre el DOM nuevamente después de la navegación del lado del cliente de Astro |
Cómo: Agregar un Nuevo Marcador de Posición
Sección titulada «Cómo: Agregar un Nuevo Marcador de Posición»-
Agregar la entrada JSON en
src/data/placeholders.json:"MY_NEW_VALUE": {"type": "text","default": "example","description": "Description shown in the form"} -
Agregar la clave a un grupo de campos en
src/lib/placeholder-store.ts. Ya sea agregándola al arraykeysde un grupo existente o creando un nuevo grupo enFIELD_GROUPS. -
Usar el token en el contenido: Escriba
xMY_NEW_VALUExen cualquier archivo.mdx. El recorredor del DOM lo reemplazará en tiempo de ejecución.
Cómo: Agregar un Valor Calculado
Sección titulada «Cómo: Agregar un Valor Calculado»Los valores calculados se derivan de otros marcadores de posición. Para agregar uno:
-
Agregue una tabla de búsqueda (si es necesario) en
src/lib/placeholder-store.ts, siguiendo el patrón decidrToMask. -
Extienda
getComputedValues()para incluir la nueva clave 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, // agregar aquí};} -
Use
xMY_COMPUTEDxen el contenido como cualquier otro token. Los valores calculados no necesitan una entrada enplaceholders.jsonni un grupo de campos — son invisibles para el formulario.