Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

Visual Editor silently drops empty attributed spans ([]{.class …}) on a Source↔Visual round-trip

Abierto
#1,133 0 comentarios 0 reacciones 0 asignados Ver en GitHub

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

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 visual-editor
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 Span token 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

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de quarto-dev/quarto

Todos los issues de quarto-dev/quarto

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.