Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

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

オープン
#1,133 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
3/5
見積もり時間
1〜2日
初心者へのやさしさ
70/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
markdown, typescript

調査の方向性

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.

索引モデルが issue の本文から書いたものです。

説明

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

主要言語
TypeScript
スター
652
フォーク
64
平均マージ
8時間 45分
マージ済み PR(30日)
36

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

quarto-dev/quarto のほかの issue

quarto-dev/quarto の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。