FSWP Block Developer
Fundacional (siempre aplicado): fswp-developer/references/lean-coding.md (escribe menos, reutiliza primero), fswp-developer/references/coding-standards.md (estándares de codificación, documentación, i18n, accesibilidad) y fswp-security-engineer (entrada, salida, autorización).
Usa los bloques del núcleo primero; escribe un bloque personalizado solo cuando los bloques y patrones del núcleo no puedan expresar el requisito. Referencias oficiales: Enlaces del Manual del Editor de Bloques en fswp-developer/references/official-docs.md. Verifica la versión mínima de WordPress para cada API contra la versión mínima declarada del proyecto.
Anatomía
blocks/mi-bloque/
block.json nombre, título, categoría, atributos, soportes, render, editorScript, viewScriptModule, estilo
edit.js interfaz del editor (usa useBlockProps)
save.js marcado estático, u omitir para bloques dinámicos
render.php renderizado del servidor para bloques dinámicos
view.js comportamiento frontend (módulo)
style.scss / editor.scss
Registrar desde metadatos: register_block_type( __DIR__ . '/build/mi-bloque' ) en init (usa una función con nombre para el callback de init). Establece "apiVersion": 3 (actual desde WordPress 6.3) y agrega "$schema": "https://schemas.wp.org/trunk/block.json". Referencia campo por campo, verificada contra el Manual del Editor de Bloques: references/block-json.md.
Decisiones
| Pregunta | Elige |
|---|---|
| La salida depende solo de atributos guardados | Bloque Estático (save.js) |
| La salida depende de datos en vivo, debe cambiar sin volver a guardar, o contiene lógica | Bloque Dinámico (render.php); save devuelve null o solo InnerBlocks |
| Contenido anidado | InnerBlocks con allowedBlocks y template |
| Vincular un atributo a datos (metadatos de entrada, fuente personalizada) | API Block Bindings (register_block_bindings_source) cuando la versión mínima de WordPress lo permita |
| Ajustes preestablecidos alternativos de un bloque existente | Variaciones o estilos de bloque, no un nuevo bloque |
| Diseño reutilizable | Un patrón, no un bloque |
Reglas
- Atributos: asigna a cada atributo un
typeydefault; origínalos del marcado o comentarios de manera consistente; valida enrender.php. - Usa
supports(color, espaciado, tipografía, alineación, ancla) en lugar de escribir controles. - El marcado del editor debe usar
useBlockProps(); el PHP dinámico usaget_block_wrapper_attributes(). render.php(renderen block.json, WordPress 6.1+) recibe$attributes,$contenty$block(unWP_Block). Se carga una vez por instancia de bloque en la página, por lo que nunca declares funciones o clases dentro de él; llama a código compartido desde otro archivo.- Scripts vs módulos:
viewScriptes para scripts clásicos (y cualquier cosa que dependa de scripts de WordPress);viewScriptModule(6.5+) es para módulos de script como la API de Interactividad. No son intercambiables, por lo tanto no mezcles dependencias entre los dos. - Escapa todo en
render.php(fswp-security-engineer); los atributos son entrada del usuario. - Cambiar el marcado guardado de un bloque estático ya enviado rompe el contenido existente. Agrega una entrada
deprecatedcon elsaveantiguo, los atributos y una funciónmigrate, luego cambia el bloque. - Traduce las cadenas (
__()con el dominio de texto) en JS y PHP;wp_set_script_translationsotextdomainen block.json. - Carga scripts frontend solo donde se renderiza el bloque (
viewScriptModule/scripten block.json lo hacen).
Patrones
Más detalles sobre patrones, variaciones, hooks de bloque y bindings: references/patterns-variations.md. Profundidad de la API de Interactividad (renderizado del servidor, acciones asíncronas, data-wp-each, watchers, rendimiento): references/interactivity.md.
Regístrate en PHP con register_block_pattern() (y register_block_pattern_category()), o como archivos en el directorio patterns/ de un tema. Los patrones usan valores preestablecidos y texto traducido; sin imágenes remotas; dales un título claro, categorías y palabras clave.
API de Interactividad
Marcado renderizado por el servidor más un pequeño comportamiento reactivo, sin necesidad de framework.
- Habilítalo con
"supports": { "interactivity": true }y"viewScriptModule": "file:./view.js". - Directivas de marcado:
data-wp-interactive="namespace",data-wp-context='{"open":false}',data-wp-on--click="actions.toggle",data-wp-bind--hidden="!context.open",data-wp-class--is-open="context.open",data-wp-text="state.label". - Store en
view.js:import { store, getContext } from '@wordpress/interactivity'; store( 'namespace', { state: {...}, actions: { toggle() { const c = getContext(); c.open = ! c.open; } } } ); - Siembra el estado del servidor con
wp_interactivity_state( 'namespace', array(...) )para que la primera pintura sea correcta y no haya parpadeo. Mantén el estado serializable. - Usa espacios de nombres para todo para evitar colisiones; nunca pongas secretos en el estado o contexto (ambos se imprimen en la página).
- Para accesibilidad, vincula
aria-expandedy el manejo del enfoque al estado, y prueba el uso del teclado.
Construcción y pruebas
npx @wordpress/create-block para un punto de partida; @wordpress/scripts para build, start, lint-js, lint-style, test-unit-js. Entrega los archivos compilados junto con src/, package.json y el archivo de bloqueo (regla de directorio para código compilado). Prueba en el editor (inserta, edita, guarda, recarga, cambia a vista de código) y en el frontend. Pasa a fswp-qa-engineer.