MDL describe un mueble por intención (qué tipo es y qué tiene), no por construcción. Cada línea de MDL transpila a un fichero MFL completo. La cadena:
MDL ─→ MFL ─→ Furniture ─→ SVG
El verificador comprueba que el SVG cumple los invariantes que el MDL afirma. Lo que MDL no afirma (ancho exacto, color, herraje) lo afina el usuario en el diseñador.
Como primera línea (opcional) puedes declarar la unidad en la que escribirás los valores numéricos (ANCHO, ALTO, FONDO). Si la omites, MDL asume centímetros.
CENTIMETROS # defecto MILIMETROS PULGADAS PIES
Internamente todo se convierte a milímetros. Pulgadas y pies usan los factores estándar (×25.4 y ×304.8). Los conteos como 2 PUERTAS o 4 BALDAS no se ven afectados.
DEFINE familia <modificadores>
| DEFINE bajo-cocina 2 PUERTAS | 2 puertas en una banda |
| DEFINE cómoda 5 CAJONES | 5 cajones apilados |
| DEFINE armario 4 PUERTAS 3 BALDAS | 4 puertas con 3 baldas internas cada una |
| DEFINE estantería 4x4 | grid 4 columnas × 4 filas |
| DEFINE mesa-comedor RECTANGULAR | mesa con tablero + patas |
Mayúsculas/minúsculas se ignoran. Acentos opcionales (CAJÓN≡CAJON). Singular y plural valen.
DEFINE librería-3-cuerpos CUERPO estantería 4 BALDAS CUERPO armario 2 PUERTAS CUERPO estantería 4 BALDAS
Cada CUERPO es una mini-definición MDL completa. Los cuerpos se colocan de izquierda a derecha en el orden escrito y son homogéneos: comparten alto, fondo y ancho. Por defecto, el primer cuerpo es el "lider" y los demás heredan sus dimensiones. BODY es alias de CUERPO.
DEFINE librería ANCHO 3000 ALTO 2200 FONDO 400 CUERPO estantería 4 BALDAS CUERPO armario 2 PUERTAS CUERPO estantería 4 BALDAS
Tras el nombre puedes añadir ANCHO N, ALTO N y FONDO N en milímetros, sin signo igual. ANCHO se reparte por igual entre los cuerpos (3000/3=1000 cada uno); ALTO y FONDO se aplican idénticos a todos. Cualquiera de los tres es opcional; lo que no especifiques se hereda del primer cuerpo.
| bajo-cocina | 600×600×850 con plinto (bajo encimera) |
| alto-cocina | 600×350×700 sin plinto (a pared) |
| columna-cocina | 600×600×2000 (columna alta) |
| esquinero-cocina | 900×900×850 (esquina) |
| isla-cocina | 1500×600×820 (isla central) |
| mueble-tv | 1500×400×450, con patas 60 |
| aparador | 1500×400×850 con plinto |
| mesa-comedor | 1800×900, tablero + patas 720 |
| mesa-centro | 1000×600, tablero + patas 370 |
| estantería | 1200×300×1200 abierta |
| vitrina | 1000×350×2000 (puertas con cristal) |
| consola | 1000×300×800, con patas 370 |
| mesilla | 450×400×550 |
| cómoda | 1000×450×850 |
| sinfonier | 600×450×1200 (alto y estrecho) |
| armario | 1000×600×2200 |
| vestidor | 600×580×2200 (abierto) |
| cambiador | 800×600×950 (nuevo 2026-05-26) |
| cuna | 1400×700×950 (nuevo 2026-05-26) |
Las dimensiones por defecto son orientativas. El usuario las afina en el diseñador. Solo lo afirmado en MDL (puertas, cajones…) se verifica.
| escritorio | 1400×600×740 |
| librería | 1800×350×2200 — soporta rejilla NxM |
| banco | 1200×400×450 (asiento sobre patas) |
| zapatero | 800×350×900 (mueble vertical con baldas) |
| vinoteca | 600×350×1500 |
| mesa-abatible | 1200×600×30 + patas plegables |
| mueble-baño | 900×460×650 — bajo lavabo |
| columna-baño | 350×280×1600 — estrecha y alta |
Acentos opcionales: mueble-bano también vale.
| N PUERTA(S) | N puertas en una banda |
| N CAJÓN/CAJONES | N cajones apilados |
| N BALDA(S) | baldas internas o estructurales (ver abajo) |
| NxM | grid (estantería 4x4) |
| RECTANGULAR / CUADRADA / REDONDA | forma de mesa-comedor |
| ABIERTO | cell sin puertas ni cajones |
| N CUERPOS | azúcar para N copias (vestidor 3 CUERPOS) |
| ANCHO N · ALTO N · FONDO N | tras el nombre del compuesto: ancho total se reparte; alto/fondo idénticos en todos los cuerpos |
| ENCIMERA <piedra|laminado|madera> | aplica a bajo-cocina/isla-cocina; activa la encimera con el material indicado |
| MAGIC-CORNER | aplica a esquinero-cocina/columna-cocina; cesto extraíble en el panel ciego |
| KIT | marca cajones/puertas como kit comprado (solo se fabrica el frente) |
| PUERTA-ESPEJO | armario con frente espejo |
| CRISTAL | vitrina con frente de cristal explícito |
| PATAS-ALTAS / PATAS-BAJAS / PATAS-OCULTAS | mueble-tv, aparador, consola: estilo de patas |
| LAVABO | mueble-baño con encastre de lavabo |
| N BOTELLAS / N VINOS | vinoteca con N huecos para botellas |
| espacio entre grupos | banda nueva (apilamiento arriba→abajo) |
| + entre grupos | sub-cell en la misma banda (izda→dcha) |
| , entre grupos | fin de banda explícito (opcional, ayuda a leer) |
# banda única, 2 puertas lado a lado DEFINE bajo-cocina 2 PUERTAS # 2 bandas: cajón corrido arriba, 2 puertas abajo DEFINE bajo-cocina 1 CAJÓN 2 PUERTAS # 1 banda subdividida: puerta a la izda, 2 cajones a la dcha DEFINE bajo-cocina 1 PUERTA + 2 CAJONES # mezcla: cajones arriba, puerta+cajones subdivididos abajo DEFINE aparador 3 CAJONES, 1 PUERTA + 1 PUERTA
La balda tiene dos significados según el contexto:
| Tras puerta: baldas internas | "2 PUERTAS 1 BALDA" → 2 puertas con 1 balda detrás de cada una |
| Sola en familia abierta: baldas estructurales | "estantería 5 BALDAS" → mueble abierto con 5 divisores horizontales |
# puertas con baldas internas DEFINE armario 2 PUERTAS 3 BALDAS # estantería abierta DEFINE estantería 5 BALDAS # vestidor abierto con baldas DEFINE vestidor 3 BALDAS
| bajo-cocina · isla-cocina | puertas, cajones, baldas |
| alto-cocina | puertas, baldas (sin cajones) |
| columna-cocina | puertas, cajones, baldas, hueco-horno/microondas/frigo |
| cómoda · sinfonier | solo cajones |
| mesa-comedor | solo formas (no admite cajones) |
| mesa-centro | solo cajones (opcional) |
| estantería | grid NxM, baldas, puertas, cajones |
| vestidor | abierto, baldas, N CUERPOS |
Si una familia no admite un modificador, el parser falla con error claro y sugerencia.
| cómoda 2 PUERTAS | "la familia cómoda no admite PUERTAS" |
| mesa-comedor 5 CAJONES | "prueba mesa-centro si quieres cajones" |
| 3 CAJONES 1 BALDA | "los cajones no admiten baldas" |
| 0 PUERTAS | "el conteo debe ser ≥ 1" |
| DEFIN bajo-cocina | "se esperaba DEFINE" |
| armarito 2 PUERTAS | "familia desconocida; disponibles: bajo-cocina, alto-cocina…" |
# todas equivalentes: DEFINE cómoda 5 CAJONES DEFINE comoda 5 cajones define CÓMODA 5 CAJÓN # singular vale
normalize() prueba con tilde, sin tilde y NFD reverse. Las 17 familias y los modificadores se reconocen en cualquier forma.
DEFINE mesa-centro # mesa abierta sin cajones DEFINE bajo-cocina # carcasa simple, frente abierto
Sin modificadores produce un mueble base con los defaults de la familia, frente abierto. Útil para vinotecas, mesas planas o arrancar y luego retocar en el diseñador.
# pared de salón con armario en medio DEFINE pared-salón CUERPO estantería 4 BALDAS CUERPO armario 2 PUERTAS 3 BALDAS CUERPO estantería 4 BALDAS # pared de 3 m a 2.20 m de alto y 40 cm de fondo DEFINE pared-salón ANCHO 3000 ALTO 2200 FONDO 400 CUERPO estantería 4 BALDAS CUERPO armario 2 PUERTAS 3 BALDAS CUERPO estantería 4 BALDAS # armario asimétrico DEFINE armario-asim CUERPO armario 1 PUERTA CUERPO armario 2 PUERTAS # azúcar: 3 vestidores idénticos DEFINE vestidor 3 CUERPOS # isla doble cara (3 cajones por cara) DEFINE isla-doble CUERPO isla-cocina 3 CAJONES CUERPO isla-cocina 3 CAJONES
Lo que MDL afirma se verifica contra el SVG guardado:
| family | tipo del mueble (kitchen-low, dresser…) |
| doors · drawers | conteo total, suma cells y zonas |
| shelves | internalShelves + divisores estructurales |
| cols · rows | solo si MDL declara grid NxM |
Lo que MDL NO afirma (ancho exacto, fondo, alto, color, plinto, herraje) NO se verifica — el usuario es libre de afinarlo en el diseñador.
Cada línea MDL transpila a un MFL canónico que se compila igual que cualquier MFL. Una composición con N cuerpos genera N bloques mueble en el mismo MFL (con suffix _b1, _b2...). Tras la compilación se obtiene un Furniture (uno por cuerpo) y se renderiza al SVG.
# MDL DEFINE bajo-cocina 2 PUERTAS 1 BALDA # MFL transpilado mueble kitchen_low_2p ancho = 600 alto = 850 fondo = 600 grosor = 19 zocalo = 80 trasera = fino distribucion columnas = 2 A:resto B:resto filas = 1 A1 = puerta B1 = puerta A1..B1.baldas-interiores = 1
Cada item de json/catalogo.json puede llevar un campo mdl con la spec canónica. En catalogo.php:
| badge azul MDL | el item tiene MDL definido (tooltip = el texto) |
| botón M | prompt para editar el MDL (valida sintaxis antes de guardar) |
| botón 🔍 | comprobar título contra modelo guardado |
| botón 🔍 Comprobar todos | batch sobre todos los items |
Si el item tiene mdl, la verificación lo usa (parser → invariantes → diff contra el SVG). Si no, fallback al sistema legacy de expects.
| DEFINE bajo-cocina 3 CAJONES | bajo cocina cajonera |
| DEFINE columna-cocina 2 PUERTAS 1 BALDA | columna despensa |
| DEFINE aparador 4 PUERTAS 1 BALDA | aparador clásico |
| DEFINE mesa-comedor RECTANGULAR | mesa de comedor |
| DEFINE mesilla 2 CAJONES | mesilla de noche |
| DEFINE cómoda 5 CAJONES | cómoda alta |
| DEFINE armario 4 PUERTAS 3 BALDAS | armario batiente |
| DEFINE estantería 4x4 | estantería tipo Kallax |
| DEFINE vitrina 2 PUERTAS | vitrina con cristal |
| DEFINE | arranca cada mueble (forma simple o compuesta) |
| CUERPO / BODY | sub-mueble dentro de un compuesto |
| + | sub-cell lado a lado en la misma banda |
| , | fin de banda (opcional) |
| # ... fin línea | comentario |
Una sola fuente de verdad: el catálogo guarda el MDL; el SVG es la implementación. La verificación cierra el ciclo.