Review #6 (approve-with-comments) follow-ups: 1. canonicalize step 7 now strips bare footnoteDefinitions at ANY depth (stripFootnoteDefinitionsDeep), not just footnotesList, in BOTH copies. A definition hand-authored outside a list (e.g. nested in a callout via a raw-JSON write path) was left in place while a copy was also added to the rebuilt list -> duplicate, idempotent, self-perpetuating. Runs only in the rebuild path (after the lists are stripped); the fast-path / placement-keep branch is untouched. Added a shared-corpus case (bare def nested in a callout) to pin it in both mirrors. 2. markdown-clipboard: removed the dead top-level footnoteReference check in canonicalizePastedFootnotes (an inline atom is never a top-level slice child; only the descendants scan can find it). Test coverage: 4. New MCP binding tests (full-doc-write-canonicalize.test.mjs): update_page_json and copy_page_content canonicalize the persisted full doc, asserted via a new `replacePage` seam (symmetric to the existing `mutatePage` seam) so no live collab socket is needed. Routed both writers through the seam. 5. New server spec (file-import-task.service.footnote-canonicalize.spec.ts): the zip-import path (processGenericImport) canonicalizes footnotes — real markdown->HTML->JSON via a real ImportService over a temp-dir .md file, DB trx stubbed to capture the persisted page content. FileImportTaskService had no spec before. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1256 lines
27 KiB
JavaScript
1256 lines
27 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": "bare footnoteDefinition nested in a callout is collected, NOT duplicated",
|
|
"input": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "see "
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "a"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "callout",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "a"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "note A"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"expected": {
|
|
"type": "doc",
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "see "
|
|
},
|
|
{
|
|
"type": "footnoteReference",
|
|
"attrs": {
|
|
"id": "a"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "callout",
|
|
"content": []
|
|
},
|
|
{
|
|
"type": "footnotesList",
|
|
"content": [
|
|
{
|
|
"type": "footnoteDefinition",
|
|
"attrs": {
|
|
"id": "a"
|
|
},
|
|
"content": [
|
|
{
|
|
"type": "paragraph",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "note A"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"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"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
];
|