ADR 0086 — El código de la ficha, con editor
Estado: aceptado · Fecha: 2026-10-27
Contexto
Sección titulada «Contexto»La ficha enseña el código del símbolo abierto en un bloque propio, con sus números de línea, una fila por línea y un resaltado con Prism (ADR 0067). La muestra no es corta: la plataforma sirve cientos de líneas y un símbolo grande llega a 770.
El ADR 0085 retiró la pestaña del fichero entero porque montar mil líneas resaltadas congelaba la app, y dejó abierto «medir y trocear el pintado». Faltaba saber si ese coste era del resaltado, del CSS o del montaje, y si una herramienta lo resolvía.
Se construyó el prototipo con CodeMirror 6 y se midió el mismo símbolo —useCodarchApp.tsx, líneas
195–964— en la app real, con PerformanceObserver y performance.measure:
| Camino | Montaje | Tarea más larga | Nodos en el DOM | Líneas pintadas |
|---|---|---|---|---|
<pre> con Prism | — | 21.785 ms | 5.809 | 770 |
| CodeMirror 6 | 17 ms (10–20 tras el arranque) | ninguna | 172 | 16 |
Las dos piezas que se podían culpar no lo explican: el resaltado de esas 770 líneas son 16,1 ms (la peor línea, 3,3 ms) y una maqueta equivalente de 8.470 nodos se compone en 66,8 ms. El bloqueo lo paga el montaje del árbol. CodeMirror no lo paga porque pinta solo el viewport.
También se midió lo que se descartó: Shiki cuesta 27 ms por bloque de 400 líneas más 48 ms de
arranque, con una gramática de 190 kB; content-visibility: auto baja el layout de 1.000 líneas de
33 a 16 ms, pero no toca el montaje.
Decisión
Sección titulada «Decisión»- La ficha pinta el código con CodeMirror 6, no con un
<pre>de Prism. El bloque gana la canaleta del fichero, la envoltura de líneas y la selección nativa, y pierde la tarea de 21,8 s. - Solo lectura.
EditorState.readOnlyyEditorView.editableen falso, sin historia, sin autocompletado y sin teclas propias:Escy el retroceso siguen siendo del mapa. - Los colores son los de la casa. El editor no trae tema: sus tokens usan las clases
.token.*destyles.css, sobre el mismo marco y el mismo fondo que el bloque anterior, así que no hay dos paletas para lo mismo. - Carga diferida. El editor vive en su propio trozo (
CodeEditor, 371 kB; 127 kB gzip), que solo se descarga al abrir el código de un símbolo. El arranque del mapa no crece. - La canaleta numera el fichero. La primera línea de la muestra es la que dice la plataforma: en el prototipo, 195–964 se ven como 195, 196, 197.
- Prism sale de la UI.
highlight.tsy su test se retiran con el<pre>: el resaltado ya no se hace línea a línea, y eso arregla de paso el color partido de los comentarios y las cadenas de varias líneas. - El número manda. Si el montaje de una muestra vuelve a pasar de ~50 ms o aparece una tarea
larga al abrir el código, se mide otra vez con
codarch-code-mountantes de dar nada por bueno.
Consecuencias
Sección titulada «Consecuencias»@codarch/uicambiaprismjspor cinco paquetes de CodeMirror (state,view,language,lang-javascripty@lezer/highlight).- El DOM de la ficha pasa de 5.809 nodos a 172 en el caso grande: el panel deja de arrastrar el bloque al hacer scroll o al cambiar de pestaña.
- El código ya no se puede editar desde la app; el botón Editor sigue abriendo el editor del usuario, que es donde se escribe (ADR 0068).
- El primer símbolo que se abre paga la descarga del trozo; en local es un fichero más y en el escritorio va dentro del paquete.
- El ADR 0067 sigue vigente en todo lo demás: el snapshot no guarda código y la plataforma sirve el fragmento.
- Queda una pregunta abierta para el 0085: con el editor puesto, ver el fichero entero ya no exige trocear el pintado a mano.
Alternativas descartadas
Sección titulada «Alternativas descartadas»- Dejar el
<pre>y virtualizar a mano con@tanstack/react-virtual. Habría que trocear las filas, la canaleta y la envoltura, y el coste de montar 5.809 nodos seguiría ahí en cada apertura. - Seguir con Prism y dar el problema por resuelto con «es solo un marco». Medido, es una tarea de 21,8 s: no es un marco, es una congelación.
- Shiki, que ya estaba en
node_modulespor Astro. Diez veces más lento por bloque y 190 kB de gramática, y no resuelve el montaje: seguiría pintando todas las líneas. - Mónaco. Megas, workers y un aspecto de VS Code para leer un símbolo.
content-visibility: autosobre el<pre>. Barato y sin dependencia, pero solo baja el layout: el montaje de React y elinnerHTMLde cada fila se pagan igual.
Hoja de ruta
Sección titulada «Hoja de ruta»El código de la ficha
Sección titulada «El código de la ficha»- Medir el resaltado de Prism con líneas reales: 16,1 ms en 770 líneas.
- Medir el montaje del
<pre>en la app: una tarea de 21.785 ms y 5.809 nodos. - Medir Shiki y
content-visibilitycomo alternativas parciales. - Prototipo con CodeMirror 6: 17 ms de montaje, 172 nodos, 16 líneas pintadas.
- Cambiar la ficha al editor, de solo lectura y en su propio trozo, y retirar Prism.
- Ver el fichero entero en el escenario con esta base (ADR 0087).
- Comprobar el trozo diferido en el escritorio empaquetado (evidencia 2026-11-02:
npm run package:dir --workspace @codarch/desktop; el asar incluye el chunkCodeEditor-CQTiFMcc.jscon import relativo desde el índice; Vitebase: './').
El registro de lo hecho vive en el feed de la guía.