- El reStructured Text (rST) de Sphinx es más difícil de aprender que Markdown, pero facilita un control fino de la estructura y el formato de salida en documentos grandes, como libros.
- Markdown se parece más a una notación ligera para escribir HTML, mientras que rST se centra en un árbol de documento abstracto, combinando directivas, nodos y renderizadores para agregar nuevos objetos de documento.
- Sphinx transforma el doctree antes del renderizado, por lo que tareas como referencias cruzadas, procesamiento por formato de salida y transformaciones en etapas específicas del build pueden manejarse dentro del sistema documental.
- En Logic for Programmers, se escriben los ejercicios y sus soluciones cerca del texto original, y luego se usa una extensión personalizada para cambiar su ubicación y forma de presentación en las salidas EPUB y LaTeX.
- Markdown simple carece de una sintaxis de extensiones unificada y de soporte para transformaciones previas al renderizado, así que mientras más recurre un generador documental a preprocesamiento externo, más se debilitan el soporte de herramientas y la extensibilidad.
Por qué elegí rST
- La nueva versión de Logic for Programmers es el segundo libro escrito con Sphinx, y el trabajo anterior, la nueva Learn TLA+, también usa Sphinx.
- Sphinx usa reStructured Text, y rST tiene una curva de aprendizaje más pronunciada que Markdown.
- Después de escribir varios libros en Markdown, surgió la necesidad de una herramienta mejor y por eso se hizo el cambio a rST.
- rST en sí es independiente de Sphinx, pero en la práctica muchas veces se usa por Sphinx, así que aquí se tratan ambos juntos.
Diferencias estructurales entre Markdown y rST
- La diferencia más grande es que Markdown se parece más a una notación ligera de HTML, mientras que rST es una notación de escala intermedia para crear un árbol de documento abstracto.
- La sintaxis de imagen de Markdown puede convertirse en HTML como
<img alt="alttext" src="example.jpg"/>con una transformación sencilla.- Incluso los motores modernos de Markdown suelen parsear a una representación intermedia, pero su naturaleza básica sigue siendo la de una notación ligera para HTML.
- En rST, las imágenes se expresan con la directiva
.. image::.- Sphinx busca el manejador de directiva registrado y ejecuta
ImageDirective.run. - El resultado es un objeto nodo como
image_nodecon un campoalt. - Cuando termina el procesamiento completo del doctree, el HTML Writer busca la función de renderizado para
image_nodey emite la etiqueta HTML.
- Sphinx busca el manejador de directiva registrado y ejecuta
- El enfoque de rST hace que la implementación y la sintaxis sean más complejas y con más boilerplate que Markdown, pero también permite tratar las imágenes con el mismo mecanismo de extensión que otras directivas.
Cómo se agregan nuevos objetos de documento
- En rST/Sphinx se pueden agregar nuevos objetos de texto mediante extensiones.
- Por ejemplo, si se quiere generar
<figure>y<figcaption>en lugar de<image>, en Markdown básico habría que insertar HTML directamente. - En Sphinx, esto se resuelve registrando una nueva directiva
figure.FigureDirectiveincluso puede heredar deImageDirectivey reutilizar la mayor parte del procesamiento de imágenes.
- El patrón de registrar directivas, crear nodos y registrar renderizadores por builder se aplica igual a todas las extensiones.
Transformaciones del doctree antes del renderizado
- Sphinx puede realizar transformaciones del doctree antes de renderizar.
- Las referencias cruzadas entre documentos también se resuelven con esta capacidad.
- Si un documento tiene el ancla
fooy otro contiene:ref:\image <foo>``, Sphinx inserta la URL correcta en una etapa posterior del procesamiento.
- Si un documento tiene el ancla
- El código de transformación se trata como una funcionalidad de primer nivel dentro del proceso de build.
- Se puede aplicar una transformación solo para salida HTML.
- Se puede ejecutar una transformación en una etapa específica del build.
- También se pueden quitar transformaciones integradas que no se quieran ejecutar.
- No todos los documentos necesitan este nivel de potencia, y Markdown sigue siendo muy usado por ser ligero y portable.
Caso de extensión para ejercicios y soluciones
- Logic for Programmers es un libro más cercano a las matemáticas, así que necesita ejercicios para los lectores.
- Al escribirlo, es más fácil mantener los ejercicios y sus soluciones cerca dentro del documento, pero para el lector las soluciones deben aparecer al final del libro.
- Los requisitos además cambiaban según el formato de salida.
- Había que enlazar cada ejercicio con su solución.
- Pensando en la impresión, el PDF también necesitaba referencias de página.
- LaTeX/PDF y EPUB debían renderizarse de forma distinta.
- Para eso se escribió una extensión personalizada de Sphinx que maneja
exercise,solutionysolutionlist. - En la salida HTML de depuración, los ejercicios y soluciones se renderizan inline.
- En la generación de EPUB y LaTeX, se ejecuta una transformación después de construir el doctree completo.
- Todos los
solution_nodeen su posición original se mueven debajo desolutionlist. - A cada ejercicio se le agrega un nodo de referencia hacia la nueva ubicación de su solución.
- A cada solución se le agrega un nodo de referencia de vuelta al ejercicio original.
- Todos los
- El builder de LaTeX envuelve ejercicios y soluciones con answers environment.
- El builder de EPUB renderiza las soluciones como popup footnote.
- Esta estructura también ayuda al crear una muestra gratuita del libro.
- En la parte final de la muestra gratuita no aparecen todas las soluciones del libro, sino solo las correspondientes a la parte incluida en la muestra.
Preferencias de sintaxis y alternativas
- La objeción más común contra rST es que su sintaxis es fea.
- No usar una herramienta porque visualmente desagrada es una elección totalmente válida, y la dificultad para aceptar Lisp puede verse como una cuestión de gusto similar.
- Como alternativas existen asciidoc, MyST, Typst, Pollen, pandoc-extended markdown.
- La idea central no es que Sphinx/rST sea excepcionalmente bueno para documentación a gran escala, sino que Markdown simple es excepcionalmente inadecuado para documentación a gran escala.
Limitaciones de los generadores basados en Markdown
- Markdown simple no tiene soporte nativo para una sintaxis de extensiones unificada ni para transformaciones previas al renderizado.
- Muchos generadores documentales basados en Markdown agregan su propia etapa de preprocesamiento para cubrir nuevos casos de uso.
- Este enfoque suele funcionar, pero en vez de resolverse dentro de Markdown, termina siendo una solución alrededor de Markdown.
- Como resultado, hay límites en la potencia de las funciones, y además a las herramientas para programadores les cuesta entender bien esas variantes.
- Existen LSP y treesitter para Markdown y rST, pero es difícil esperar el mismo nivel de herramientas para gitbook-markdown, md-markdown o leanpub-markdown.
- La sintaxis fea de rST puede convertirse, de hecho, en una ventaja al ofrecer un árbol sintáctico más rico.
- Es posible hacer una consulta de treesitter que cambie solo el cuerpo de una directiva
todoespecífica. - Esto es posible porque el árbol sintáctico de rST es más rico que el de Markdown.
- Es posible hacer una consulta de treesitter que cambie solo el cuerpo de una directiva
Actualización de Logic for Programmers
- Logic for Programmers es un libro sobre cómo la lógica formal puede ser útil en la ingeniería de software cotidiana.
- El libro comienza con una introducción básica a las matemáticas y continúa con 8 aplicaciones como property testing, restricciones de bases de datos y tablas de decisión.
- Todavía está en fase alfa, pero ya tiene unas 20,000 palabras y está recibiendo comentarios de lectores.
1 comentarios
Opiniones de Hacker News
Si me preguntan “¿dejarías de usar una buena herramienta solo porque te da ganas de vomitar con solo verla?”, respondería que sí. La mayor ventaja de Markdown es que es fácil de leer, y la segunda es que es fácil de escribir.
Qué tan fácil sea de parsear o de extender importa muy poco. Más allá de si Markdown es lo mejor para escribir libros, para escribir rápidamente texto con formato de una manera fácil de leer incluso para quienes no conocen bien la sintaxis, Markdown es lo mejor. No estoy intentando escribir un libro; solo necesito tomar notas, documentar rápido o escribir comentarios, y si fuera a escribir un libro, usaría LaTeX antes que RST.
Pero al usarlo en apps reales, el punto de Markdown no era ese. Su objetivo es ofrecer solo el formato mínimo para que, incluso en texto plano, se lea tan naturalmente como cuando se renderiza en HTML. El conjunto de formatos admitidos es deliberadamente pequeño, así que cabe en la cabeza y se puede usar sin barra de herramientas. Encaja con cajas de comentarios, chats, mensajes de commit y quizá entradas de blog, pero no con la redacción de documentación de producto de nivel empresarial. Hoy se usa Markdown incluso en lugares donde no se va a renderizar como HTML, porque se lee bien por sí mismo, y me gustaría que HN también lo admitiera.
También hice bastante documentación técnica en Markdown, y con las extensiones de Pandochttps://pandoc.org/MANUAL.html se puede incluir casi todo el formato necesario, incluidas fórmulas complejas y bloques de código con resaltado de sintaxis. Ese Markdown se puede convertir a HTML, documentos de Word, ePub, PDF, etc. Haría falta una razón muy convincente para sacar algo que no sea Markdown.
El mayor problema que he visto con TeX no es el lenguaje, sino las personas. La gente suele escribir TeX espagueti con estilos pésimos. Pero si lo escribes con la mentalidad de “los documentos son código”, el resultado puede ser bastante limpio. El segundo mayor problema es que no hay un buen compilador de TeX → HTML.
No soy experto en LaTeX, pero cuando intenté aprenderlo una vez, se sentía como aprender el idioma de una civilización alienígena insectoide. No era nada intuitivo, y salvo que copiara algo que otra persona ya había hecho y solo insertara mi propio texto, era casi imposible hacer algo nuevo. Según recuerdo, tampoco tenía soporte de Unicode de primera clase.
Usar asteriscos o guiones bajos para cursivas también requiere acostumbrarse, y hay formas mucho más intuitivas como
/barras para cursiva/. Si sales de lo básico, las tablas, los metadatos y las etiquetas tapan el texto, por lo que no es fácil escribirlo ni leerlo sin una herramienta adecuada. Si fuera fácil de extender, también se podrían corregir esos problemas básicos, así que la extensibilidad también es relevante.Trabajé unos 12 años como redactor de documentación técnica y, al inicio de mi carrera, migré la documentación de una startup de Word a Sphinx. Después trabajé en el CMS/plataforma de documentación para desarrolladores propia de Google, en un sitio basado en Eleventy y, en los últimos 2 años, de nuevo en un sitio basado en Sphinx: pigweed.dev. También trabajé en una startup basada en readme.com y probé un poco Docusaurus, Astro y Hugo.
reStructuredText solo puede ser tosco, pero reST combinado con Sphinx es muy bueno. Las fortalezas de Sphinx superan por mucho las debilidades de reST. Para un sitio grande de documentación profesional, de más de 100 páginas y más de 10 colaboradores, creo con bastante convicción que Sphinx es la opción más responsable a largo plazo. Por ejemplo, en Pigweed hicimos que con solo escribir
:bug:\59385981`` se convirtiera en un enlace a https://pwbug.dev/59385981, y si más adelante hubiera que migrar masivamente los enlaces de bugs, sería fácil. También se garantiza que los enlaces internos siempre se resuelvan, y si enlazas a un lugar inexistente queda una advertencia o un error. Hace tiempo escribí en https://technicalwriting.dev/src/link-text-automation.html que me parece raro que esto no sea el estándar en los sitios de documentación. Sphinx también tiene APIs de extensiones y temas bien definidas, y un ecosistema bastante grande en PyPI. Últimamente llamo a Sphinx el gigante dormido de los sistemas de documentación; con solo concentrar un poco de esfuerzo podría volverse mucho más impresionante.Si cambia el slug o reorganizas la estructura del sitio, tienes que hacer buscar y reemplazar en todo el sitio. Los generadores de sitios estáticos podrían permitir enlazar como
[Hello](../hello.md)y resolverlo durante el build, pero muchas de las herramientas que he usado o revisado te hacen escribir directamente[Hello](/why/hello/). Parece que esta función divide opiniones. Incluso al comentárselo a miembros de equipos de generadores de sitios estáticos, recibí respuestas como “¿por qué querrías eso?”, y aunque lo expliqué no logré convencerlos. No sé si hay que haber sufrido el problema para apreciar el valor de la solución, o si están acostumbrados a escribir algo una vez y no mantenerlo por más de 10 años, pero me gustaría que tuviera soporte más amplio.Su ecosistema de plugins es excelente y ofrece una enorme palanca para mejorar la documentación de equipos y proyectos. reStructuredText en sí no me gusta, pero hoy, gracias a MyST-Parser, la mayoría de las cosas para las que antes Sphinx estaba fuertemente atado a RST también se pueden hacer con Markdown: https://github.com/executablebooks/MyST-Parser
Acabo de migrar a Sphinx un libro de más de 200 páginas que explica un lenguaje/VM/capa de abstracción interna, y realmente es un sistema que cambia la vida. Me gustaría que la documentación de Sphinx tuviera una barrera de entrada más baja o más ejemplos, pero ahora mismo estoy en una luna de miel bastante intensa. Mis principales intereses son cómo producir un libro PDF atractivo y un sistema para dividir el libro por capítulos y secciones en páginas man compatibles con POSIX.
La estética es un factor bastante importante al elegir un generador de sitios. Hugo y Gatsby tienen temas predeterminados excelentes, y de hecho alguna vez los elegí para un proyecto solo por esa razón. Las colecciones de temas de Sphinx https://sphinx-themes.org/ y https://sphinxthemes.com/#featured-themes en general son bastante sosas. Si comparas el tema estándar Sphinx RTD https://sphinx-rtd-theme.readthedocs.io/en/stable/ con la documentación de Apple https://developer.apple.com/documentation/swift/array o Fluent UI https://react.fluentui.dev/?path=/docs/concepts-developer-positioning-components--default, se ve anticuado.
Considero que la frase “Markdown es una representación ligera de HTML” es el mayor problema de este artículo. Es claramente imprecisa.
Markdown fue diseñado como una herramienta para convertir las convenciones de formato de texto que se usaban de facto como estándar en correos electrónicos y publicaciones de Usenet a principios de los años 90. Debido a la limitación de ASCII de 7 bits, formatos como énfasis o títulos se marcaban con símbolos especiales, y HTML también tenía mucho en común con esas convenciones sin nombre. Por eso John Gruber escribió en 2004 un script básico para convertir eso a HTML https://daringfireball.net/projects/markdown/, pero probablemente no esperaba que se convirtiera en un estándar de facto tan universal.
Gruber no tomó simplemente el estándar de facto de Usenet para crear un convertidor a HTML, sino que diseñó su propio marcado tomando prestadas convenciones de Usenet y de otros lugares. La sección “Acknowledgements” al final del enlace también lo muestra. Markdown fue concebido desde el inicio como una sintaxis de marcado para CMS web, y decir que es una representación ligera de HTML es correcto. La clave era que cada parte de la sintaxis generara HTML con una correspondencia directa.
El hecho de que se haya inspirado en convenciones de correo electrónico no hace menos correcta la afirmación “Markdown es una representación ligera de HTML”.
Hay una regla que dice que hay que responder a la interpretación más plausible y fuerte de lo que dijo la otra persona, y no tomar una interpretación débil que sea fácil de criticar. También hay una regla que dice que no hay que escoger solo la frase más provocadora del texto para quejarse, sino responder a las partes interesantes: https://news.ycombinator.com/newsguidelines.html
Si no estás de acuerdo con el punto central del texto, basta con decir que prefieres Markdown a rST y explicar por qué. Pelearse por una sola frase sobre qué es exactamente Markdown es tonto.
Sí se inspiró en convenciones como las del correo electrónico o Usenet, y algunas de ellas incluso existían antes de las computadoras. Por ejemplo, creo haber visto casos en documentos antiguos escritos a máquina donde se usaban asteriscos como cursivas. Pero Markdown está fuertemente ligado a HTML, su sintaxis está muy condicionada por HTML, y los intentos de separarlo de HTML en general están destinados a fracasar.
Creo que la esencia de Markdown es hacer más rápido lo que es más simple que el HTML crudo, pero permitir mezclar HTML crudo cuando haga falta.
En proyectos donde necesitaba más potencia que Markdown, como la de RST, me resultaba más cómodo escribir HTML directamente.
Al crear un sistema de documentación de complejidad similar, evalué RST porque necesitaba desesperadamente un marcado con semántica clara: guardar la estructura de archivos RST en una base de datos y mezclar los resultados de la base de datos con el contenido.
Me encontré con dos problemas. Primero, las herramientas de RST no tienen un unparser que vuelva a generar RST. Quería fusionar varios archivos RST y otras fuentes para generar archivos RST automáticamente y manipularlos mediante una API documental, pero no estaba soportado. Segundo, las herramientas de RST esperan un conjunto de bloques definido para un documento específico. Si los bloques se representaran de forma genérica, sería posible crear herramientas que transformaran documentos sin conocer las definiciones internas de cada bloque, pero no es así. Esto es un problema de herramientas más que del propio RST, pero cada vez que tenía que desmontar el código hasta el fondo me hacía pensar en otros sistemas de marcado, como alguno basado en HTML.
La ventaja de este enfoque es que puedes controlar por completo el esquema de entrada y la salida; la desventaja es que tiene muchísimo más ruido sintáctico que Markdown o RST, y necesitas scripts para parsearlo y transformarlo al formato de salida que quieras.
El propósito completo de docutils es parsear formatos y convertirlos a una API: https://www.docutils.org/docs/index.html#api-reference-material-for-client-developers
Hace algunos años recopilé un subconjunto de reStructuredText que valía la pena memorizar: https://simonwillison.net/2018/Aug/25/restructuredtext/
En proyectos recientes empecé a usar MyST, que ofrece las funciones de referencias e índices que valoraba en reStructuredText, pero permite usar una sintaxis Markdown más fácil de escribir para los colaboradores.
Lo que realmente cambia las reglas del juego es rST+Sphinx con los enlaces internos y las directivas
:ref:,:doc:. Al referenciar anclas o enlaces a documentos dentro del mismo contenido, no hace falta escribir manualmente el encabezado, y se evita que ese encabezado escrito a mano termine quedando desactualizado: https://www.sphinx-doc.org/en/master/usage/referencing.html#ref-roleEs una de las funciones que más extraño cuando escribo en rST.
No quiero secuestrar la conversación sobre ReStructuredText, pero si buscas un lenguaje de marcado que dé más que Markdown, recomendaría mirar AsciiDoc antes que ReStructuredText. He escrito documentación técnica durante años con los tres, y considero que AsciiDoc es mejor que ReStructuredText y Markdown.
Por ejemplo, el soporte de tablas en Markdown y ReStructuredText es muy engorroso. El formato de tablas de AsciiDoc es fácil de leer, escribir y mantener, y es más potente: admite encabezados, leyendas, tamaños personalizados de tablas y filas, e incluso formato complejo dentro de las tablas. Es un formato con un estándar único, sin tantos dialectos como Markdown; su sintaxis es concisa y legible, y la curva de aprendizaje es más suave que la de ReStructuredText. También ofrece mejores opciones de estilo de salida, una cadena de herramientas superior y muchas funciones de documentación integradas, por lo que se depende menos de plugins de terceros. AsciiDoc fue diseñado desde el principio para documentación técnica; los otros dos fueron más bien adaptados para ese rol.
Si armas con buena presentación un documento Markdown de unas 5 a 10 páginas, y haces que se renderice dentro de una plantilla Jinja más dinámica, al principio resulta bastante satisfactorio. También tienes un proceso de build para documentación automática, y ya es algo demasiado grande para un único README de GitHub. Pero ahí empieza el dolor.
La documentación de GitHub Project Pages no encaja bien, no sabes si hace falta un archivo
.nojekylni si todavía se necesita una ramagh-pages. No queda claro si el problema es una mala configuración del repositorio o si los cambios no se están reflejando, y después de pasar horas probando GitHub Actions todo se vuelve irracional. Vuelves a mirar Read the Docs y parece que quiere Sphinx, así que conectas Markdown con Sphinx; el build funciona, pero después del despliegue el ancho de la página se rompe, aunque no puedes reproducirlo localmente, así que parece culpa de la inserción de anuncios del nivel comunitario. Lo he visto funcionar bien en muchos proyectos y también lo he hecho yo mismo, pero hasta que funciona es increíblemente quisquilloso en mil detalles. Al final, Markdown contra RST ni siquiera es el tema: lo importante es encontrar una combinación que funcione bien para proyectos de documentación de tamaño medio y hosting estático.También tiene buenas instrucciones para despliegue automático: https://github.com/rust-lang/mdBook
Parece que se está pasando por alto que el autor habla en el contexto de maquetar su propio libro. No está afirmando que rST sea mejor que Markdown en general.
En los casos comunes, la simplicidad de Markdown explica por qué se usa tanto, pero ese no es el objetivo del que habla el autor.
Me resulta curioso que se reaccione como si reST hubiera sido creado como competidor de Markdown. En realidad, es casi al revés. reST es una evolución de StructuredText de 2002, y Markdown se publicó por primera vez en 2004.
Sus objetivos son muy parecidos, y en el texto más básico ambos se pueden leer y escribir como texto plano. En esa época, mucha gente empezó a querer algo así y surgieron varios formatos. Creo que la razón por la que Markdown ganó tiene poco que ver con que sea “más simple” o “más legible”. Para contenido que se expresa fácilmente con ASCII puro y espacios, en general son intercambiables. ¿Alguien diría que el documento reST del ejemplo es un texto críptico que no puede leerse sin un parser? No tengo claro en qué sentido una variante de Markdown sería mejor que eso; más bien, por casualidad histórica uno terminó imponiéndose, pero ambos son suficientemente buenos para su objetivo principal.
reST ofrece muchas funciones de formato adicionales útiles cuando hacen falta, pero cuando no hacen falta son ruido. Empecé a usar GitHub-flavored Markdown alrededor de 2010, cuando me registré en GitHub, y también usé reStructuredText algunas veces por la documentación de Python. Este último tenía una curva de aprendizaje mucho más pronunciada y después no tuve motivos para seguir usándolo.
Los dobles backticks también son una sintaxis desproporcionadamente irritante en comparación con el tiempo que realmente toma usarlos.