Visual Editor silently drops empty attributed spans ([]{.class …}) on a Source↔Visual round-trip
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Aptitud para principiantes
- 70/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- markdown, typescript
- Área
- devtools, documentation
Línea de trabajo
The issue is in the panmirror editor's representation of empty spans. Start by examining packages/editor/src/marks/span.ts to understand how spans are modeled as ProseMirror marks. Then look at packages/editor/src/pandoc/pandoc_to_prosemirror.ts for the reading logic and the corresponding writing logic. The fix likely involves creating a placeholder node or handling empty spans specially to preserve their attributes. Test by modifying the editor and verifying that empty attributed spans survive a source-visual-source round-trip.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Bug description
Originally reported downstream
When a document contains an empty attributed span — []{.class key="val"} with no text between the brackets — the Visual Editor deletes it on the first Source → Visual → Source round-trip. A non-empty span ([text]{.class …}) round-trips correctly. The deletion is silent (no warning), so it is easy to lose content.
Steps to reproduce
Start with this Markdown in Source mode:
Before []{.comment remark="EMPTY SPAN TEST"} after.
Before [some words]{.comment remark="NONEMPTY SPAN TEST"} after.
Switch to Visual mode, then back to Source mode, without making any edit. Result:
Before after.
Before [some words]{.comment remark="NONEMPTY SPAN TEST"} after.
The standalone empty span is gone; the one wrapping text remains.
Actual behavior
The empty span (and its attributes) is removed entirely.
This is not Pandoc — it's the editor's document model
Round-tripping the same input through the Pandoc that Quarto bundles preserves both spans, so nothing in Pandoc/Quarto strips it:
printf 'Before []{.comment remark="x"} after.\n' | quarto pandoc -f markdown -t markdown
# -> Before []{.comment remark="x"} after. (empty span preserved)
The loss happens in panmirror (the Visual Editor's ProseMirror layer). A span is modeled as a ProseMirror mark, not a node — see packages/editor/src/marks/span.ts: the Pandoc Span token is read as a mark applied to the span's children (getChildren), and written back by re-wrapping those children.
A ProseMirror mark can only exist on text. An empty span has no children, so:
- on read, there is nothing for the mark to attach to → the mark (and its attributes) is dropped;
- on write-back, there is no marked text → no
Spantoken is emitted.
This is consistent with the reader, which guards text creation with if (!text) return in pandoc_to_prosemirror.ts, and with prosemirror-model itself, where schema.text("") throws RangeError: Empty text nodes are not allowed — so an empty span can never produce an anchor node.
A non-empty span has children to carry the mark, which is exactly why it round-trips fine.
Impact
Any extension relying on empty attributed spans loses that content silently whenever the author touches the Visual Editor. Because it is a consequence of the "span = mark" modeling, no extension-side setting can recover it — it needs handling in the editor.
Expected behavior
Empty attributed spans are valid Pandoc AST and should survive the round-trip unchanged, exactly like non-empty ones. They are used by real extensions (e.g. annotation/comment tooling) to attach metadata at a point in the text, so dropping them is data loss.
Could you reserve empty attributed spans across the round-trip — e.g. by representing an empty span as a small node/anchor rather than a mark with no content, so its attributes survive ? Even preserving it as a raw/verbatim inline would avoid the silent data loss.
Your environment
The root cause is at the editor-model level (panmirror), so it is not expected to be platform- or IDE-specific (RStudio and the VS Code Quarto visual editor share panmirror).
Initial poster (@gasperploj) environment :
- Quarto: 1.9.38
- RStudio: 2026.07.0 Build 139
- OS: Windows 10
Also reproduced by myself via the bundled Pandoc for the AST checks above on macOS / Quarto 1.10.18
- Lenguaje dominante
- TypeScript
- Estrellas
- 652
- Forks
- 64
- Merge medio
- 8 h 45 min
- PR fusionados (30 d)
- 36
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de quarto-dev/quarto
-
VS Code extension: `quarto preview` fails when the file path contains parentheses (path not shell-quoted)Posiblemente ocupada @Bondrewd-K la tomó hace 3 días. Abiertobug vscode
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
quarto-dev/quarto#1194 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
quarto-dev/quarto#1139 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 1-3 horas Aptitud para principiantes 90/100
quarto-dev/quarto#1138 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
quarto-dev/quarto#1137 ·
Los mantenedores suelen responder en 1 día
-
Add dependabot?Quizá libre de nuevo Un pull request para esta issue se cerró sin fusionarse. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
quarto-dev/quarto#1135 ·
Los mantenedores suelen responder en 1 día
Todos los issues de quarto-dev/quarto
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 73/100
anomalyco/opencode#56380 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
enhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
-
BUG | `MCP 服务器` | 全局层行的停用/启用与删除报 404 server row not found,编辑保存会在 profile 层复制出重复行Posiblemente ocupada @w6242652 la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Chocobozzz/PeerTube#7832 ·
Los mantenedores suelen responder en 3 días
-
Pay to use?Abierto
Dificultad 1/5 Menos de una hora Aptitud para principiantes 66/100
darkreader/darkreader#16108 · 1 comentario ·
Los mantenedores suelen responder en 2 días