1 points par GN⁺ 2024-11-19 | 1 commentaires | Partager sur WhatsApp
  • Il est possible de réunir dans un même document l’exploration, l’analyse, la visualisation, la mise en page et la diffusion de données avec un unique fichier HTML exécuté par le navigateur, ce qui réduit le flux classique notebook → outil de publication → PDF
  • L’implémentation centrale consiste à combiner des cellules echo qui affichent à l’écran style et script, contenteditable et l’Observable Runtime pour créer des cellules réactives éditables
  • cell(name, inputs, definition) suit le modèle de dépendances d’Observable afin de composer des unités d’exécution reliées entre elles, comme counter, un rendu FizzBuzz, des cellules masquées ou des cellules intermédiaires sans sortie
  • Le même document HTML fait la démonstration d’Observable Plot, TeX, Markdown, Graphviz, SQLite basé sur WASM, Python basé sur Pyodide, R basé sur WebR, Observable Inputs et de l’état Mutable
  • Le résultat est un document scientifique et technique qui s’exécute dans le navigateur sans plateforme séparée, et l’implémentation a ensuite été publiée sous forme de bibliothèque @celine/celine

Réduire la séparation notebook-publication à un seul fichier HTML

  • HTML est largement utilisé pour la mise en page, mais il a été relativement peu exploité comme plateforme d’exploration, d’analyse et de visualisation de données
  • Le flux de travail habituel passe par plusieurs outils
    • L’exploration, l’analyse et la visualisation sont réalisées dans des notebooks interactifs comme Jupyter, RStudio, Pluto.jl ou Observable
    • Le contenu est transféré vers une plateforme de publication comme Typst, Overleaf, LaTeX ou un éditeur WYSIWYG pour la mise en page
    • Il est exporté en .pdf pour la diffusion
  • Si un seul fichier HTML prend en charge ces trois étapes, cela réduit les procédures manuelles, les outils CLI, les étapes de CI et la dépendance à des plateformes tierces
  • L’implémentation est fortement influencée par In-browser code playgrounds d’Anton Zhiyanov, Self-modifying HTML notes de Cristóbal Sciutto, Quarto et Observable Framework

Créer des cellules éditables

  • La première étape consiste à rendre visibles tels quels dans le document les éléments style et script grâce à la classe CSS echo
  • En y ajoutant une police avec coloration syntaxique intégrée et l’attribut contenteditable, on peut s’en servir comme d’un éditeur de code basique
  • Un script auquel contenteditable est appliqué est réévalué lorsqu’il perd le focus
    • Le script existant est cloné pour créer un nouvel élément script, puis l’original est supprimé
    • Cette méthode est nécessaire, car eval ne fonctionne pas avec du code contenant des instructions import
  • Deux bibliothèques sont chargées pour l’exécution basée sur Observable
  • Seuls deux symboles, library et cell, sont exposés globalement

Flux de données réactif basé sur l’Observable Runtime

  • La fonction cell(name, inputs, definition, observerVisibility) définit une cellule en utilisant la portée de module de l’Observable Runtime
  • Si une variable portant le même nom existe déjà, elle est récupérée ; sinon, une nouvelle variable est créée et définie
    • Grâce à cette structure, lorsqu’une cellule contenteditable est réévaluée, la nouvelle définition se propage aux cellules connectées
  • L’Inspector d’Observable est utilisé pour afficher la sortie des cellules au-dessus du bloc script
  • La cellule counter est composée comme un générateur asynchrone qui émet un nombre chaque seconde
    • L’attribut id du script et l’argument name de cell sont identiques
    • Si l’on modifie la valeur initiale i puis que l’on retire le focus, la nouvelle valeur est prise en compte
  • On peut aussi créer des cellules qui dépendent de counter
    • Hypertext Literal est chargé pour rendre la valeur de counter sous forme de FizzBuzz
    • htl implémente un parseur HTML5 et gère l’échappement automatique ainsi que l’interpolation de valeurs non sérialisables comme les écouteurs d’événements, les objets de style et les nœuds DOM

Cellules visibles, masquées et sans sortie

  • Si l’on n’ajoute pas la classe echo, on peut masquer la définition de la cellule tout en observant sa sortie
    • Ce type de cellule peut servir de primitive de rendu
  • Il est aussi possible de créer un type de cellule qui n’affiche pas la sortie elle-même
    • silent(name, inputs, definition) définit observerVisibility sur masqué afin de pouvoir stocker des valeurs intermédiaires ou des structures de données
  • Les cellules peuvent fonctionner indépendamment de leur ordre de déclaration
    • Dans l’exemple, la cellule reallyNegative dépend de la cellule negative, déclarée plus tard
  • La même valeur de cellule est aussi utilisée pour des sorties plus complexes
    • Observable Plot est chargé pour tracer un tableau de nombres sous forme de courbe et afficher une règle verticale à la position counter % 40

Extension des sorties documentaires et de visualisation

  • Une cellule peut retourner n’importe quel élément DOM
  • Les démos TeX, Markdown et Graphviz retournent chacune des éléments de formes différentes
    • La cellule tex retourne un élément span
    • La cellule md retourne un élément table
    • La cellule dot retourne un élément svg
  • Une cellule peut retourner une Promise ou lancer une Error
    • L’Inspector d’Observable applique la classe observablehq--running au div extérieur d’une cellule en cours d’exécution
    • Il applique la classe observablehq--error aux cellules en erreur
    • Le document définit son style en fonction de ces états

SQLite, Python et R dans le navigateur

Entrées et état mutable

  • Le type de cellule viewof est créé pour être utilisé avec Observable Inputs
  • viewof déclare deux cellules réactives
    • NAME : la valeur de l’entrée
    • viewof NAME : l’élément DOM lui-même
  • Pour afficher l’entrée au-dessus de la cellule, il faut définir l’id de la cellule sur viewof NAME
  • Dans l’exemple, une entrée de plage est créée avec Inputs.range([0, 100], { step: 1 }), et la cellule rangePlot est mise à jour en fonction de cette valeur
  • Le fonctionnement d’Observable Inputs est assez déroutant, et la démo Synchronized Inputs peut aider
  • Pour les cas où un flux de données purement fonctionnel ne suffit pas, un helper mutable est aussi créé
    • mutable enregistre un objet Mutable qui émet une nouvelle valeur lorsque la valeur change

Publication de la bibliothèque et diapositives de présentation

  • Cette implémentation devait d’abord s’appeler incel, puis a ensuite été envisagée sous le nom celine
  • La bibliothèque est publiée sous le nom @celine/celine
  • Ce document a été présenté en démo à SydJS
  • Du code est aussi inclus pour transformer le document en diaporama
    • Shift+N : démarrer le diaporama ou passer à la diapositive suivante
    • Shift+B : diapositive précédente
    • Shift+E : quitter le diaporama
  • Le code de l’implémentation est disponible sous forme de source code

1 commentaires

 
GN⁺ 2024-11-19
Avis sur Hacker News
  • Je suis fortement d’accord avec le postulat de l’article. HTML peut constituer une excellente base pour des notebooks computationnels.
    Cela dit, les choix d’implémentation ici ne me plaisent pas. Du HTML dynamique et réactif peut être rendu bien plus déclaratif que cela, et Observable est génial, mais il s’écarte par certains aspects du JavaScript standard.
    J’ai commencé à créer un système de HTML réactif appelé Heximal, auquel j’ajouterai plus tard la prise en charge des notebooks. C’est un système déclaratif basé sur des templates HTML et des éléments personnalisés, avec par-dessus un système d’expressions/réactivité fondé sur la proposition TC39 Signals.
    https://github.com/elematic/heximal
    Cela ressemble plutôt à un mélange de HTMX, Tangle, Curvenote et Polymer, et j’imagine que c’est à cela que ressemblerait HTML s’il avait été réactif dès le départ. Je pense que cela conviendrait assez bien aux cas d’usage d’édition graphique et de notebooks.

    • Dire qu’« Observable est génial, mais s’écarte du JS standard » est vrai côté frontend, mais le runtime sous-jacent exécute simplement du JavaScript. Le code source ressemble aussi beaucoup à du JavaScript avec de petites macros entièrement contenues dans le parseur acorn sous licence MIT.
      C’est pourquoi les expressions de débogage JavaScript ordinaires fonctionnent correctement dans Observablehq.
      https://github.com/observablehq/parser
      J’aime tellement le runtime Observable que j’ai aussi créé un décompilateur capable de convertir dans les deux sens entre le code source frontend et la représentation compilée en JS pur.
      https://observablehq.com/@tomlarkworthy/observablejs-toolcha...
    • Je me demande si Observable Framework a été pris en compte ici. Il est sorti en mars, et l’une de ses principales caractéristiques était d’utiliser du JavaScript standard, plutôt que les bidouillages syntaxiques créés pour Observable Notebooks : https://observablehq.com/blog/observable-2-0#a-better-develo...
  • Vraiment excellent. J’ai particulièrement aimé la démo Python et SQLite. C’est intéressant de partir d’une boucle d’édition via le Web (TTW) et d’appeler cela une quine ; c’est défendable, mais le principal point faible reste la persistance.
    TiddlyWiki fait en fait à peu près la même chose, mais l’enregistrement du travail est problématique. Car pour rendre quelque chose persistant, il faut au bout du compte un processus serveur headless distinct.
    Quand j’ai voulu construire quelque chose de similaire[0], j’ai personnellement commencé par la persistance, ce qui voulait évidemment dire des fichiers. Des fichiers en texte brut, éditables avec un éditeur pour programmeurs et stockables/déployables via le système de fichiers. Cela permet d’éviter d’avoir à réimplémenter un éditeur pour programmeurs dans le navigateur, ce qui est loin d’être trivial.
    En contrepartie, il faut écrire un serveur rapide, mais c’est aussi un problème assez amusant[1]. Ici, ce problème a été évité en utilisant des sections contenteditable de base, mais c’est le plus gros sujet après la persistance.
    L’impossibilité de faire des export dans les scripts embarqués me semble relever du même mur. Ce serait utile pour éviter d’encombrer l’objet global window, et dans mon cas d’usage cela faciliterait aussi la génération de code.
    0 - Literate Markdown : https://simpatico.io/lit.md
    1 - Reflector, un petit serveur node qui transforme, compresse et met en cache du Markdown, avec invalidation par surveillance de fichiers : https://simpatico.io/reflector

  • Je respecte la réflexion et les efforts investis, mais l’utilisabilité de cette approche est atroce. Je ne vois pas pourquoi, alors qu’on essaie de faire de l’analyse exploratoire de données, il faudrait aussi se préoccuper d’éléments de style.
    C’est précisément pour cela que des outils comme les notebooks Jupyter fonctionnent bien. Cela dit, j’apprécie beaucoup la curiosité et le fait d’avoir concrétisé une idée alternative.

    • Auteur : malheureusement, je suis d’accord moi aussi pour dire que l’utilisabilité de cette méthode est atroce, et c’est une grande partie de ce qui m’a motivé à créer @celine/celine (https://maxbo.me/celine, autrement dit empaqueter l’article sous forme de bibliothèque).
      Ce n’est pas encore suffisant comme plateforme d’analyse exploratoire de données. Il n’y a pas la réactivité immédiate d’un véritable éditeur de code web comme Observable Notebooks, ni le hot reloading basé sur la surveillance de fichiers qu’offre Observable Framework. Le nouveau kernel Jupyter pour Deno + VSCode offre lui aussi une expérience assez fluide.
      Donc, pour l’utilisabilité en analyse exploratoire, euh… je suis d’accord pour dire qu’elle est mauvaise, mais je trouve que l’utilisabilité pour la diffusion n’est pas si mauvaise. En fait, elle est bonne. Tout simplement parce que c’est un fichier unique. Si l’on veut envoyer à quelqu’un un graphe et des résultats de traitement de données, pas besoin de maintenir une énorme toolchain ni de payer un service tiers : il suffit de déposer un fichier HTML dans Slack ou de l’héberger quelque part.
      La flexibilité qui permet de styliser les résultats d’analyse permet aussi de les publier dans des contextes où le style compte, comme un blog ou un article de recherche.
    • À première vue, on dirait qu’ils essaient de positionner ça du côté de « l’analyse exploratoire du DOM ». La démo d’introduction a un côté Scheme/Smalltalk, dans la manière de construire progressivement la structure et les éléments de base, et le moment où le remplacement de ivory par red modifie la coloration syntaxique en temps réel l’illustre bien.
      Je comprends le cheminement qui a mené jusque-là, mais je trouve dommage qu’il ne soit pas plus facile de jouer avec des frameworks et bibliothèques JavaScript dans le navigateur. Au bout du compte, ce n’est que du JS, et on devrait pouvoir expérimenter rapidement dans un environnement léger. Cette approche est forte sur ce point.
      C’est une manière de retrouver le potentiel ludique et expérimental de HTML/JS. J’aimerais voir davantage d’initiatives de ce genre plutôt que TS, rollup, webpack, etc.
      Ajout : après avoir lu un peu plus, je vois que c’est proposé pour l’analyse de données. Je ne pense pas que ce soit très adapté à cet usage.
    • On dit « alors qu’on essaie juste de faire de l’analyse exploratoire de données », mais le point essentiel n’est-il pas d’avoir une plateforme intégrée permettant de faire de l’analyse exploratoire de données puis d’en publier facilement les résultats ? Ce n’est pas destiné à des notebooks Jupyter jetables.
      Je pense qu’il y a beaucoup de valeur dans une alternative aux notebooks Jupyter qui ne finissent pas simplement à la poubelle. L’expérience utilisateur actuelle est vraiment médiocre, mais cela peut être amélioré. La question est de savoir si cette configuration est meilleure que le chaos JSON des notebooks Jupyter ; personnellement, j’aurais tendance à dire que oui.
  • L’auteur original de Lit a récemment quitté Google et, à ma connaissance, travaille sur quelque chose de très similaire.
    https://github.com/elematic/heximal

    • Je ne savais pas qu’il avait rendu public ce sur quoi il travaillait ensuite. Merci pour l’info.
  • J’aime le format de cet article. Il part de zéro et construit progressivement quelque chose d’intéressant. Ce n’est pas une fuite en avant tape-à-l’œil consistant à empiler des dépendances ou à greffer des frameworks dans tous les sens.
    Pour suivre, il me semble qu’il suffit de copier-coller les fragments proposés et de comprendre étape par étape comment ils fonctionnent. Si j’écrivais quelque chose comme ça, je pense que je le ferais en programmation lettrée avec org-mode, puis que je l’exporterais en HTML pour en faire un billet de blog.
    En revanche, une police avec coloration syntaxique intégrée continue de me laisser perplexe.

  • On parle de HTML réactif, mais est-ce que ce n’est pas presque entièrement du JavaScript, ou est-ce que j’ai mal compris quelque chose ?

    • La partie interaction/réactivité est en JavaScript, mais le notebook est implémenté dans un fichier HTML autonome. Il gère tout, depuis la structure du document jusqu’à l’édition et l’affichage.
      À part le navigateur, il ne dépend d’aucun logiciel tiers ; comme HTML, il est durable, portable et facile à utiliser.
    • Ça donne l’impression de dire : « Pourquoi tout le monde utilise Colab ou Observable pour faire tourner des notebooks dans le navigateur ? Bon, quoi qu’il en soit, je vais proposer une alternative qui utilise Observable pour les parties difficiles. »
  • J’essaierai bientôt de prendre en charge ce type de notebook HTML dans Raku, ou pour Raku.
    Actuellement, les « solutions de notebook » de Raku sont soit basées sur Jupyter, soit sur Mathematica.

  • Je ne comprends pas bien l’argument qui consiste à rendre ce processus plus complexe en y ajoutant des technologies web. Quel problème cette complexité supplémentaire résout-elle ? Au contraire, cela semble plutôt ralentir le processus et supprimer des fonctionnalités nécessaires comme l’autocomplétion, les snippets et les extensions.
    En plus, il y a de fortes chances que les autres ne soient pas habitués à cette configuration, ce qui rend aussi la collaboration plus difficile.
    Il suffit de configurer l’environnement une fois, puis de continuer à l’utiliser en ajoutant seulement de petites améliorations au fil de l’évolution des technologies.
    Pour les utilisateurs de n/vim, ce qui suit suffit largement. 1- Exploration des données : utiliser https://github.com/untitled-ai/jupyter_ascending pour relier du texte à un notebook Jupyter. Comme cela utilise jupytext, on peut éditer et exécuter efficacement du code depuis un éditeur de texte.
    2- Rédaction : pour LaTeX, on peut utiliser https://github.com/lervag/vimtex.
    En ajoutant tmux et tmuxp par-dessus, on peut ouvrir un projet instantanément. Dans Emacs, org mode[1][2] et/ou Auctex permettent de mettre en place un processus fluide.
    [1] https://sqrtminusone.xyz/posts/2021-05-01-org-python/
    [2] https://martibosch.github.io/jupyter-emacs-universe/

    • Quand on ouvre un notebook Jupyter dans le navigateur, quelle technologie utilise-t-on ? Quand on ouvre le site web de l’OP, quelle technologie utilise-t-on ?
    • C’est globalement une bonne remarque.
      Cela dit, comme je n’aime pas particulièrement Python, j’ai envie d’utiliser des outils qui ne soient pas centrés sur Python. C’est pour cela que j’ai parlé de Raku et de Mathematica.
      Au passage, merci de m’avoir signalé https://github.com/imbue-ai/jupyter_ascending.
    • D’accord. Les personnes qui veulent des notebooks réactifs devraient envisager sérieusement Emacs. Beaucoup d’utilisateurs n’utilisent Emacs que pour quelques usages, et les notebooks réactifs en font souvent partie.
  • Je suis globalement d’accord avec le postulat de cet article, à savoir que HTML est sous-exploité comme support de diffusion pour l’écriture scientifique.
    Il y a des travaux récents de Will Crichton sur ce sujet.
    https://willcrichton.net/nota/
    https://willcrichton.net/notes/portable-epubs/.

  • Les notebooks ont clairement le vent en poupe en ce moment. Nous avons aussi lancé une version de notebook TypeScript[1], mais nous avons fait des choix assez différents en termes de compromis.
    Comme nous voulons exécuter du code backend node, contrairement à l’approche de cet article ou à Observable, nous n’essayons pas de l’exécuter dans un environnement navigateur. Cela dit, pour beaucoup d’applications, cette idée peut être une meilleure solution.
    Bravo à l’auteur.
    https://github.com/srcbookdev/srcbook