Preguntas frecuentes

El lenguaje

¿Qué significa el nombre STXT?

La primera versión del lenguaje se llamaba STxT (Semantic Text); de ahí vienen el nombre y la pronunciación «s-text». STXT es su evolución: conserva el espíritu y la motivación originales, pero se ha transformado tanto desde entonces —la misma idea, ejecutada desde otra perspectiva— que puede considerarse casi otro lenguaje. Las referencias a STxT que puedan encontrarse corresponden al lenguaje antiguo; STXT, escrito así, es siempre el actual. Para evitar confusiones —y porque puede llevar a malentendidos— el término Semantic Text también se ha retirado: el nombre es, simplemente, STXT.

¿Es un lenguaje o un formato?

Las dos palabras son correctas: miran la misma cosa desde ángulos distintos. «Lenguaje» pone el foco en la gramática y en quien escribe: unas reglas de sintaxis, una especificación, algo que se aprende y se escribe a mano. «Formato» pone el foco en el papel que esa sintaxis juega cuando un sistema guarda o intercambia algo con ella. No son categorías excluyentes —XML significa literalmente Extensible Markup Language y nadie duda al decir «un fichero en formato XML»—, sino dos maneras de mirar.

STXT es un lenguaje: así se define, y de ese punto de partida sale el diseño Human-First entero —una gramática pensada para escribirse a mano, cinco especificaciones normativas, esquemas, herramientas—. Y actúa como formato allí donde un sistema lo emplea: como formato fuente de un CMS, de configuración, de intercambio entre agentes. La primera palabra dice lo que es; la segunda, el papel que hace en cada caso.

¿Es un formato de datos o de documentos?

Ambas cosas, porque la línea entre ambas es artificial: un email tiene campos y un cuerpo, un contrato tiene cláusulas y metadatos, una configuración tiene valores y comentarios largos. STXT es un árbol de nodos con nombre; cada nodo lleva o bien un valor y unos hijos, o bien un bloque de texto. Con eso se describe tanto una ficha de datos como un documento de veinte páginas. Los casos de uso recorren ese abanico.

¿Qué lo distingue de otros formatos?

STXT está diseñado para las personas, y de ese principio salen las características que lo definen:

  • La sencillez en los tres planos. Las reglas que hay que conocer caben en una página; un parser conforme es un recorrido línea a línea con una pila y se escribe en días, sin bibliotecas. El coste de parsear es lineal, en una sola pasada, sin retroceso ni referencias.
  • La indentación es la estructura. Un tabulador o cuatro espacios por nivel; el nivel de una línea se decide con esa sola línea. No hay llaves, corchetes, comillas obligatorias ni etiquetas de cierre.
  • El texto libre es literal. Todo lo indentado bajo un nodo >> es texto tal cual, sin escapes ni comillas; :, # y >> no tienen significado dentro.
  • Sin caracteres de escape. Cualquier carácter vale en un valor o en un bloque; a cambio, los nombres de nodo sí que tienen restricciones.
  • Seguridad del parseo por diseño. Sin entidades, referencias, anclas, inclusión de ficheros ni ejecución de código; namespaces en ASCII, sin ambigüedad de identificadores. Ver STXT-SPEC §15.
  • Validación aparte, opcional y cerrada. El parser no necesita esquemas; pero sí que existe un sistema de esquemas opcional y sencillo, adecuado para la mayoría de casos.

El razonamiento que hay detrás de cada una de estas decisiones está en Principios de diseño.

¿Qué extensión y qué media type se usan?

Extensión .stxt; media type text/stxt (registro en IANA previsto, aún no registrado), y text/plain como alternativa compatible. Codificación UTF-8 sin BOM (un parser acepta también el BOM), finales de línea LF (se acepta CRLF). Ver STXT-SPEC §3 y §13.

¿Nos enseñas un uso real?

El que estás leyendo: este mismo portal. Todas las páginas de stxt.dev —el tutorial, los casos de uso, las cinco especificaciones, esta FAQ— están escritas en STXT, y un generador de sitios estáticos las convierte en el HTML que tienes delante. Se puede comprobar de dos maneras: el enlace .stxt de la cabecera abre el fuente de la página actual, y añadir .stxt a la dirección de cualquier página devuelve su código tal cual — por ejemplo, faq.stxt es el fuente de esta misma página. El generador también es público: stxt-cms. Cómo explota un CMS a STXT como formato fuente se desarrolla en CMS y publicaciones.

¿Por qué no...?

¿Por qué no XML, YAML o TOML?

Ninguno de estos formatos es un error; cada uno optimiza otra cosa. La tabla compara, criterio a criterio, las decisiones de diseño de STXT con las de los formatos que suelen aparecer en la misma conversación:

STXT XML YAML TOML
Human-First Diseñado para escribirse a mano; las reglas caben en una página Verboso: etiquetas de cierre, atributos, escapes Legible, pero con reglas sutiles: comillas opcionales, valores que cambian de tipo Claro en configuración plana; el anidamiento va en cabeceras [a.b.c]
Esquemas y validación Integrados en el lenguaje, opcionales y cerrados Tres lenguajes de esquema —DTD, XSD y RELAX NG—, cada uno un ecosistema propio No tiene; se valida con herramientas de otros ecosistemas No tiene
Facilidad de parseo Lineal, en una sola pasada; un parser conforme se escribe en días Exige un parser industrial Especificación enorme; los parsers discrepan entre sí Asequible, con bordes laboriosos: fechas, tablas, strings
Superficie de ataque Sin entidades, referencias, anclas ni ejecución de código (STXT-SPEC §15) Entidades externas (XXE) y expansión de entidades Anclas expansibles y etiquetas que instancian objetos Pequeña
Texto libre Bloques >> literales: cualquier carácter, sin escapes Escapar < y &, o CDATA Escalares de bloque con reglas de indentación y recorte sutiles Strings multilínea entre triples comillas

La comparación con cada formato se desarrolla en su propia página: STXT frente a XML, STXT frente a YAML y STXT frente a TOML.

¿Por qué no Markdown?

Markdown no es una alternativa a STXT: es su complemento. Cubren dominios distintos —Markdown da formato a la prosa: negrita, enlaces, listas dentro del texto; STXT da estructura al documento: nodos, jerarquía, validación— y por eso funcionan juntos. De hecho, MARKDOWN es el único formato incrustado que los esquemas definen: un nodo declarado de ese tipo marca su texto como prosa con formato, a interpretar según CommonMark, y su forma cruda sigue siendo legible. Ver STXT-SCHEMA-SPEC §9.7; el reparto de trabajo entre ambos se desarrolla en STXT frente a Markdown.

Article: Guía de estilo
	Summary >>
		Un bloque de tipo MARKDOWN admite **negrita**, [enlaces](https://stxt.dev)
		o listas; la estructura del documento la ponen los nodos de alrededor.

¿Por qué no JSON?

Porque JSON no está pensado para escribirse a mano: es un formato de serialización para máquinas. Todo va entre comillas, llaves y comas; los saltos de línea se escriben \n; no hay comentarios, y un texto largo acaba en una sola línea llena de escapes. Nada de eso es un defecto —JSON no promete otra cosa—, pero lo descarta como formato Human-First. La página STXT frente a JSON desarrolla la comparación — y el camino inverso: el árbol JSON canónico que toda herramienta STXT puede emitir.

¿Por qué no hay listas?

Porque todo son listas. Los hijos de un nodo son una secuencia ordenada, y un mismo nombre puede repetirse tantas veces como haga falta; el árbol conserva el orden de aparición. Un documento STXT es ya una lista de nodos raíz, y cada nodo inline es una lista de hijos. Por eso no hace falta una sintaxis aparte para expresarla.

Una lista de elementos de un mismo tipo se escribe como un nodo contenedor con el mismo hijo repetido:

Authors:
	Author: María Pérez
	Author: Juan García
	Author: Ana López

Con un esquema, la cardinalidad del hijo (Min/Max, o (+) y (*) en una plantilla) fija cuántas veces puede aparecer. Y como los hijos de cualquier nodo admiten nombres distintos, una secuencia heterogénea —capítulos y anexos intercalados, por ejemplo— no necesita nada más que escribirlos en orden.

Es una consecuencia de tener pocas formas y ninguna redundante; ver Principios de diseño y STXT-SPEC §8.5.

¿Por qué no hay caracteres de escape?

Porque no hacen falta. La sintaxis de STXT solo tiene significado en dos puntos de una línea: el nombre del nodo y el separador (: o >>) que lo sigue. Todo lo que viene después del separador es el valor, y todo lo indentado bajo un >> es texto literal; en ninguno de los dos hay nada que escapar, porque el parser no busca nada ahí. Un valor puede contener :, un bloque puede contener # o >>, y una barra invertida es una barra invertida.

Ruta: C:\Users\ana\docs
Nota >>
	Los símbolos :, # y >> no significan nada aquí.

El precio está en los nombres de nodo. Técnicamente bastaba con excluir de ellos los caracteres que delimitan la sintaxis —:, > y los paréntesis—, pero por el principio Human-First se limitan a letras, dígitos y los separadores -, _ y espacio (INVALID_NODE_NAME en otro caso): así un signo dentro de un nombre no sugiere un significado que en STXT no existe.

Ver Principios de diseño y STXT-SPEC §4.2.

¿Por qué un bloque de texto no puede tener hijos?

No por una limitación técnica —podría hacerse—, sino por diseño: permitirlo iría en contra del principio Human-First en tres frentes.

  • Ruido visual. Para saber dónde acaba el texto y empiezan los hijos haría falta una marca de fin de bloque, y un documento dejaría de leerse como un esquema de notas.
  • Más complejidad en el parser. Hoy una línea bajo un >> es texto, sin más análisis; con hijos posibles, cada línea necesitaría una decisión.
  • Mezcla de significado. Un nodo que necesita a la vez hijos y un bloque de texto está describiendo dos cosas distintas, y eso apunta a que son dos nodos.

Por eso un nodo es una de dos cosas, y no las dos a la vez: un nodo inline, con valor e hijos, o un bloque, con texto. Y la forma de escribirlo es la misma en todos los casos: el bloque es un hijo más de un nodo inline, junto a los hermanos que necesite.

Chapter: Introducción
	Author: María Pérez
	Summary >>
		Conceptos básicos: monolitos, microservicios y criterios de diseño.
	Content >>
		El capítulo presenta...

Así Chapter lleva la estructura —título, autor, resumen, contenido— y cada bloque lleva solo texto. Con un esquema, Summary y Content se declaran de tipo TEXT (o MARKDOWN), y un tipo con validación de contenido no admite hijos.

Ver STXT-SPEC §6 y STXT-SCHEMA-SPEC §9.1.

Escribir documentos

¿Tabuladores o espacios?

Ambos son válidos y equivalentes: un tabulador es un nivel, cuatro espacios son un nivel. No es válido mezclarlos en la indentación de una misma línea (error INDENTATION_MIXED), ni usar otro ancho (dos espacios no son medio nivel: son un error). Líneas distintas de un documento pueden usar estilos distintos; stxt format --tabs o --spaces unifican el estilo de un fichero.

El ancho fijo es deliberado: el nivel de una línea se calcula a partir de esa sola línea, y la jerarquía se ve igual en cualquier editor. Una indentación visualmente más compacta se obtiene con tabuladores y el ancho de tabulador del editor. Ver STXT-SPEC §8.1.

¿Importan las mayúsculas, los acentos y los espacios en los nombres?

Los nombres se comparan por su nombre canónico: minúsculas, y toda secuencia de espacios, guiones y guiones bajos reducida a un solo guion. Los acentos y las letras no latinas se conservan. Así:

  • Fecha de nacimiento, fecha_de_nacimiento y Fecha-De-Nacimiento son el mismo nodo.
  • Título y título son el mismo nodo; Titulo es otro.
  • Caña y cana, o Peña y pena, son nodos distintos.

Los namespaces son más estrictos: solo ASCII [a-z0-9] y puntos, al menos a.b, y se pasan a minúsculas. Ver STXT-SPEC §4.3 y §7.

¿Cómo se escribe un valor con dos puntos o almohadilla dentro?

Sin ninguna marca. En un nodo inline el valor es todo lo que sigue al primer :, de modo que Hora: 10:30 vale 10:30, y # solo abre un comentario cuando es el primer carácter no blanco de la línea. En un bloque >> todo es texto literal.

Cita: 10:30 en la sala 2 # esto forma parte del valor
Notas >>
	# esto también es texto, no un comentario
	Clave: valor >> tampoco es un nodo

¿Puede un documento tener varios nodos raíz?

Sí. Un fichero puede contener varios nodos de nivel 0, cada uno con su árbol, y las herramientas los devuelven en orden. Eso permite parsear en streaming ficheros grandes: cada raíz se emite completa en cuanto empieza la siguiente. Los namespaces no se heredan lateralmente entre raíces: cada una declara el suyo. Ver STXT-SPEC §8.5.

¿Puede un documento usar varios namespaces?

Sí. Cualquier nodo puede declarar su propio namespace, y sus descendientes lo heredan a partir de él; cada namespace se valida contra su propia definición. Así un vocabulario común se define una vez y se incorpora desde otros: en la definición que lo incorpora, el hijo externo se declara con su namespace y solo con su cardinalidad.

Book (com.acme.book):
	Title: Arquitectura de software moderna
	Review (com.acme.reviews):
		Reviewer: Ana López
		Score: 9

Y las plantillas de los dos namespaces:

Template (@stxt.template): com.acme.book
	Structure >>
		Book:
			Title: (1)
			Review (com.acme.reviews): (*)

Template (@stxt.template): com.acme.reviews
	Structure >>
		Review:
			Reviewer: (1)
			Score: (1) NUMBER

Reviewer y Score pertenecen a com.acme.reviews sin escribirlo: lo heredan de Review, y cada namespace se valida contra su plantilla; el tutorial desarrolla el ejemplo completo. Ver STXT-SPEC §7.2 y STXT-SCHEMA-SPEC §8.

¿Y los comentarios?

Una línea cuyo primer carácter no blanco es # es un comentario. No forma parte del árbol ni mueve la jerarquía, pero su indentación se valida como la de un nodo: estilo homogéneo, múltiplos de 4 si son espacios, y como máximo un nivel más que el último nodo. Las líneas vacías están exentas. Dentro de un bloque >>, una línea con # más indentada que el nodo es texto del bloque; una menos o igual de indentada es un comentario y cierra el bloque. Ver STXT-SPEC §9.

¿Qué pasa con los comentarios al formatear?

Se conservan. stxt format (y Format Document de la extensión de VS Code) reescribe solo las líneas que abren un nodo; los comentarios, las líneas en blanco y el contenido de los bloques quedan como están, salvo el blanco final de línea. Descartar los comentarios exige un flag explícito, --clean, que reserializa el árbol y elimina todo lo que el árbol no describe. Ninguna herramienta del ecosistema reescribe un fichero sin una petición explícita (--write).

Esquemas y plantillas

¿Los esquemas son obligatorios?

No. Un documento sin namespace solo se parsea. Si tiene namespace, la herramienta que valida busca su definición en la cadena de resolución (los directorios .stxt/ ascendentes, el de usuario, el del sistema) y, si ninguna cubre ese namespace, lo señala con SCHEMA_NOT_FOUND: el documento no es incorrecto, pero no se ha podido validar, y eso se informa en lugar de omitirse, también cuando la cadena está vacía. Si se valida o no lo decide la herramienta, no la presencia de otras definiciones instaladas: en la CLI, --warn-schema lo rebaja a aviso y --no-schema desactiva la validación; en VS Code, el ajuste stxt.schemaValidation; en el playground, el interruptor Schema validation.

¿Esquema o plantilla?

Son dos sintaxis para el mismo modelo, y toda plantilla equivale a un esquema. La plantilla (@stxt.template) se escribe como el documento que describe, con la cardinalidad y el tipo entre paréntesis, y es la forma recomendada para la escritura manual:

Template (@stxt.template): com.example.docs
	Structure >>
		Email (com.example.docs):
			From: EMAIL
			To: (+) EMAIL
			Subject: (?)
			Body: (1) TEXT

El esquema (@stxt.schema) es la forma explícita, con Node, Children, Child, Min/Max y Type; es la forma que se genera y la que procesan las herramientas. Ver STXT-TEMPLATE-SPEC y STXT-SCHEMA-SPEC.

¿Cómo encuentra una herramienta los esquemas y plantillas?

Depende de la herramienta, porque la resolución de definiciones no forma parte del lenguaje base: es una capa opcional más, como los propios esquemas y plantillas. Una aplicación sin sistema de ficheros la resuelve a su manera —el playground, por ejemplo, asocia documentos y gramáticas por namespace dentro del workspace—. Para cuando intervienen ficheros y proyectos, STXT-DISCOVERY-SPEC define una resolución común, que una herramienta puede implementar o no; es la que siguen la CLI, la extensión de VS Code y las tres bibliotecas.

¿Dónde se colocan los esquemas y plantillas?

En las herramientas que siguen STXT-DISCOVERY-SPEC, en un directorio llamado .stxt/ en el proyecto: se cargan todos los .stxt que haya dentro, recursivamente, con independencia de los nombres de fichero y de los subdirectorios. La cadena de resolución de un documento son todos los .stxt/ de sus directorios ascendentes, luego ~/.stxt y por último /etc/stxt (en Windows, %USERPROFILE%\.stxt y %ProgramData%\stxt). Gana el nivel más cercano, namespace a namespace. La variable STXT_PATH sustituye la cadena entera por una lista de directorios, por ejemplo en CI.

stxt install fichero.stxt coloca una definición en su sitio y stxt schemas muestra qué definición aplica en un directorio y de dónde procede. El recorrido completo, con ejemplo, está en El entorno de trabajo; la norma, en STXT-DISCOVERY-SPEC.

¿Qué pasa si se escribe Titel en vez de Title?

El validador lo rechaza (CHILD_NOT_DECLARED). El modelo de contenido es cerrado: un nodo solo admite los hijos que su definición declara, y si no declara ninguno, no admite ninguno. Ese es el propósito de la validación: fallar de forma explícita en vez de aceptar en silencio. Ver STXT-SCHEMA-SPEC §6.

¿Se valida el orden de los hijos?

No. Se valida cuántas veces aparece cada hijo, no en qué posición: dos documentos con los mismos hijos en distinto orden validan igual. El orden se conserva en el árbol, de modo que una aplicación que le dé significado lo obtiene del árbol, no del validador. Tampoco hay expresiones regulares, valores por defecto ni reglas condicionales entre campos: son no-objetivos declarados. Ver STXT-SCHEMA-SPEC §11.

¿Cómo se evoluciona un esquema sin romper documentos?

Ampliando la definición sin invalidar lo ya escrito: todo documento que validaba sigue validando si el cambio permite más casos, no menos. No hace falta una versión nueva para:

  • Añadir un nodo opcional: con cardinalidad (?), (*) o cualquier otra de mínimo cero.
  • Relajar una cardinalidad: rebajar un mínimo o ampliar un máximo, como pasar de (2,5) a (1,5) o a (2,6).

Un matiz: la compatibilidad es respecto a la definición ampliada. Un documento que use lo añadido no valida contra una copia anterior, así que si los consumidores del namespace no actualizan la definición a la vez, conviene versionar también las ampliaciones; con una definición única —el .stxt/ del propio repositorio—, no hace falta. Es una decisión del caso de uso, no del cambio.

Lo que rompe es lo contrario —añadir un nodo obligatorio, retirar uno, estrechar una cardinalidad—, porque el modelo es cerrado. Para esos cambios se recomienda versionar el namespace (com.example.docs.v1com.example.docs.v2): cada versión tiene su definición y cada documento declara la que usa.

Herramientas

¿Cómo se valida en CI?

Con la línea de comandos, sin instalación permanente:

npx @stxt-lang/cli validate --recursive docs/
npx @stxt-lang/cli format --check --recursive docs/

El código de salida es 1 si algún documento no pasa y 2 si la llamada es incorrecta, de modo que el trabajo de CI falla por sí solo. --format json produce salida para máquinas. Si el entorno de CI no debe depender del contenido de ~/.stxt o /etc/stxt, STXT_PATH=./.stxt fija la cadena de resolución. Los detalles, en Herramientas; el caso de uso de ficheros de configuración enseña la misma comprobación protegiendo un despliegue.

¿Existe una representación canónica de un documento STXT?

Todo documento válido tiene un árbol canónico en JSON, definido en STXT-TREE-SPEC: un array de raíces con name, canonicalName, namespace, y value más children (inline) o lines (bloque). stxt describe fichero.stxt lo imprime, y las tres bibliotecas lo exponen desde su API. No incluye posiciones ni comentarios: es el contenido lógico, el mismo en todas las implementaciones.

¿En qué lenguajes hay parser?

Desde este portal se mantienen tres: TypeScript/JavaScript (@stxt-lang/core), Java (dev.stxt:stxt-core) y Python (stxt), con el mismo alcance, la misma fecha de especificación y el mismo corpus de conformidad. Sobre el primero se construyen la extensión de VS Code, la CLI y el playground. La lista completa está en Herramientas; para probar sin instalar nada, play.stxt.dev.

¿Qué estabilidad se promete?

Que un documento válido hoy lo será para siempre. Las especificaciones no llevan número de versión: cada una lleva una fecha (la de su texto vigente) y un estado, que solo avanza: Genesis (en construcción), Aurora (usable; un cambio incompatible es posible, raro y se anuncia siempre), Zenith (lo válido lo es para siempre; solo se añade) y Twilight (cerrada). La sintaxis y el árbol canónico —STXT-SPEC y STXT-TREE-SPEC— están en Zenith; los esquemas, las plantillas y el descubrimiento, en Aurora. Los códigos de error no se renombran, y la API de cada biblioteca queda congelada dentro de su propia línea 1.x. No se congelan el texto de los mensajes ni las fachadas de comodidad. La conformidad se declara contra la fecha de la especificación (SPEC_VERSION), no contra la versión del paquete. La declaración completa está en Estabilidad y versiones.

¿Dónde pregunto, o doy mi opinión?

En las discusiones de la organización stxt-lang en GitHub: preguntas, ideas, ambigüedades de las especificaciones y lo que hayas construido con STXT. Todo cambio del lenguaje empieza ahí. Los errores de una herramienta concreta van a las incidencias de su repositorio, listados en la página de Herramientas.