1 puntos por GN⁺ 2024-11-19 | 1 comentarios | Compartir por WhatsApp
  • Con solo un archivo HTML único que se ejecuta en el navegador, es posible reunir en un solo documento la exploración, el análisis, la visualización de datos, la composición tipográfica y la publicación, reduciendo así el flujo tradicional de cuaderno → herramienta de publicación → PDF
  • La implementación central combina celdas echo que muestran style y script en pantalla, contenteditable y Observable Runtime para crear celdas reactivas editables
  • cell(name, inputs, definition) sigue el modelo de dependencias de Observable para componer unidades de ejecución conectadas entre sí, como counter, el renderizado de FizzBuzz, celdas ocultas y celdas intermedias sin salida visible
  • Dentro del mismo documento HTML se demuestran Observable Plot, TeX, Markdown, Graphviz, SQLite basado en WASM, Python basado en Pyodide, R basado en WebR, Observable Inputs y estado mutable
  • El resultado es un documento científico o técnico que se ejecuta en el navegador sin una plataforma adicional, y más adelante la implementación se publicó como la librería @celine/celine

Reducir la separación entre cuaderno y publicación con un solo archivo HTML

  • HTML se usa ampliamente para composición tipográfica, pero se ha aprovechado relativamente menos como plataforma de exploración, análisis y visualización de datos
  • El flujo de trabajo habitual pasa por varias herramientas
    • En cuadernos interactivos como Jupyter, RStudio, Pluto.jl, Observable se realizan la exploración, el análisis y la visualización
    • Luego se traslada a plataformas de publicación como Typst, Overleaf, LaTeX o editores WYSIWYG para la composición tipográfica
    • Para distribuirlo, se exporta a .pdf
  • Si un solo archivo HTML asume estas tres etapas, se pueden reducir procedimientos manuales, herramientas CLI, pasos de CI y la dependencia de plataformas de terceros
  • La implementación recibe una fuerte influencia de In-browser code playgrounds de Anton Zhiyanov, Self-modifying HTML notes de Cristóbal Sciutto, Quarto y Observable Framework

Cómo crear celdas editables

  • El primer paso consiste en usar la clase CSS echo para hacer que los elementos style y script se vean tal cual dentro del documento
  • Si además se agrega una fuente con resaltado de sintaxis integrado y el atributo contenteditable, puede usarse como un editor de código básico
  • Un script con contenteditable se vuelve a evaluar cuando pierde el foco
    • Se clona el script existente para crear un nuevo elemento script y se elimina el original
    • Este método es necesario porque eval no funciona con código que contiene sentencias import
  • Para la ejecución basada en Observable se cargan dos librerías
  • En el ámbito global solo se exponen dos símbolos: library y cell

Flujo de datos reactivo con Observable Runtime

  • La función cell(name, inputs, definition, observerVisibility) define celdas usando el alcance de módulo de Observable Runtime
  • Si ya existe una variable con el mismo nombre, recupera la variable existente; si no, crea una nueva y la define
    • Gracias a esta estructura, al reevaluar una celda contenteditable, la nueva definición se propaga a las celdas conectadas
  • Inspector de Observable se usa para mostrar la salida de la celda encima del bloque script
  • La celda counter está compuesta como un generador asíncrono que emite un número cada segundo
    • El atributo id del script y el argumento name de cell son iguales
    • Si se cambia el valor inicial i y luego se quita el foco, se refleja el nuevo valor
  • También se pueden crear celdas que dependan de counter
    • Se carga Hypertext Literal para renderizar el valor de counter en formato FizzBuzz
    • htl implementa un parser de HTML5 y maneja el escape automático, listeners de eventos, objetos de estilo e interpolación de valores no serializables como nodos DOM

Celdas visibles, ocultas y sin salida

  • Si no se agrega la clase echo, se puede ocultar la definición de la celda y aun así observar su salida
    • Estas celdas pueden usarse como primitivas de renderizado
  • También se puede crear un tipo de celda que no muestre la salida en absoluto
    • silent(name, inputs, definition) configura observerVisibility como oculto para usarla con valores intermedios o almacenamiento de estructuras de datos
  • Las celdas pueden funcionar sin importar el orden de declaración
    • En el ejemplo, la celda reallyNegative depende de la celda negative, declarada más adelante
  • El mismo valor de una celda también puede usarse en salidas más complejas
    • Se carga Observable Plot para dibujar un gráfico de líneas a partir de un arreglo de números y mostrar una regla vertical en la posición counter % 40

Ampliación de las salidas de documento y visualización

  • Una celda puede devolver cualquier elemento DOM
  • Las demos de TeX, Markdown y Graphviz devuelven cada una un tipo distinto de elemento
    • La celda tex devuelve un elemento span
    • La celda md devuelve un elemento table
    • La celda dot devuelve un elemento svg
  • Una celda puede devolver un Promise o lanzar un Error
    • Inspector de Observable aplica la clase observablehq--running al div externo de una celda en ejecución
    • A una celda con error le aplica la clase observablehq--error
    • El documento define estilos de acuerdo con esos estados

SQLite, Python y R dentro del navegador

Entradas y estado mutable

  • El tipo de celda viewof se creó para usarse junto con Observable Inputs
  • viewof declara dos celdas reactivas
    • NAME: el valor de la entrada
    • viewof NAME: el propio elemento DOM
  • Para mostrar la entrada encima de la celda, hay que establecer el id de la celda como viewof NAME
  • En el ejemplo se crea una entrada de rango con Inputs.range([0, 100], { step: 1 }), y la celda rangePlot se actualiza según ese valor
  • El funcionamiento de Observable Inputs es algo difícil de entender, y la demo Synchronized Inputs puede ser útil
  • También se creó el helper mutable para los casos en que no basta con un flujo de datos puramente funcional
    • mutable registra un objeto Mutable que emite un nuevo valor cuando este cambia

Publicación de la librería y diapositivas para presentaciones

  • Al principio se pensó en el nombre incel para esta implementación, pero luego se decidió llamarla celine
  • La librería se publicó como @celine/celine
  • Este documento se mostró en SydJS
  • También incluye código para convertir el documento en una presentación de diapositivas
    • Shift+N: iniciar la presentación o avanzar a la siguiente diapositiva
    • Shift+B: volver a la diapositiva anterior
    • Shift+E: salir de la presentación
  • La implementación está publicada como source code

1 comentarios

 
GN⁺ 2024-11-19
Comentarios en Hacker News
  • Coincido fuertemente con la premisa del artículo. HTML puede ser una base excelente para cuadernos computacionales
    Dicho eso, no me convence la elección de implementación aquí. El HTML dinámico y reactivo puede hacerse de forma mucho más declarativa que esto, y Observable es genial, pero en ciertos aspectos se aparta del JavaScript estándar
    Empecé a crear un sistema de HTML reactivo llamado Heximal, y más adelante planeo agregar soporte para cuadernos. Es un sistema declarativo basado en plantillas HTML y elementos personalizados, con un sistema de expresiones/reactividad encima basado en la propuesta TC39 Signals
    https://github.com/elematic/heximal
    Se parece más a una mezcla de HTMX, Tangle, Curvenote y Polymer, y siento que así se vería HTML si hubiera sido reactivo desde el principio. Creo que encaja bastante bien con casos de uso de edición gráfica y cuadernos

    • “Observable es genial, pero se aparta del JS estándar” aplica al frontend, pero por debajo el runtime simplemente ejecuta JavaScript. De hecho, el código fuente se parece mucho a JavaScript con macros mínimas, todo contenido dentro del parser acorn con licencia MIT
      Por eso las expresiones normales de depuración de JavaScript funcionan correctamente en Observablehq
      https://github.com/observablehq/parser
      Me gusta tanto el runtime de Observable que también hice un decompilador que puede convertir en ambos sentidos entre el código fuente del frontend y su representación compilada en JS puro
      https://observablehq.com/@tomlarkworthy/observablejs-toolcha...
    • Me pregunto si aquí se tomó en cuenta también Observable Framework. Salió en marzo, y una de sus características principales era justamente que usa JavaScript estándar, no los hacks de sintaxis creados en Observable Notebooks: https://observablehq.com/blog/observable-2-0#a-better-develo...
  • Está realmente genial. Me gustó especialmente la demo de Python y SQLite. Me parece interesante que parta de un ciclo de edición a través de la web (TTW) y lo llame un quine; tiene sentido, pero su debilidad principal es la persistencia
    TiddlyWiki en esencia hace lo mismo, pero guardar el trabajo es un dolor de cabeza. Porque para que algo persista, al final necesitas un proceso de servidor headless aparte
    Cuando quise crear algo parecido[0], personalmente empecé por la persistencia, y eso naturalmente significaba archivos. Eran archivos de texto plano que podían editarse con un editor para programadores y guardarse/publicarse a través del sistema de archivos. Así se evita el problema de tener que reimplementar dentro del navegador un editor para programadores, que no es nada trivial
    A cambio aparece el problema de tener que escribir un servidor rápido, pero también es un problema bastante divertido[1]. Aquí esquivaron eso usando secciones básicas de contenteditable, pero después de la persistencia, ese es el siguiente problema más grande
    El hecho de que no se pueda hacer export dentro de scripts embebidos también parece la misma pared. Sería bueno tener esa capacidad para no ensuciar el objeto global window, y en mi caso de uso también haría más fácil la generación de código
    0 - Literate Markdown: https://simpatico.io/lit.md
    1 - Reflector, un pequeño servidor node que transforma, comprime y cachea markdown, y hace invalidación por vigilancia de archivos: https://simpatico.io/reflector

  • Respeto las ideas y el esfuerzo invertido, pero la usabilidad de este enfoque es terrible. Si estoy tratando de hacer análisis exploratorio de datos, no entiendo por qué también tendría que preocuparme por elementos de estilo
    Justamente por eso herramientas como Jupyter Notebook funcionan tan bien. Aun así, valoro mucho que hayan implementado una idea alternativa con curiosidad

    • Autor: también me apena, pero coincido en que la usabilidad de este enfoque es terrible, y buena parte de la motivación para crear @celine/celine vino de ahí (https://maxbo.me/celine, o sea, empaquetar la escritura como una biblioteca)
      Todavía no es suficiente como plataforma de análisis exploratorio de datos. No tiene la capacidad de respuesta inmediata de un editor web de código completo como Observable Notebooks, ni es Observable Framework con hot reloading basado en file watching. El nuevo kernel de Jupyter para Deno + VSCode también ofrece una experiencia bastante fluida
      Así que sí, diría que la usabilidad para análisis exploratorio es, mm… mala, pero no me parece que la usabilidad para despliegue sea tan mala. De hecho, es buena. Porque simplemente es un solo archivo. Si quieres enviarle a alguien una gráfica y el resultado del procesamiento de datos, no necesitas mantener una cadena enorme de herramientas ni pagar por un servicio de terceros; basta con mandar un archivo HTML por Slack o alojarlo en algún lado
      Gracias a la flexibilidad para dar estilo a los resultados del análisis, también se puede publicar en entornos donde el estilo importa, como blogs o artículos de investigación
    • A simple vista, parece que esto quiere posicionarse más del lado del “análisis exploratorio del DOM”. El demo de introducción tiene una vibra de Scheme/Smalltalk en cómo se va trabajando al construir la estructura y los elementos básicos, y la parte donde cambian ivory por red y el resaltado de sintaxis se actualiza en tiempo real lo muestra bien
      Entiendo el contexto que llevó a esto, pero da pena que no sea más fácil jugar con frameworks y bibliotecas de JavaScript en el navegador. Al final solo es JS; debería poder experimentarse rápido en un entorno liviano. Este enfoque tiene fortaleza en ese punto
      Es una manera de recuperar el potencial juguetón y experimental de HTML/JS. Ojalá hubiera más intentos así que cosas como TS, rollup o webpack
      Extra: leyendo un poco más, veo que lo están proponiendo para análisis de datos. Para ese uso, no me parece que encaje bien
    • Dices “solo estoy tratando de hacer análisis exploratorio de datos”, pero me parece que la idea central es tener una plataforma integrada donde puedas hacer análisis exploratorio de datos y publicar fácilmente el resultado. No sería para Jupyter Notebooks desechables
      Creo que hay mucho valor en una alternativa a Jupyter Notebook que no termine siendo algo para tirar. La experiencia de usuario actual sí está muy mal, pero eso se puede mejorar. La cuestión es si esta configuración es mejor que el caos en JSON de Jupyter Notebook, y en lo personal creo que sí
  • El autor original de Lit dejó Google recientemente y, hasta donde sé, está trabajando en algo muy parecido a esto
    https://github.com/elematic/heximal

    • No sabía que había hecho público en lo que estaba trabajando después. Gracias por compartirlo
  • Me gusta el formato de este texto. Empieza desde lo más básico y va construyendo hasta llegar a algo interesante. No sigue esa corriente exagerada de meter un montón de dependencias o pegar frameworks por todos lados
    Para seguirlo, parecería que basta con copiar y pegar los fragmentos presentados y entender paso a paso cómo funcionan. Si yo escribiera algo así, probablemente lo haría con programación literaria en org-mode y luego lo exportaría a HTML para convertirlo en una entrada de blog
    Aun así, sigo teniendo mis dudas sobre la tipografía con resaltado de sintaxis integrado

  • Le dicen HTML reactivo, pero ¿no es casi puro JavaScript, o estoy entendiendo algo mal?

    • La parte interactiva/reactiva es JavaScript, pero el notebook está implementado dentro de un archivo HTML autocontenido. Se encarga de todo, desde la estructura del documento hasta la edición y visualización
      Fuera del navegador, no depende de software de terceros y, como HTML, es duradero, portable y fácil de escribir
    • Se siente como: “¿Por qué todos usan Colab u Observable para correr notebooks en el navegador? Bueno, de todos modos les voy a proponer una alternativa que use Observable para las partes difíciles”
  • Pronto intentaré dar soporte a este tipo de notebook HTML en Raku, o para Raku
    En este momento, las “soluciones de notebook” de Raku están basadas en Jupyter o en Mathematica

  • No entiendo bien la lógica de usar tecnologías web para complicar este proceso. ¿Qué resuelve la complejidad añadida? Más bien parece que lo vuelve más lento y elimina funciones necesarias como autocompletado, snippets y extensiones
    Además, es muy probable que otras personas no estén familiarizadas con esta configuración, así que colaborar también se vuelve más difícil
    El entorno se configura una sola vez y luego se puede seguir usando, agregando solo pequeñas mejoras a medida que cambia la tecnología
    Si usas n/vim, con esto basta. 1- Exploración de datos: usa https://github.com/untitled-ai/jupyter_ascending para conectar texto con notebooks de Jupyter. Como usa jupytext, puedes editar y ejecutar código de forma eficiente desde el editor de texto
    2- Escritura: puedes usar https://github.com/lervag/vimtex para LaTeX
    Si además le sumas tmux y tmuxp, puedes abrir proyectos al instante. En Emacs, se puede crear un flujo de trabajo fluido con org mode[1][2] y/o Auctex
    [1] https://sqrtminusone.xyz/posts/2021-05-01-org-python/
    [2] https://martibosch.github.io/jupyter-emacs-universe/

    • Cuando abres un notebook de Jupyter en el navegador, ¿qué tecnología estás usando? Cuando abres el sitio web del OP, ¿qué tecnología estás usando?
    • En general, son buenos puntos
      Pero no me gusta mucho Python, así que quiero usar herramientas que no estén centradas en Python. Por eso mencioné Raku y Mathematica
      Por cierto, gracias por mostrarme https://github.com/imbue-ai/jupyter_ascending
    • De acuerdo. Quien quiera notebooks reactivos debería considerar Emacs seriamente. Hay mucha gente que usa Emacs solo para unas pocas cosas, y los notebooks reactivos suelen ser una de ellas
  • En general, estoy de acuerdo con la premisa de este texto: que HTML no se está aprovechando lo suficiente como medio de publicación para la escritura científica
    Relacionado con esto, está el trabajo reciente de Will Crichton
    https://willcrichton.net/nota/
    https://willcrichton.net/notes/portable-epubs/

  • Últimamente los notebooks están en auge. Nosotros también lanzamos una versión de notebooks en TypeScript[1], pero tomamos una decisión bastante distinta en cuanto a los trade-offs
    Queríamos ejecutar código de node en el backend, así que, a diferencia del enfoque de este texto u Observable, no intentamos ejecutarlo en el entorno del navegador. Aun así, para muchas aplicaciones esta idea podría ser una mejor solución
    Aplausos para el autor
    https://github.com/srcbookdev/srcbook