Skip to content

ADF quoting: inline content inside a blockquote-illegal node is flattened to text #68

Description

@Hinne1

Found while verifying the --reply-to ADF quoting fix (branch claude/reply-to-adf-quoting).

Behaviour

QuoteADF copies blockquote-legal nodes verbatim. A node the content model rejects (heading, table, panel, expand) is flattened with ADFToText. For a node whose children are inline, that flattening is lossy in three ways at once.

Input — a heading with mixed inline runs:

heading[ text("Fixture heading for "), mention(@Hinne Stolzenberg), text(" with inline") ]

Quoted output:

paragraph[ text("## Fixture heading for@Hinne Stolzenbergwith inline") ]

Three losses: the mention node becomes plain text (no notification, no link), the ## markdown prefix leaks into the visible text, and the spaces between adjacent inline runs are eaten.

Not a regression

ADFToText returns byte-identical output on the same input, and the pre-fix code applied that flattening to the entire comment. The current code applies it only to illegal nodes, so this is strictly less lossy than before — but it is the last remaining fidelity gap in quoting.

Suggested fix

For an illegal node whose content is inline, rebuild its children into a paragraph rather than calling ADFToText: keep mention/text nodes as nodes, preserving marks and spacing. paragraph is blockquote-legal, so the result is valid; only the heading level is lost, which a blockquote cannot express anyway.

Reproduction (drop into internal/api, no network needed):

func TestHeadingInlineFlatten(t *testing.T) {
	doc := &ADF{Type: "doc", Version: 1, Content: []ADFContent{{
		Type:  "heading",
		Attrs: &ADFAttrs{Level: 2},
		Content: []ADFContent{
			{Type: "text", Text: "Fixture heading for "},
			{Type: "mention", Attrs: &ADFAttrs{ID: "acc-1", Text: "@Hinne Stolzenberg"}},
			{Type: "text", Text: " with inline"},
		},
	}}}
	q := QuoteADF(doc)
	t.Logf("%q", q.Content[0].Content[0].Text)
	// got: "## Fixture heading for@Hinne Stolzenbergwith inline"
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions