ajustes
This commit is contained in:
212
docs/08-layout-and-libraries.md
Normal file
212
docs/08-layout-and-libraries.md
Normal file
@@ -0,0 +1,212 @@
|
||||
# Layout Global y Librerías Globales
|
||||
|
||||
Este documento explica cómo gestionar los **4 campos globales del proyecto** (`style` CSS global, `javascript` JS global, `header` Twig del header del sitio, `footer` Twig del footer) y las **librerías globales** (CSS/JS/fonts inyectadas en `<head>` o antes de `</body>`). Cubre la regla crítica de NO editar nunca `cms/lib/plugins/builder_saas/layout.json` ni los `.tpl` de `custom-header-twig` / `custom-footer-twig` directamente, las tools `get_layout_field` / `set_layout_field` (única vía válida para editar header/footer/style/javascript) y las tools `list_global_libraries` / `add_global_library` / `remove_global_library` / `set_global_libraries` para gestionar las URLs de librerías. Léelo antes de tocar cualquier cosa relacionada con header, footer, CSS global o librerías externas (jQuery, Vue CDN, Google Fonts, etc.).
|
||||
|
||||
## Layout global
|
||||
|
||||
Los 4 campos globales del proyecto viven en `cms/lib/plugins/builder_saas/layout.json`:
|
||||
|
||||
| Campo | Contenido |
|
||||
|-------|-----------|
|
||||
| `style` | CSS global del proyecto (se inyecta en todas las páginas) |
|
||||
| `javascript` | JS global del proyecto (se inyecta en todas las páginas) |
|
||||
| `header` | Twig del header del sitio (se renderiza arriba de cada página) |
|
||||
| `footer` | Twig del footer del sitio (se renderiza al final de cada página) |
|
||||
|
||||
Los campos `header` y `footer` son **Twig** — se beneficias de filtros (`| get`, `| translate`, etc.) y atributos (`c-if`, `c-for`).
|
||||
|
||||
### REGLA CRÍTICA — Nunca edites estos archivos directamente
|
||||
|
||||
**Está prohibido** usar `acai-view`, `acai-line-replace`, `acai-write` ni `acai-delete` sobre:
|
||||
|
||||
- `cms/lib/plugins/builder_saas/layout.json`
|
||||
- `template/estandar/modulos/custom-header-twig/*`
|
||||
- `template/estandar/modulos/custom-footer-twig/*`
|
||||
- `template/estandar/modulos/custom-header/*`
|
||||
- `template/estandar/modulos/custom-footer/*`
|
||||
|
||||
Estos ficheros son **artefactos generados** a partir de `layout.json`. Editarlos directamente provoca:
|
||||
- Desincronización con `layout.json.{header,footer}ModuleCustom.htmlParsed`.
|
||||
- Sobrescritura de tus cambios cuando el usuario abre el builder visual y guarda.
|
||||
- Comportamiento inconsistente entre el render público y el builder.
|
||||
|
||||
**El backend protege estas rutas** — las tools de archivo devolverán error si intentas tocarlas.
|
||||
|
||||
### Workflow correcto
|
||||
|
||||
#### Leer
|
||||
|
||||
```
|
||||
get_layout_field({ field: "header" }) // Twig source del header
|
||||
get_layout_field({ field: "footer" }) // Twig source del footer
|
||||
get_layout_field({ field: "style" }) // CSS global
|
||||
get_layout_field({ field: "javascript" }) // JS global
|
||||
```
|
||||
|
||||
#### Escribir
|
||||
|
||||
```
|
||||
set_layout_field({
|
||||
field: "footer",
|
||||
content: "<footer class='bg-gray-900 text-white py-10'>…nuevo HTML/Twig…</footer>"
|
||||
})
|
||||
```
|
||||
|
||||
`set_layout_field` ejecuta una pipeline atómica:
|
||||
1. Escribe el source en `layout.json.{field}`.
|
||||
2. Sincroniza `layout.json.{field}ModuleCustom.htmlParsed`.
|
||||
3. Regenera los `.tpl` de `custom-{field}-twig/`.
|
||||
4. Compila el Twig a PHP.
|
||||
|
||||
Es **destructivo** — sobrescribe el contenido completo. **Pair con `get_layout_field` primero** para leer el actual y modificarlo, no escribirlo desde cero.
|
||||
|
||||
### Ejemplos de uso
|
||||
|
||||
#### Cambiar el copyright del footer
|
||||
|
||||
```
|
||||
// 1. Leer
|
||||
get_layout_field({ field: "footer" })
|
||||
// devuelve: <footer><p>© 2024 Mi Sitio</p>…</footer>
|
||||
|
||||
// 2. Modificar localmente y reescribir entero
|
||||
set_layout_field({
|
||||
field: "footer",
|
||||
content: "<footer><p>© 2025 Mi Sitio. Todos los derechos reservados.</p>…</footer>"
|
||||
})
|
||||
```
|
||||
|
||||
#### Añadir un menú al header
|
||||
|
||||
```
|
||||
// 1. Leer source actual
|
||||
get_layout_field({ field: "header" })
|
||||
|
||||
// 2. Escribir nueva versión con el menú añadido
|
||||
set_layout_field({
|
||||
field: "header",
|
||||
content: "<header>…<nav>{% for item in 'apartados' | get('parentNum=0 AND visible_en_el_menu=1', 'globalOrder ASC') %}<a href='{{ item.enlace }}'>{{ item.name }}</a>{% endfor %}</nav>…</header>"
|
||||
})
|
||||
```
|
||||
|
||||
#### Añadir CSS global
|
||||
|
||||
```
|
||||
// 1. Leer
|
||||
get_layout_field({ field: "style" })
|
||||
|
||||
// 2. Reescribir con la regla añadida
|
||||
set_layout_field({
|
||||
field: "style",
|
||||
content: ":root { --main-color: #2563eb; }\n.btn-primary { … }\n…"
|
||||
})
|
||||
```
|
||||
|
||||
## Librerías globales
|
||||
|
||||
`layout.json["libraries"]` define una lista de URLs (CSS, JS, fonts) que el CMS inyecta en cada página. Hay **dos secciones**:
|
||||
|
||||
| Sección | Posición | Uso típico |
|
||||
|---------|----------|------------|
|
||||
| `top` | Dentro de `<head>` | CSS, fonts (Google Fonts), JS crítico (preload) |
|
||||
| `bottom` | Antes de `</body>` | La mayoría de JS (jQuery, Vue, sliders, etc.) |
|
||||
|
||||
### Tools
|
||||
|
||||
#### Listar — `list_global_libraries`
|
||||
|
||||
```
|
||||
list_global_libraries()
|
||||
```
|
||||
|
||||
Devuelve:
|
||||
```json
|
||||
{
|
||||
"top": [
|
||||
{ "num": 1, "url": "https://fonts.googleapis.com/css2?family=Inter" },
|
||||
{ "num": 2, "url": "/css/extras.css" }
|
||||
],
|
||||
"bottom": [
|
||||
{ "num": 1, "url": "https://unpkg.com/vue@3/dist/vue.global.prod.js" },
|
||||
{ "num": 2, "url": "/js/main.js" }
|
||||
],
|
||||
"layoutExists": true
|
||||
}
|
||||
```
|
||||
|
||||
Llama a esta tool **antes** de añadir/quitar para no duplicar entradas.
|
||||
|
||||
#### Añadir — `add_global_library`
|
||||
|
||||
Idempotente: si la URL ya existe en esa sección, devuelve `added: false`.
|
||||
|
||||
```
|
||||
add_global_library({
|
||||
section: "bottom",
|
||||
url: "https://unpkg.com/vue@3/dist/vue.global.prod.js"
|
||||
})
|
||||
|
||||
add_global_library({
|
||||
section: "top",
|
||||
url: "https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap"
|
||||
})
|
||||
|
||||
// Rutas relativas al proyecto también valen
|
||||
add_global_library({
|
||||
section: "bottom",
|
||||
url: "/js/custom.js"
|
||||
})
|
||||
```
|
||||
|
||||
#### Eliminar — `remove_global_library`
|
||||
|
||||
Idempotente: si la URL no existe, devuelve `removed: false`.
|
||||
|
||||
```
|
||||
remove_global_library({
|
||||
section: "bottom",
|
||||
url: "https://unpkg.com/vue@3/dist/vue.global.prod.js"
|
||||
})
|
||||
```
|
||||
|
||||
#### Reemplazar entera — `set_global_libraries`
|
||||
|
||||
**Destructivo** — sobrescribe la lista completa de la sección. Úsalo solo para reordenar masivamente o reemplazar el conjunto. Para cambios incrementales prefiere `add_global_library` / `remove_global_library`.
|
||||
|
||||
```
|
||||
set_global_libraries({
|
||||
section: "bottom",
|
||||
libraries: [
|
||||
{ url: "/js/jquery.min.js" },
|
||||
{ url: "/js/main.js" },
|
||||
{ url: "https://unpkg.com/vue@3/dist/vue.global.prod.js" }
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
### Convenciones
|
||||
|
||||
- Para **librerías populares**, prefiere CDN oficial (`unpkg.com`, `cdn.jsdelivr.net`, `cdnjs.cloudflare.com`).
|
||||
- Para **assets propios** del proyecto, usa rutas relativas (`/js/main.js`, `/css/extras.css`).
|
||||
- Si añades una librería que ya tiene equivalente cargada (ej. dos versiones de jQuery), elimina la antigua antes de añadir la nueva.
|
||||
- El **orden** importa: las dependencias deben ir antes que sus consumidores. `set_global_libraries` permite reordenar.
|
||||
|
||||
## Decisión: ¿layout global o módulo?
|
||||
|
||||
| Caso | Solución |
|
||||
|------|----------|
|
||||
| Header/footer del sitio | Layout global (`set_layout_field` con `header`/`footer`) |
|
||||
| CSS aplicado a todo el sitio | Layout global (`set_layout_field` con `style`) o librería global |
|
||||
| JS aplicado a todo el sitio | Layout global (`set_layout_field` con `javascript`) o librería global |
|
||||
| Componente reutilizable en páginas | Módulo en `template/estandar/modulos/` |
|
||||
| Detalle de un registro | Sección general `custom-{tableName}` |
|
||||
| Bloque visual específico | Módulo |
|
||||
|
||||
## Reglas críticas
|
||||
|
||||
1. **NUNCA edites directamente** `layout.json`, `custom-header-twig/*`, `custom-footer-twig/*`, `custom-header/*`, `custom-footer/*`. Las tools de archivo te devolverán error si lo intentas.
|
||||
2. Para header/footer/style/javascript globales, **única vía**: `get_layout_field` + `set_layout_field`.
|
||||
3. `set_layout_field` es **destructivo** — siempre lee primero, modifica, escribe.
|
||||
4. Para librerías globales: `list_global_libraries` → `add_global_library` / `remove_global_library`. `set_global_libraries` solo para reordenar/reemplazar masivamente.
|
||||
5. Inyección automática: `top` va en `<head>`, `bottom` antes de `</body>`. Decide según el tipo de asset.
|
||||
6. El orden de las librerías importa para dependencias.
|
||||
Reference in New Issue
Block a user