STXT - Semantic Text
Built for humans. Reliable for machines.

STXT Plantillas (@stxt.template)

1. Introducción
2. Terminología
3. Relación entre STXT y Template
4. Estructura general de un Template
5. Un template por namespace objetivo
6. Bloque `Structure >>`
7. Cardinalidades
8. Tipos
9. ENUM y lista de valores
10. Namespaces dentro de `Structure`
11. Reglas de "nodos definidos"
12. Compilación a Schema (equivalencia semántica)
13. Errores de Template
14. Conformidad
15. Meta-template del propio sistema `@stxt.template`
16. Ejemplos normativos
17. Apéndice A — Gramática (informal)
18. Fin del Documento

1. Introducción

Este documento define la especificación del lenguaje STXT Template, un mecanismo para describir reglas semánticas (estructura, tipos, cardinalidades y valores permitidos) aplicables a documentos STXT.

Un template:

Relación con @stxt.schema:

2. Terminología

Las palabras clave "DEBE", "NO DEBE", "DEBERÍA", "NO DEBERÍA", y "PUEDE" deben interpretarse según RFC 2119.

Términos como nodo, indentación, namespace, inline y bloque >> mantienen su significado en STXT-SPEC.

Definiciones adicionales:

3. Relación entre STXT y Template

La validación mediante templates ocurre después del parseo STXT:

  1. Parseo del documento STXT a estructura jerárquica.
  2. Resolución del namespace efectivo de cada nodo.
  3. Selección del template correspondiente al namespace objetivo.
  4. Aplicación de reglas del template (estructura, cardinalidad, tipos, valores).

Una implementación PUEDE aplicar reglas durante el parseo, siempre que esta validación permanezca débilmente acoplada al parser base.

4. Estructura general de un Template

Un documento template DEBE tener como nodo raíz:

Template (@stxt.template): <namespace_objetivo>

El template DEBE contener exactamente un nodo Structure en forma de bloque (>>).

Template (@stxt.template): com.example.docs
	Description: Plantilla de ejemplo
	Structure >>
		Document (com.example.docs):
			Title: (1)
			Body: (1) TEXT

Reglas:

5. Un template por namespace objetivo

Para cada namespace lógico:

6. Bloque `Structure >>`

El bloque Structure >> define un árbol de plantillas de nodos usando indentación, donde:

Nivel superior y nodos definidos. Las líneas de nivel superior de Structure no tienen semántica especial de "raíz": son plantillas de nodo como cualquier otra, y su anidamiento define sus hijos. Cada línea de Structure (a cualquier nivel) define o referencia un nodo del namespace correspondiente, exactamente igual que un Node en un schema.

6.1 Convención de estilo recomendada

Por legibilidad, se recomienda:

6.2 Sintaxis de una línea de `Structure`

Cada línea del bloque Structure >> tiene la forma:

<NodeName> [<NamespaceOverride>] ":" [<RuleSpec>]

donde:

Ejemplos:

Title:
Title: (1)
Body: (1) TEXT
Color: (?) ENUM [red, green, blue]
Body Content: (?) @Body Content
Metadata (org.example.meta): (0,1)

Notas:

6.3 Reglas de parsing del `Structure >>`

Un parser de templates DEBE:

  1. Leer el bloque Structure >> como una secuencia de líneas (ya canonicalizadas por STXT core: trim derecha por línea).

  2. Ignorar líneas vacías.

  3. Calcular jerarquía por indentación (mismos principios que STXT: indentación consecutiva, sin saltos).

  4. Para cada línea, parsear:

    • Nombre del nodo + namespace opcional (ns) si existe.
    • El carácter : obligatorio.
    • La especificación de reglas opcional (RuleSpec).
  5. Resolver el namespace efectivo de cada línea.

  6. Resolver referencias @Nombre Nodo según la sección 6.4.

Un parser de templates DEBE fallar si una línea no contiene :.

6.4 Definición, referencia y recursión

Las plantillas distinguen entre:

Reglas de definición y referencia:

Recursión. Una referencia @Nombre Nodo DEBE apuntar a:

Esta segunda opción habilita estructuras recursivas: un nodo puede declararse como hijo de sí mismo o de un ancestro. Para resolver la referencia sólo se necesita la identidad del nodo (nombre + namespace + tipo), que ya está disponible en su línea de definición; no es necesario que su lista de hijos esté completa.

Como escribir Structure equivale a recorrer en profundidad el grafo de nodos, esta regla cubre todo grafo de dependencias: auto-recursión, recursión a través de ancestros y recursión mutua.

Ejemplo (auto-recursión):

Template (@stxt.template): com.example.doc
	Structure >>
		Documento (com.example.doc):
			Título: (1)
			Sección: (*)
				Título: (1) @Título
				Texto: (?) TEXT
				Sección: (*) @Sección

Aquí la última línea, Sección: (*) @Sección, declara Sección como hijo de sí misma, referenciando al ancestro Sección cuya definición está abierta. Título: (1) @Título reutiliza la definición local previa de Título.

Ejemplo (recursión mutua A/B):

Template (@stxt.template): com.example.tree
	Structure >>
		A (com.example.tree):
			B: (*)
				A: (?) @A

7. Cardinalidades

La cardinalidad se aplica por instancia del nodo padre, contando sólo hijos directos que coincidan por:

La cardinalidad se expresa como un token opcional entre paréntesis: ( ... ). Es independiente del orden de los hijos (cuenta apariciones, no posiciones).

7.1 Formas permitidas

Formas permitidas:

Forma Significado
num Exactamente num.
* Cualquier número (0..∞).
+ Una o más (1..∞).
? Cero o una (0..1).
num+ num o más (num..∞).
num- Hasta num (0..num).
min,max Entre min y max.

Reglas:

7.2 Cardinalidad por defecto

Si no se especifica cardinalidad, el valor por defecto es:

8. Tipos

Los tipos en templates reutilizan el conjunto de tipos de STXT Schema, con la misma intención: validar forma del valor y, opcionalmente, su contenido.

El tipo se especifica como una palabra tras la cardinalidad (si existe).

Ejemplos:

Fecha: (1) DATE
Cuerpo: (1) TEXT
Es Público: (1) BOOLEAN

Reglas generales:

8.1 Tipo por defecto

Si se omite el tipo, el tipo por defecto es:

8.2 Compatibilidad con hijos

La regla de compatibilidad con hijos es la misma que en STXT-SCHEMA-SPEC (sección 9):

Sólo los tipos INLINE y GROUP admiten hijos. Todos los demás tipos son hojas.

Por tanto:

8.3 Conjunto de tipos

El conjunto de tipos recomendado es el mismo que STXT-SCHEMA-SPEC.

Una implementación de templates:

9. ENUM y lista de valores

Si el tipo es ENUM, el template DEBE declarar una lista de valores permitidos, con al menos un valor.

La lista de valores se especifica con corchetes [...] tras el tipo:

ENUM [valor1, valor2, valor3]

Color: (1) ENUM [red, green, blue]

Reglas:

9.1 Limitación de la sintaxis de lista

Por la forma de la sintaxis [a, b, c], un valor ENUM declarado en un template NO PUEDE contener una coma , (separador de valores) ni un corchete de cierre ] (fin de lista). Tampoco conserva espacios al inicio o final, que el trim elimina.

Ésta es una limitación del subconjunto expresable por templates. Si se necesitan valores ENUM con comas, corchetes o espacios significativos, debe usarse un schema (@stxt.schema), cuyos nodos Value admiten cualquier valor inline.

10. Namespaces dentro de `Structure`

Cada línea puede incluir un namespace explícito para el nodo plantilla:

Metadata (org.example.meta): (?)

Reglas:

11. Reglas de "nodos definidos"

En templates, un nodo queda definido por su aparición en Structure. A diferencia de Schema, no existe una sección Node: separada; la propia estructura es la definición.

Reglas:

12. Compilación a Schema (equivalencia semántica)

Un template puede compilarse a un schema equivalente:

Reglas de traducción de cardinalidad:

13. Errores de Template

Un template es inválido si ocurre cualquiera de estas condiciones:

  1. El documento de Structure>> no es un documento válido STXT (indentación inválida, etc.)
  2. El documento no tiene raíz Template (@stxt.template): <namespace_objetivo>.
  3. Falta Structure >> o Structure no es bloque >>.
  4. Una línea no vacía dentro de Structure no contiene :.
  5. Cardinalidad mal formada o con números inválidos.
  6. Tipo desconocido (según el conjunto de tipos soportado por la implementación).
  7. Uso de [...] si el tipo no es ENUM.
  8. Un nodo con hijos tiene un tipo efectivo que no admite hijos (es decir, distinto de INLINE o GROUP).
  9. Redefinir un nodo local que ya ha aparecido previamente sin usar referencia @Nombre Nodo.
  10. Usar una referencia @Nombre Nodo que no apunta a una definición local previa ni a un ancestro abierto.
  11. El nombre de una referencia @Nombre Nodo no coincide (en nombre canónico) con el nombre de su línea.
  12. Declarar a la vez referencia @Nombre Nodo y tipo explícito en la misma línea.
  13. Declarar valores ENUM duplicados tras la normalización por trim.
  14. Definir hijos, tipo explícito o valores ENUM en un nodo cross-namespace.

14. Conformidad

Una implementación de templates es conforme si:

15. Meta-template del propio sistema `@stxt.template`

Esta sección define un template mínimo recomendado para validar documentos del namespace @stxt.template.

Template (@stxt.template): @stxt.template
	Structure >>
		Template (@stxt.template):
			Description: (?) TEXT
			Structure: (1) BLOCK

Notas:

16. Ejemplos normativos

16.1 Template simple (un namespace)

Template (@stxt.template): com.example.docs
	Description: Plantilla simple
	Structure >>
		Document (com.example.docs):
			Title: (1)
			Author: (1)
			Date: (1) DATE
			Body: (1) TEXT

16.2 Template con repetición y nodos anidados

Template (@stxt.template): com.example.blog.post
	Structure >>
		Post (com.example.blog.post):
			Title: (1)
			Slug: (1)
			Published: (1) BOOLEAN
			Tags: (?)
				Tag: (+)
			Sections: (1)
				Section: (+)
					Heading: (1)
					Content: (1) TEXT

16.3 Template con ENUM

Template (@stxt.template): com.example.ui.theme
	Structure >>
		Theme (com.example.ui.theme):
			Name: (1)
			Mode: (1) ENUM [light, dark]
			Accent: (?) ENUM [blue, green, orange]

16.4 Template con reutilización local

Template (@stxt.template): org.example.docs
	Structure >>
		Email (org.example.docs):
			Body Content: (1) TEXT
		Demo (org.example.docs):
			Body Content: (?) @Body Content

16.5 Template con recursión

Template (@stxt.template): com.example.doc
	Structure >>
		Documento (com.example.doc):
			Título: (1)
			Sección: (*)
				Título: (1) @Título
				Texto: (?) TEXT
				Sección: (*) @Sección

Sección se contiene a sí misma a cualquier profundidad. Es el caso que un parser con la regla de "sólo definición previa" rechazaría incorrectamente; por eso se incluye como ejemplo normativo de conformidad.

16.6 Cross-namespace (referencias externas)

Template (@stxt.template): com.example.docs
	Structure >>
		Document (com.example.docs):
			Metadata (org.example.meta): (?)
			Content: (1) TEXT

En este caso:

17. Apéndice A — Gramática (informal)

TemplateDoc      = "Template" "(" "@stxt.template" ")" ":" NamespaceTarget { TemplateField }
TemplateField    = DescriptionField | StructureField
DescriptionField = "Description" ":" Text
StructureField   = "Structure" ">>" Newline { StructureLine }

StructureLine    = Indent NodeSpec Newline
NodeSpec         = NodeName [NsOverride] ":" [RuleSpec]
NsOverride       = "(" ["@"] Namespace ")"
RuleSpec         = [Card] [NodeRef | Type [EnumValues]]

Card             = "(" CardToken ")"
CardToken        = "*" | "+" | "?" | Num | Num "+" | Num "-" | Num "," Num
NodeRef          = "@" NodeName
Type             = IdentUpper
EnumValues       = "[" Value { "," Value } "]"

NodeName         = Texto hasta `(` o `:`, con trim y compactación de espacios
NamespaceTarget  = Namespace según STXT-SPEC
Namespace        = Ident "." Ident { "." Ident }   ; al menos 2 Ident
Ident            = [A-Za-z0-9]+   ; aceptado en entrada; normalizado a minúsculas (STXT-SPEC sección 7)
IdentUpper       = [A-Z0-9_]+     ; recomendado en mayúsculas (estilo)
Value            = cualquier texto sin "," ni "]", con trim   ; ver sección 9.1

18. Fin del Documento