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 C — 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): Nombre nodo: Valor inline
  2. Nodo bloque de texto (nodo BLOCK): 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:

Nombre 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 contenedor INLINE) o bien >> (nodo de texto BLOCK), siempre precedido de un nombre no vacío.

4.2 Restricciones del nombre del nodo

El nombre del nodo sólo permitirá caracteres alfanuméricos y los caracteres -, _, . 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

Las 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ísticas:

Ejemplos:

Título: 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:

Descripción >>
    Línea 1
    Línea 2
Sección>>
    Acepta el operador sin espacio

6.1 Reglas formales

Como consecuencia de la transparencia de los comentarios, el contenido de un bloque >> puede no ser contiguo en el fichero: una línea de comentario intercalada (con indentación menor o igual que la del nodo >>) se descarta sin cerrar el bloque, y el texto del bloque puede continuar después. Ver el ejemplo detallado en la sección 9.1.

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:

7.1 Restricción a ASCII

Cada elemento de un namespace (Ident) DEBE estar formado únicamente por caracteres del rango [a-z0-9] (en su forma canónica), con un @ opcional al inicio del namespace completo para indicar un namespace especial.

En la entrada se aceptan también las letras ASCII en mayúscula [A-Z], que el parser normaliza a minúsculas. No se aceptan diacríticos, caracteres no ASCII ni espacios.

Esta restricción a ASCII es deliberada: evita las ambigüedades de normalización Unicode y los ataques homográficos (caracteres visualmente idénticos pero distintos, p. ej. una a latina frente a una а cirílica), de forma coherente con las prioridades de seguridad de STXT (ver sección 15).

7.2 Herencia y nodos de nivel 0

Ejemplo:

Documento (com.example.docs):
    Autor: Joan
Anexo:
    Nota: texto

En este ejemplo, Anexo tiene namespace "" (vacío). No hereda com.example.docs del nodo raíz anterior. La ausencia de herencia lateral garantiza que el significado de un nodo raíz no dependa de los nodos que lo precedan (ver sección 8.5, concatenación).

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 indentación especiales

En los siguientes ejemplos se muestra . para identificar un espacio, y |--> para identificar un tabulador. El tabulador se representa ocupando hasta la siguiente columna múltiplo de 4, como haría 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 indentación que los dos anteriores.

Nodo nivel 0: Valor nivel 0
.|-->Nodo nivel 1: 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 espacio + 1 TAB, 2 espacios

Nivel 0:
....Nivel 1:
..........Nivel más que 2: ERROR: 4 espacios, 4 espacios, 2 espacios

Nota: estas reglas de nivel se aplican a las líneas que definen nodos. Las líneas de comentario están exentas de la validación de nivel (ver sección 9): su indentación no se comprueba y nunca produce error de nivel.

8.4 Jerarquía

8.5 Múltiples nodos de nivel 0 y concatenación

Un documento STXT PUEDE contener varios nodos de nivel 0 (nodos raíz). No existe la obligación de un único nodo raíz. Cómo se interpretan o usan esos nodos raíz corresponde a la aplicación, no al núcleo STXT.

Ejemplo de documento válido con tres nodos raíz:

Documento 1: Primero
Documento 2: Segundo
Documento 3 >>
    Texto del tercero

Cerradura bajo concatenación. Como consecuencia directa de permitir múltiples nodos de nivel 0 y de la ausencia de herencia lateral (sección 7.2), la concatenación de dos documentos STXT válidos es también un documento STXT válido, siempre que el segundo comience en una línea de nivel 0 (lo cual ocurre por definición, ya que sus nodos raíz están a nivel 0).

Esto permite, sin sintaxis adicional, casos de uso como:

STXT no necesita un formato derivado para "listas de documentos": un documento ya es una secuencia de nodos raíz.

9. Comentarios

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

Reglas generales de los comentarios:

Ejemplo:

# Comentario raíz
Nodo:
    # Comentario interior

9.1 Comentarios y bloques `>>`

Dentro de un bloque >> hay que distinguir dos situaciones según la indentación de la línea:

Esto implica que un comentario puede aparecer "en medio" de un bloque sin cerrarlo, y el texto del bloque continúa después.

Ejemplo completo:

# Es un comentario
Nodo inline:
    # Es un comentario
    Nodo text >>
        # NO ES un comentario
    # Es un comentario dentro de nodo texto. NO cierra el nodo
        Sigue el texto 1
    # Esto si es un comentario
# Esto también es un comentario
        Sigue el texto 2
    Otro nodo: Ya es otro nodo

En este ejemplo, el contenido lógico del bloque Nodo text es exactamente tres líneas:

# NO ES un comentario
Sigue el texto 1
Sigue el texto 2

Detalles:

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 `>>`

La indentación de bloque de un nodo >> es la indentación de la primera línea de su contenido (el primer nivel estrictamente mayor que el del nodo >>). Para cada línea de texto que pertenece al bloque:

  1. El parser elimina solo la indentación de bloque, conservando 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.

(Las líneas de comentario intercaladas, según 9.1, ya se han descartado y no intervienen aquí.)

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 >>.
  5. El nombre lógico de un nodo es la cadena vacía.
  6. Un namespace no cumple las restricciones de la sección 7 (formato a.b, sólo ASCII [a-z0-9] por elemento, @ opcional inicial).

Las líneas de comentario y las líneas vacías no son causa de error (su indentación no se valida).

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

El bloque Cuerpo contiene dos líneas: "# Esto es texto" y "Más texto". La línea # Esto sí es comentario, con indentación menor o igual que Cuerpo >>, es un comentario: se descarta y, al ser la última línea, el bloque termina.

14.4 Múltiples nodos raíz

Entrada:
    Fecha: 2026-06-13
    Texto: primera
Entrada:
    Fecha: 2026-06-13
    Texto: segunda

Documento válido con dos nodos raíz Entrada al mismo nivel. Esto permite, por ejemplo, un registro tipo log mediante simple append.

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       = { Linea }

Linea           = [Indentacion] ( Comentario | Nodo | BloqueContinuacion | LineaVacia )

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

Namespace       = "(" ["@"] Ident { "." Ident } ")"   ; al menos 2 Ident
Ident           = [A-Za-z0-9]+   ; aceptado en entrada; el parser DEBE normalizarlo a minúsculas (sección 7)
                                 ; forma canónica (y recomendada por estilo): [a-z0-9]+

Comentario      = "#" { cualquier carácter hasta fin de línea }   ; descartado; indentación no validada

BloqueContinuacion = LineaTextoBloque   ; líneas con indentación estrictamente mayor que el nodo >>
                                          ; los comentarios intercalados (indent <= nodo >>) se descartan
                                          ; sin cerrar el bloque

Indentacion     = 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: cálculo por columnas; cada tab completa hasta el siguiente múltiplo de 4

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 (org.example.meta)
				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.

18. Apéndice C — 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 sintaxis simplificada, orientada a prototipos rápidos. Aun 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 schema.

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

18.1. Asociación de un template a un namespace

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

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

Una vez definido, un template cumple la misma función que un schema. Si una implementación encuentra varios schemas o templates aplicables al mismo namespace, DEBERÍA definir una política de prioridad clara y determinista. Para una validación concreta, DEBE seleccionarse una única fuente semántica efectiva: o bien un schema, o bien un template.

19. Fin del Documento