diff --git a/packages/editor/src/extensions/callout/callout.ts b/packages/editor/src/extensions/callout/callout.ts index 7726c725b..86d8b0f03 100644 --- a/packages/editor/src/extensions/callout/callout.ts +++ b/packages/editor/src/extensions/callout/callout.ts @@ -258,10 +258,10 @@ export const Callout = Node.create({ container.onmousedown = onClick; container.ontouchstart = onClick; - if (node.attrs.hiddenUnder) { - container.dataset.hiddenUnder = node.attrs.hiddenUnder; + if (node.attrs.hidden) { + container.dataset.hidden = node.attrs.hidden; } else { - delete container.dataset.hiddenUnder; + delete container.dataset.hidden; } return { @@ -275,9 +275,9 @@ export const Callout = Node.create({ if (updatedNode.attrs.collapsed) container.classList.add("collapsed"); else container.classList.remove("collapsed"); - if (updatedNode.attrs.hiddenUnder) - container.dataset.hiddenUnder = updatedNode.attrs.hiddenUnder; - else delete container.dataset.hiddenUnder; + if (updatedNode.attrs.hidden) + container.dataset.hidden = updatedNode.attrs.hidden; + else delete container.dataset.hidden; return true; } diff --git a/packages/editor/src/extensions/code-block/code-block.ts b/packages/editor/src/extensions/code-block/code-block.ts index 6895b7cf5..5f82e9826 100644 --- a/packages/editor/src/extensions/code-block/code-block.ts +++ b/packages/editor/src/extensions/code-block/code-block.ts @@ -555,7 +555,7 @@ export const CodeBlock = Node.create({ compareCaretPosition(prev.caretPosition, next.caretPosition) || prev.language !== next.language || prev.indentType !== next.indentType || - prev.hiddenUnder !== next.hiddenUnder + prev.hidden !== next.hidden ); } }); diff --git a/packages/editor/src/extensions/heading/heading.ts b/packages/editor/src/extensions/heading/heading.ts index 5d493e40b..222fa216f 100644 --- a/packages/editor/src/extensions/heading/heading.ts +++ b/packages/editor/src/extensions/heading/heading.ts @@ -89,14 +89,14 @@ export const Heading = TiptapHeading.extend({ { types: COLLAPSIBLE_BLOCK_TYPES, attributes: { - hiddenUnder: { - default: null, + hidden: { + default: false, keepOnSplit: false, - parseHTML: (element) => element.dataset.hiddenUnder || null, + parseHTML: (element) => element.dataset.hidden === "true", renderHTML: (attributes) => { - if (!attributes.hiddenUnder) return {}; + if (!attributes.hidden) return {}; return { - "data-hidden-under": attributes.hiddenUnder + "data-hidden": attributes.hidden === true }; } } @@ -200,16 +200,9 @@ export const Heading = TiptapHeading.extend({ if (currentNode && currentNode.type.name === "heading") { const shouldCollapse = !currentNode.attrs.collapsed; const headingLevel = currentNode.attrs.level; - const headingId = currentNode.attrs.blockId; tr.setNodeAttribute(pos, "collapsed", shouldCollapse); - toggleNodesUnderHeading( - tr, - pos, - headingLevel, - shouldCollapse, - headingId - ); + toggleNodesUnderHeading(tr, pos, headingLevel, shouldCollapse); } return true; }); @@ -234,9 +227,9 @@ export const Heading = TiptapHeading.extend({ if (updatedNode.attrs.collapsed) heading.dataset.collapsed = "true"; else delete heading.dataset.collapsed; - if (updatedNode.attrs.hiddenUnder) - heading.dataset.hiddenUnder = updatedNode.attrs.hiddenUnder; - else delete heading.dataset.hiddenUnder; + if (updatedNode.attrs.hidden) + heading.dataset.hidden = updatedNode.attrs.hidden; + else delete heading.dataset.hidden; if (updatedNode.attrs.textAlign) heading.style.textAlign = @@ -259,8 +252,7 @@ function toggleNodesUnderHeading( tr: Transaction, headingPos: number, headingLevel: number, - isCollapsing: boolean, - headingId: string + isCollapsing: boolean ) { const { doc } = tr; const headingNode = doc.nodeAt(headingPos); @@ -269,6 +261,8 @@ function toggleNodesUnderHeading( let nextPos = headingPos + headingNode.nodeSize; const cursorPos = tr.selection.from; let shouldMoveCursor = false; + let insideCollapsedHeading = false; + let nestedHeadingLevel: number | null = null; while (nextPos < doc.content.size) { const nextNode = doc.nodeAt(nextPos); @@ -289,15 +283,33 @@ function toggleNodesUnderHeading( shouldMoveCursor = true; } + const currentPos = nextPos; + nextPos += nextNode.nodeSize; + if (COLLAPSIBLE_BLOCK_TYPES.includes(nextNode.type.name)) { - if (isCollapsing && typeof nextNode.attrs.hiddenUnder !== "string") { - tr.setNodeAttribute(nextPos, "hiddenUnder", headingId); - } else if (!isCollapsing && nextNode.attrs.hiddenUnder === headingId) { - tr.setNodeAttribute(nextPos, "hiddenUnder", null); + if (isCollapsing) { + tr.setNodeAttribute(currentPos, "hidden", true); + } else { + if (insideCollapsedHeading) { + if ( + nextNode.type.name === "heading" && + nestedHeadingLevel !== null && + nextNode.attrs.level <= nestedHeadingLevel + ) { + insideCollapsedHeading = false; + nestedHeadingLevel = null; + } else { + continue; + } + } + + tr.setNodeAttribute(currentPos, "hidden", false); + if (nextNode.type.name === "heading" && nextNode.attrs.collapsed) { + insideCollapsedHeading = true; + nestedHeadingLevel = nextNode.attrs.level; + } } } - - nextPos += nextNode.nodeSize; } if (shouldMoveCursor) { diff --git a/packages/editor/src/extensions/math/plugin/math-node-view.ts b/packages/editor/src/extensions/math/plugin/math-node-view.ts index 8a785651f..8704299e7 100644 --- a/packages/editor/src/extensions/math/plugin/math-node-view.ts +++ b/packages/editor/src/extensions/math/plugin/math-node-view.ts @@ -125,10 +125,10 @@ export class MathView implements NodeView, ICursorPosObserver { if (options.className) this.dom.classList.add(options.className); this.dom.classList.add("math-node"); - if (node.attrs.hiddenUnder) { - this.dom.dataset.hiddenUnder = node.attrs.hiddenUnder; + if (node.attrs.hidden) { + this.dom.dataset.hidden = node.attrs.hidden; } else { - delete this.dom.dataset.hiddenUnder; + delete this.dom.dataset.hidden; } this._mathRenderElt = document.createElement("span"); diff --git a/packages/editor/src/extensions/react/react-node-view.tsx b/packages/editor/src/extensions/react/react-node-view.tsx index a2a5a1843..5095b50d7 100644 --- a/packages/editor/src/extensions/react/react-node-view.tsx +++ b/packages/editor/src/extensions/react/react-node-view.tsx @@ -112,10 +112,10 @@ export class ReactNodeView

implements NodeView { return; } - if (this.node.attrs.hiddenUnder) { - this.domRef.dataset.hiddenUnder = this.node.attrs.hiddenUnder; + if (this.node.attrs.hidden) { + this.domRef.dataset.hidden = this.node.attrs.hidden; } else { - delete this.domRef.dataset.hiddenUnder; + delete this.domRef.dataset.hidden; } portalProviderAPI.render(this.Component, this.domRef); diff --git a/packages/editor/styles/styles.css b/packages/editor/styles/styles.css index 762cd0cf5..af77b9834 100644 --- a/packages/editor/styles/styles.css +++ b/packages/editor/styles/styles.css @@ -978,7 +978,7 @@ del.diffdel { display: none; } -[data-hidden-under] { +[data-hidden="true"] { display: none !important; }