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

STXT Documentos

1. Introducción
2. Terminología
3. Codificación del Documento
4. Unidad Sintáctica: Nodo
5. Nodos contenedor, tipo INLINE
6. Nodos bloque texto, tipo BLOCK
7. Namespaces
8. Indentación y Jerarquía
9. Comentarios
10. Normalización de espacios en blanco
11. Reglas de Error
12. Conformidad
13. Extensión de Archivo y Media Type
14. Ejemplos Normativos
15. Consideraciones de Seguridad
16. Apéndice A — Gramática (Informal)
17. Apéndice B — Interacción con `@stxt.schema`
18. Apéndice B — Interacción con `@stxt.template`
19. Fin del Documento

1. Introducción

Este documento define la especificación del lenguaje STXT (Semantic Text).

STXT es un lenguaje Human-First, diseñado para que su forma natural sea legible, clara y cómoda para las personas, manteniendo al mismo tiempo una estructura precisa y fácilmente procesable por máquinas.

STXT es un formato textual jerárquico y semántico orientado a:

Este documento describe la sintaxis base del lenguaje.

2. Terminología

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

3. Codificación del Documento

Un documento STXT DEBERÍA codificarse en UTF-8 sin BOM.

Un parser:

4. Unidad Sintáctica: Nodo

Cada línea no vacía del documento que no sea comentario ni parte de un bloque >> define un nodo.

Existen dos formas de nodo:

  1. Nodo contenedor inline (nodo INLINE text): Nombre nodo: Valor inline
  2. Nodo bloque de texto (nodo BLOCK text): Nombre nodo >>

El nombre del nodo NO puede estar vacío. Una línea con sólo : o >> no es válida.

Ejemplo con nodos INLINE:

Nodo 1: Valor inline
	Nodo 2 sin valor:
	Nodo 3 con otro valor: este es el otro valor

Ejemplo con nodo BLOCK:

Nodo block >>
	Este es el contenido
	del bloque de texto:

	  - Se conservan espacios iniciales y saltos de línea
	  - Se hace trim a la derecha
	  - NO se hace trim a la izquierda

Un nodo puede incluir opcionalmente un namespace:

Nombre (namespace.normal):
Nombre (@namespace.especial):

4.1 Normalización del nombre del nodo

El nombre del nodo se toma a partir del texto comprendido entre:

Sobre ese fragmento se aplica:

El resultado de esta normalización es el nombre del nodo.

Un nodo cuyo nombre lógico sea la cadena vacía ("") es inválido y DEBE provocar un error de parseo.

Ejemplos equivalentes a nivel de Nombre de nodo:

Nombe de nodo:
Nombre de nodo: valor
Nombre  de   nodo   : valor
Nombre  de nodo (@un.namespace.especial):
Nombre de nodo(un.namespace.normal):
Nombre  de nodo >>
Nombre de nodo>>

La definición de un nodo siempre debe incluir o bien : (nodo container INLINE) o bien >> (nodo texto BLOCK), siempre precedido de un nombre no vacío.

4.2 Restricciones del nombre del nodo

El nombre del nodo sólo permitirá carácteres alfanuméricos y los carácteres -, _, . Se permiten nombres con diacríticos, mayúsculas y minúsculas.

4.3 Nombre canónico del nodo

El nombre canónico se forma a partir del nombre del nodo mediante el siguiente proceso:

El nombre canónico será usado para saber si un nodo tiene el mismo nombre que otro. También será usado internamente por todas las operaciones de búsqueda o comprobación, para saber si se trata del mismo elemento.

Ejemplos de transformación:

Un nombré con äcento: un-nombre-con-acento
UN NOMBRE con äcento: un-nombre-con-acento
TAMaÑo número 2__ y 3: tamano-numero-2-y-3

4.4 Normas de estilo

La normas de estilo recomendables son las siguientes:

Ejemplos de estilo correcto:

Nombre con valor: El valor
Nombre sin valor:
Nombre con namespace (el.namespace):
Nodo de texto >>

5. Nodos contenedor, tipo INLINE

La forma con : define un nodo contenedor INLINE con las siguientes caracteríticas:

Ejemplos:

Titulo: Informe
Autor: Joan
Nodo:
Nodo: Valor
Nodo:
    SubNodo 1: 123
    Otro subnodo: 456

5.1 Normalización del valor

El valor (INLINE) de un nodo debe normalizarse con un trim (derecha e izquierda).

Ejemplo:

Nombre: valor 1
Nombre:    valor 1
# en los dos casos, el valor inline de Nombre es "valor 1", aunque en el
# segundo haya espacios antes y después.

La normalización fuerte se aplica sólo a identificadores estructurales. Los valores son literales, aunque se aplica una normalización sencilla: trim derecha e izquierda.

6. Nodos bloque texto, tipo BLOCK

La forma con >> define un bloque de texto literal.

Ejemplos válidos:

Descripcion >>
    Línea 1
    Línea 2
Seccion>>
    Acepta el operador sin espacio

6.1 Reglas formales

6.2 Ejemplo

Bloque >>
    Texto
        Hijo: valor SI permitido, es texto, no se parsea
        Otro hijo: SI permitido
    # Esto también es texto
Siguiente Nodo: valor

En este ejemplo:

7. Namespaces

Un namespace es opcional y se especifica así:

Nodo (com.example.docs):
Otro nodo (otro.namespace):
Más nodos (@un.nombre.especial):

Reglas:

8. Indentación y Jerarquía

La indentación define la jerarquía estructurada del documento.

8.1 Indentación Permitida

Un documento STXT:

8.2 Ejemplos de identación especiales

En los siguientes ejemplos se muestra . para identificar un espacio, y |--> para identificar un Tabulador. El tabulador se mostrará con los carácteres que falten hasta llegar a la siguiente columna, como un editor de texto.

Ejemplo con tabuladores:

Nodo nivel 0: Valor nivel 0
|-->Nodo nivel 1:
|-->Otro nodo nivel 1:
|-->|-->Nivel 2:
|-->|-->Nivel 2:
|-->Nivel 1:
|-->Nivel 1:

Ejemplo con espacios:

Nodo nivel 0: Valor nivel 0
....Nodo nivel 1:
....Otro nodo nivel 1:
........Nivel 2:
........Nivel 2:
....Nivel 1:
....Nivel 1:

Ejemplo con mezcla de espacios y tabuladores.

Permitido, aunque no recomendable por estilo. Un parser PUEDE dar un aviso de mezcla en la misma línea. Este ejemplo tiene la misma identación que los dos anteriores.

Nodo nivel 0: Valor nivel 0
.|->Nodo nivel 1: Espacio + 1 TAB: nivel 1
..|>Otro nodo nivel 1: 2 Espacios + 1 TAB: nivel 1
...>..|>Nivel 2: 3 Espacios + 1 TAB, 2 Espacios + 1 TAB: nivel 2
|-->....Nivel 2: 1 TAB, 4 Espacios: nivel 2
..|>Nivel 1: 2 Espacios + 1 TAB: nivel 1
.|->Nivel 1: 1 Espacio + 1 TAB: nivel 1

8.3 Errores de nivel

Un parser DEBE dar error de parseo en los siguientes casos:

Nivel 0:
....Nivel 1:
............Nivel3: ERROR, no se puede pasar de nivel 1 a nivel 3
Nivel 0:
....Nivel 1
...Nivel casi 1: ERROR: 3 espacios (no se llega a 4)

Nivel 0:
....Nivel 1:
.|->..Nivel casi 2: ERROR: 1 espacios + 1TAB, 2 espacios

Nivel 0:
....Nivel 1:
..........Nivel mas que 2: ERROR: 4 espacios, 4 espacios, 2 espacios

8.4 Jerarquía

9. Comentarios

Fuera de bloques >>, una línea es un comentario si, tras su indentación, el primer carácter es #.

Ejemplo:

# Comentario raíz
Nodo:
    # Comentario interior

9.1 Comentarios dentro de bloques `>>`

Dentro de un bloque >>:

Ejemplo:

# Un comentario normal (nivel 0)
Documento:
	# Otro comentario normal
			# ¡Esto también es un comentario! Fuera de bloque >>
    Texto >>
        # Esto es texto
        Línea normal
            # También es texto normal
    # Esto sí es comentario
# Esto también es un comentario
    	Aquí continúa el texto del nodo

9.2 Estilo para comentarios

10. Normalización de espacios en blanco

Esta sección define cómo deben normalizarse los espacios en blanco para garantizar que distintas implementaciones produzcan la misma representación lógica a partir del mismo texto STXT.

10.1 Valores inline (`:`)

Al parsear un nodo con ::

  1. El parser toma todos los caracteres desde inmediatamente después de : hasta el fin de línea.

  2. El valor inline DEBE normalizarse aplicando:

    • Eliminación de espacios y tabuladores iniciales (trim a la izquierda).
    • Eliminación de espacios y tabuladores finales (trim a la derecha).

Esto implica que las siguientes líneas son equivalentes a nivel de parseo:

Nombre: Joan
Nombre:     Joan
Nombre: Joan
Nombre:     Joan

En todos los casos, el valor lógico del nodo Nombre es "Joan".

Si tras el trim el valor queda vacío, el valor inline se considera la cadena vacía ("").

10.2 Líneas dentro de bloques `>>`

Para cada línea que pertenece a un bloque >>:

  1. El parser determina el contenido de la línea a partir del texto que sigue a la indentación mínima del bloque (es decir, elimina solo la indentación de bloque, pero conserva cualquier indentación adicional como parte del texto).
  2. Sobre ese contenido, el parser DEBE eliminar todos los espacios y tabuladores finales (trim a la derecha).
  3. Las líneas vacías se conservan en todos los casos, exceptio líneas que son comentarios reales, con identación inferior al bloque.

Ejemplo de canonicalización de líneas:

Bloque >>
    Hola
        Mundo

Representación lógica del contenido del bloque:

10.3 Líneas vacías en bloques `>>`

Ejemplo:

Texto >>
    Línea 1

    Línea 2

Contenido lógico del bloque:

11. Reglas de Error

Un documento es inválido si ocurre alguna de estas condiciones:

  1. Espacios que no sean múltiplos de 4 (cuando se usan espacios para indentación).
  2. Saltos en los niveles de indentación.
  3. Un nodo >> contiene contenido significativo inline en la misma línea que >>.
  4. Un nodo no contiene ni : ni >>.

Un parser conforme DEBE rechazar el documento.

12. Conformidad

Una implementación STXT es conforme si:

13. Extensión de Archivo y Media Type

13.1 Extensión de Archivo

Los documentos STXT DEBERÍAN usar la extensión: .stxt

13.2 Media Type (MIME)

14. Ejemplos Normativos

14.1 Documento válido

Documento (com.example.docs):
    Autor: Joan
    Fecha: 2025/12/03
    Resumen >>
        Este es un bloque de texto.
        Con varias líneas.
    Config:
        Modo: Activo

14.2 Bloque con líneas vacías

Texto>>

    Línea 2

Contenido lógico del bloque:

  1. ""
  2. "Línea 2"

14.3 Comentarios dentro y fuera de bloques

Documento:
    Cuerpo >>
        # Esto es texto
        Más texto
    # Esto sí es comentario

15. Consideraciones de Seguridad

STXT ha sido diseñado con la seguridad del parseo como prioridad fundamental, minimizando la superficie de ataque en comparación con otros formatos textuales estructurados.

Un parser conforme de STXT es inherentemente resistente a clases comunes de vulnerabilidades:

En consecuencia, STXT es especialmente adecuado para procesar documentos de fuentes no confiables (configuraciones remotas, entradas de usuario, intercambio de datos) donde la seguridad del parser es crítica.

Las implementaciones DEBEN rechazar documentos inválidos según la sección 11 y NO DEBEN introducir extensiones que permitan carga externa o evaluación dinámica sin medidas de seguridad explícitas.

16. Apéndice A — Gramática (Informal)

Documento       = { Línea }

Línea           = [Indentación] ( Comentario | Nodo | BloqueContinuación | LíneaVacía )

Nodo            = Indentación Nombre [Namespace] ( Inline | BlockStart )
Inline          = ":" [Espacio] [TextoInline]
BlockStart      = [Espacio] ">>" [EspaciosFinales]

Namespace       = "(" ["@"] Ident { "." Ident } ")"
Ident           = [a-z0-9]+   ; solo minúsculas y números según reglas de estilo y normalización

Comentario      = "#" { cualquier carácter hasta fin de línea }

BloqueContinuación = IndentaciónMayorQueBloqueAnterior { cualquier texto }   ; texto literal

Indentación     = Mezcla permitida de espacios y tabuladores según sección 8
                  - Puros espacios: múltiplos exactos de 4 por nivel
                  - Puros tabs: 1 tab = 1 nivel
                  - Mixtos en línea: tab gana, espacios <4 se ignoran

Nombre          = Texto normalizado (trim + compactación espacios) según sección 4.1

Notas clave para implementadores:

17. Apéndice B — Interacción con `@stxt.schema`

El sistema de schemas permite añadir validación semántica a documentos STXT sin modificar la sintaxis base del lenguaje.

El núcleo STXT no define cómo debe reaccionar una implementación: el comportamiento pertenece exclusivamente al sistema de schemas (STXT-SCHEMA-SPEC).

Un schema es un documento STXT cuyo namespace es: @stxt.schema

y cuyo objetivo es definir las reglas estructurales, tipos de valor y cardinalidades de los nodos pertenecientes a un namespace concreto.

El núcleo STXT no interpreta estas reglas; únicamente define cómo se expresan y cómo se combinan mediante namespaces.

17.1. Asociación de un schema a un namespace

Para asociar un schema al namespace com.example.docs, se escribe un documento:

Schema (@stxt.schema): com.example.docs
	Node: Email
		Children:
			Child: From
			Child: To
			Child: Cc
			Child: Bcc
			Child: Title
				Max: 1
			Child: Body Content
				Min: 1
				Max: 1
			Child: Metadata (com.google)
				Max: 1
	Node: From
	Node: To
	Node: Cc
	Node: Bcc
	Node: Title
	Node: Body Content
		Type: TEXT

17.2. Aplicación a documentos STXT

Un documento que declare el mismo namespace:

Documento (com.example.docs):
    Campo1: valor
    Texto: uno
    Texto: dos

puede ser validado por una implementación que soporte schemas STXT:

17.3. Independencia del núcleo

STXT NO DEBE imponer reglas semánticas provenientes de schemas. El sistema de schemas es un componente separado y opcional que opera sobre el STXT ya parseado.

También PUEDE actuar como parte del proceso de parseo. En ese caso DEBERÍA estar débilmente acoplado con él. Esto permitiría detectar errores sin tener que esperar al final del parseo de parseo.

18. Apéndice B — Interacción con `@stxt.template`

El sistema de templates permite añadir validación semántica a documentos STXT sin modificar la sintaxis base del lenguaje.

El núcleo STXT no define cómo debe reaccionar una implementación: el comportamiento pertenece exclusivamente al sistema de templates (STXT-TEMPLATE-SPEC).

Un template es un documento STXT cuyo namespace es: @stxt.template

y cuyo objetivo es definir las reglas estructurales, tipos de valor y cardinalidades de los nodos pertenecientes a un namespace concreto.

El sistema de Templates es análogo a los schemas, pero con una syntaxis simplificada, orientada a prototipos rápidos. Aún así, es un sistema perfectamente válido para todo tipo de documentos. Podría considerarse azúcar sintáctico, ya que internamente puede usar la misma representación que un esquema.

El sistema de templates PUEDE convivir junto a un sistema con esquemas, ya que al final un Template define la misma información que un schema.

18.1. Asociación de un schema a un template

Para asociar un schema al namespace com.example.docs con templates, se escribe un documento:

Template (@stxt.template): com.example.docs
	Structure >>
		Email:
			From:
			To:
			Cc:
			Bcc:
			Title: (?)
			Body    Content: (1) TEXT
			Metadata (com.google): (?)

Una vez declarado, los templates cumplen la misma función que los schemas. Un validador estándar DEBERÍA priorizar un schema por encima de un template.

19. Fin del Documento