diff --git a/packages/core/src/api/exporters/html/util/serializeBlocksExternalHTML.ts b/packages/core/src/api/exporters/html/util/serializeBlocksExternalHTML.ts index fb993f8309..894c0f1c1b 100644 --- a/packages/core/src/api/exporters/html/util/serializeBlocksExternalHTML.ts +++ b/packages/core/src/api/exporters/html/util/serializeBlocksExternalHTML.ts @@ -319,7 +319,13 @@ function serializeBlock< } } - if (editor.pmSchema.nodes[block.type as any].isInGroup("blockContent")) { + if ("childrenDOM" in ret && ret.childrenDOM) { + // block specifies where children should go (e.g. toggle blocks + // place children inside
) + ret.childrenDOM.append(childFragment); + } else if ( + editor.pmSchema.nodes[block.type as any].isInGroup("blockContent") + ) { // default "blockContainer" style blocks are flattened (no "nested block" support) for externalHTML, so append the child fragment to the outer fragment fragment.append(childFragment); } else { diff --git a/packages/core/src/blocks/Heading/block.ts b/packages/core/src/blocks/Heading/block.ts index c5727b8ec9..38f058b775 100644 --- a/packages/core/src/blocks/Heading/block.ts +++ b/packages/core/src/blocks/Heading/block.ts @@ -1,6 +1,6 @@ -import { createBlockConfig, createBlockSpec } from "../../schema/index.js"; import { BlockNoteEditor } from "../../editor/BlockNoteEditor.js"; import { createExtension } from "../../editor/BlockNoteExtension.js"; +import { createBlockConfig, createBlockSpec } from "../../schema/index.js"; import { addDefaultPropsExternalHTML, defaultProps, @@ -110,6 +110,20 @@ export const createHeadingBlockSpec = createBlockSpec( const dom = document.createElement(`h${block.props.level}`); addDefaultPropsExternalHTML(block.props, dom); + if ("isToggleable" in block.props && block.props.isToggleable) { + const details = document.createElement("details"); + details.setAttribute("open", ""); + const summary = document.createElement("summary"); + summary.appendChild(dom); + details.appendChild(summary); + + return { + dom: details, + contentDOM: dom, + childrenDOM: details, + }; + } + return { dom, contentDOM: dom, diff --git a/packages/core/src/blocks/ListItem/ToggleListItem/block.ts b/packages/core/src/blocks/ListItem/ToggleListItem/block.ts index 02b69d4e5b..0052faab09 100644 --- a/packages/core/src/blocks/ListItem/ToggleListItem/block.ts +++ b/packages/core/src/blocks/ListItem/ToggleListItem/block.ts @@ -39,13 +39,20 @@ export const createToggleListItemBlockSpec = createBlockSpec( }, toExternalHTML(block) { const li = document.createElement("li"); + const details = document.createElement("details"); + details.setAttribute("open", ""); + const summary = document.createElement("summary"); const p = document.createElement("p"); + summary.appendChild(p); + details.appendChild(summary); + addDefaultPropsExternalHTML(block.props, li); - li.appendChild(p); + li.appendChild(details); return { dom: li, contentDOM: p, + childrenDOM: details, }; }, }, diff --git a/packages/core/src/schema/blocks/types.ts b/packages/core/src/schema/blocks/types.ts index 06270c6d82..dd8c3351f8 100644 --- a/packages/core/src/schema/blocks/types.ts +++ b/packages/core/src/schema/blocks/types.ts @@ -146,6 +146,7 @@ export type LooseBlockSpec< | { dom: HTMLElement | DocumentFragment; contentDOM?: HTMLElement; + childrenDOM?: HTMLElement; } | undefined; @@ -203,6 +204,7 @@ export type BlockSpecs = { | { dom: HTMLElement | DocumentFragment; contentDOM?: HTMLElement; + childrenDOM?: HTMLElement; } | undefined; }; @@ -476,6 +478,7 @@ export type BlockImplementation< | { dom: HTMLElement | DocumentFragment; contentDOM?: HTMLElement; + childrenDOM?: HTMLElement; } | undefined; diff --git a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/basicBlocks.html b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/basicBlocks.html index f153e57c2e..0854870529 100644 --- a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/basicBlocks.html +++ b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/basicBlocks.html @@ -14,7 +14,11 @@

Heading 1

Check List Item 1

  • -

    Toggle List Item 1

    +
    + +

    Toggle List Item 1

    +
    +
  • diff --git a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/basicBlocksWithProps.html b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/basicBlocksWithProps.html
    index 1eacf47eb2..782aab8b66 100644
    --- a/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/basicBlocksWithProps.html
    +++ b/tests/src/unit/core/clipboard/copy/__snapshots__/text/html/basicBlocksWithProps.html
    @@ -14,7 +14,11 @@ 

    Heading 1

    Check List Item 1

  • -

    Toggle List Item 1

    +
    + +

    Toggle List Item 1

    +
    +
  • diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/blocknoteHTML/lists/toggleWithChildren.html b/tests/src/unit/core/formatConversion/export/__snapshots__/blocknoteHTML/lists/toggleWithChildren.html
    new file mode 100644
    index 0000000000..018c41520e
    --- /dev/null
    +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/blocknoteHTML/lists/toggleWithChildren.html
    @@ -0,0 +1,76 @@
    +
    +
    +
    +
    +
    +
    + +

    Toggle List Item

    +
    +
    +
    +
    +
    +
    +
    +

    Toggle Child 1

    +
    +
    +
    +
    +
    +
    +

    Toggle Child 2

    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    Toggle Heading

    +
    +
    +
    +
    +
    +
    +
    +

    Heading Child 1

    +
    +
    +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/lists/basic.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/lists/basic.html index d0b661f0ce..1d9f613297 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/lists/basic.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/lists/basic.html @@ -24,6 +24,10 @@

    Check List Item 2

  • -

    Toggle List Item 1

    +
    + +

    Toggle List Item 1

    +
    +
  • \ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/lists/nested.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/lists/nested.html index fc16110695..113e6a5d08 100644 --- a/tests/src/unit/core/formatConversion/export/__snapshots__/html/lists/nested.html +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/lists/nested.html @@ -20,7 +20,11 @@

    Check List Item 2

    • -

      Toggle List Item 1

      +
      + +

      Toggle List Item 1

      +
      +
    diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/html/lists/toggleWithChildren.html b/tests/src/unit/core/formatConversion/export/__snapshots__/html/lists/toggleWithChildren.html new file mode 100644 index 0000000000..3712487eb1 --- /dev/null +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/html/lists/toggleWithChildren.html @@ -0,0 +1,17 @@ +
      +
    • +
      + +

      Toggle List Item

      +
      +

      Toggle Child 1

      +

      Toggle Child 2

      +
      +
    • +
    +
    + +

    Toggle Heading

    +
    +

    Heading Child 1

    +
    \ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/markdown/lists/toggleWithChildren.md b/tests/src/unit/core/formatConversion/export/__snapshots__/markdown/lists/toggleWithChildren.md new file mode 100644 index 0000000000..a01cab2790 --- /dev/null +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/markdown/lists/toggleWithChildren.md @@ -0,0 +1,9 @@ +* Toggle List Item + + Toggle Child 1 + + Toggle Child 2 + +## Toggle Heading + +Heading Child 1 diff --git a/tests/src/unit/core/formatConversion/export/__snapshots__/nodes/lists/toggleWithChildren.json b/tests/src/unit/core/formatConversion/export/__snapshots__/nodes/lists/toggleWithChildren.json new file mode 100644 index 0000000000..9b7407a060 --- /dev/null +++ b/tests/src/unit/core/formatConversion/export/__snapshots__/nodes/lists/toggleWithChildren.json @@ -0,0 +1,124 @@ +[ + { + "attrs": { + "id": "1", + }, + "content": [ + { + "attrs": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "content": [ + { + "text": "Toggle List Item", + "type": "text", + }, + ], + "type": "toggleListItem", + }, + { + "content": [ + { + "attrs": { + "id": "2", + }, + "content": [ + { + "attrs": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "content": [ + { + "text": "Toggle Child 1", + "type": "text", + }, + ], + "type": "paragraph", + }, + ], + "type": "blockContainer", + }, + { + "attrs": { + "id": "3", + }, + "content": [ + { + "attrs": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "content": [ + { + "text": "Toggle Child 2", + "type": "text", + }, + ], + "type": "paragraph", + }, + ], + "type": "blockContainer", + }, + ], + "type": "blockGroup", + }, + ], + "type": "blockContainer", + }, + { + "attrs": { + "id": "4", + }, + "content": [ + { + "attrs": { + "backgroundColor": "default", + "isToggleable": true, + "level": 2, + "textAlignment": "left", + "textColor": "default", + }, + "content": [ + { + "text": "Toggle Heading", + "type": "text", + }, + ], + "type": "heading", + }, + { + "content": [ + { + "attrs": { + "id": "5", + }, + "content": [ + { + "attrs": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "content": [ + { + "text": "Heading Child 1", + "type": "text", + }, + ], + "type": "paragraph", + }, + ], + "type": "blockContainer", + }, + ], + "type": "blockGroup", + }, + ], + "type": "blockContainer", + }, +] \ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/export/exportTestInstances.ts b/tests/src/unit/core/formatConversion/export/exportTestInstances.ts index 899331b55d..de46704117 100644 --- a/tests/src/unit/core/formatConversion/export/exportTestInstances.ts +++ b/tests/src/unit/core/formatConversion/export/exportTestInstances.ts @@ -159,6 +159,42 @@ export const exportTestInstancesBlockNoteHTML: TestInstance< }, executeTest: testExportBlockNoteHTML, }, + { + testCase: { + name: "lists/toggleWithChildren", + content: [ + { + type: "toggleListItem", + content: "Toggle List Item", + children: [ + { + type: "paragraph", + content: "Toggle Child 1", + }, + { + type: "paragraph", + content: "Toggle Child 2", + }, + ], + }, + { + type: "heading", + props: { + level: 2, + isToggleable: true, + }, + content: "Toggle Heading", + children: [ + { + type: "paragraph", + content: "Heading Child 1", + }, + ], + }, + ], + }, + executeTest: testExportBlockNoteHTML, + }, { testCase: { name: "lists/nested",