Must-fix: - Move canonicalizeFootnotes OUT of parseProsemirrorContent. It now runs only on FULL writes (createPage, updatePageContent operation==='replace'), never on an append/prepend fragment (a fragment would lose definition-only footnotes or synthesize a bogus empty list). Add a server binding spec. - Match the live plugin's list PLACEMENT: a single already-canonical footnotesList is left exactly where it sits (the plugin never repositions a sole correct list), so the first write no longer reorders content that follows the list. Applied to BOTH the editor-ext copy and the MCP mirror; pinned by a shared golden corpus case with content after the list. - Fix MCP tool count 38 -> 39 (README x3, AGENTS.md) and the transformJs param help (add canonicalizeFootnotes/insertInlineFootnote). Simplifications: - Remove the dead duplicate re-id mechanism (deriveFootnoteId/suffix/occurrence) from the PURE canonicalizer in both copies — references are never renamed, so the derived ids were never requested; first-wins-drop is the real behaviour. This also makes the editor-ext footnote-util note about "no cross-package copy" true again. - Remove the sentinel round-trip in insertInlineFootnote: a generalized insertNodesAfterAnchor core inserts the footnoteReference node directly. - Drop the redundant per-definition deep clone in step 4 (shallow id-normalizing copy; out is already deep-cloned). Docs / architecture: - Correct the editor-ext copy's "It exists because…" header to its real consumers (server import, page.service create/update, client paste). - Note markdownToProseMirror reuse for create/update comment in collaboration.ts. - A: shared golden JSON corpus exercised by BOTH the editor-ext copy and the MCP mirror (footnote-corpus.ts / .mjs) so "the two copies behave identically" is checkable. - C: split the MCP canonicalizer into a pure mirror + footnote-authoring.ts. - B: import services persist via a different path, so left one-line consolidation comments at the call sites rather than folding (does not fall out cleanly). Tests: insertFootnote wrapper guards + docmost_transform dryRun auto-canonicalize (MCP mock), page.service create/update + append/prepend binding (server jest), shared corpus incl. nested-container reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1165 lines
25 KiB
JavaScript
1165 lines
25 KiB
JavaScript
// MIRROR (data only) of
|
|
// packages/editor-ext/src/lib/footnote/footnote-corpus.ts — keep the two in
|
|
// sync. Shared golden corpus for the footnote canonicalizer (issue #228): each
|
|
// case is { name, input, expected } where `expected` is exactly what
|
|
// `canonicalizeFootnotes(input)` must return. Running BOTH the editor-ext copy
|
|
// and this MCP mirror against the same corpus makes "the two pure copies behave
|
|
// identically" a checkable property without coupling the packages.
|
|
export const FOOTNOTE_CORPUS = [
|
|
{
|
|
"name": "out-of-order defs ordered by first reference",
|
|
"input": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "x"
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "b"
|
|
}
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "a"
|
|
}
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "d"
|
|
}
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "c"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "a"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "A"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "c"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "C"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "b"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "B"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "d"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "D"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"expected": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "x"
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "b"
|
|
}
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "a"
|
|
}
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "d"
|
|
}
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "c"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "b"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "B"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "a"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "A"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "d"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "D"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "c"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "C"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"name": "orphan definition dropped",
|
|
"input": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "x"
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "a"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "a"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "A"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "orphan"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "O"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"expected": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "x"
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "a"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "a"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "A"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"name": "no references removes the list",
|
|
"input": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "plain"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "orphan"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "O"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"expected": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "plain"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"name": "reuse: repeated references collapse to one definition",
|
|
"input": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "d"
|
|
}
|
|
},
|
|
{
|
|
"type": "text",
|
|
"text": " a "
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "d"
|
|
}
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "d"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "d"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "shared"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"expected": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "d"
|
|
}
|
|
},
|
|
{
|
|
"type": "text",
|
|
"text": " a "
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "d"
|
|
}
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "d"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "d"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "shared"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"name": "duplicate definitions: first wins",
|
|
"input": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "x"
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "d"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "d"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "first"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "d"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "second"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "d"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "third"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"expected": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "x"
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "d"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "d"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "first"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"name": "synthesizes an empty definition for a reference with none",
|
|
"input": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "x"
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "missing"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"expected": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "x"
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "missing"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "missing"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"name": "merges multiple footnotesList nodes into one",
|
|
"input": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "a"
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "x"
|
|
}
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "y"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "x"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "X"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "tail"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "y"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "Y"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"expected": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "a"
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "x"
|
|
}
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "y"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "tail"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "x"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "X"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "y"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "Y"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"name": "single canonical list before a trailing empty paragraph stays put",
|
|
"input": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "x"
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "a"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "a"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "A"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "paragraph"
|
|
}
|
|
]
|
|
},
|
|
"expected": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "x"
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "a"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "a"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "A"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "paragraph"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"name": "single canonical list with NON-EMPTY content after it is NOT moved (plugin parity)",
|
|
"input": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "x"
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "a"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "a"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "A"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "epilogue text"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"expected": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "x"
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "a"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "a"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "A"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "epilogue text"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"name": "reference inside a nested container (callout) is collected",
|
|
"input": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "callout",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "see "
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "n"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "n"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "note"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"expected": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "callout",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "see "
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "n"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "n"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "note"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"name": "no footnotes at all is unchanged",
|
|
"input": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "just text"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"expected": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "just text"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
];
|