1- import { Slice , type Node } from "prosemirror-model" ;
1+ import { type Node } from "prosemirror-model" ;
22import { type Transaction } from "prosemirror-state" ;
3- import { ReplaceAroundStep } from "prosemirror-transform" ;
43import type { Block , PartialBlock } from "../../../../blocks/defaultBlocks.js" ;
54import type {
65 BlockIdentifier ,
@@ -11,161 +10,7 @@ import type {
1110import { blockToNode } from "../../../nodeConversions/blockToNode.js" ;
1211import { nodeToBlock } from "../../../nodeConversions/nodeToBlock.js" ;
1312import { getPmSchema } from "../../../pmUtil.js" ;
14-
15- /**
16- * Checks if a `column` node is empty, i.e. if it has only a single empty
17- * block.
18- * @param column The column to check.
19- * @returns Whether the column is empty.
20- */
21- function isEmptyColumn ( column : Node ) {
22- if ( ! column || column . type . name !== "column" ) {
23- throw new Error ( "Invalid columnPos: does not point to column node." ) ;
24- }
25-
26- const blockContainer = column . firstChild ;
27- if ( ! blockContainer ) {
28- throw new Error ( "Invalid column: does not have child node." ) ;
29- }
30-
31- const blockContent = blockContainer . firstChild ;
32- if ( ! blockContent ) {
33- throw new Error ( "Invalid blockContainer: does not have child node." ) ;
34- }
35-
36- return (
37- column . childCount === 1 &&
38- blockContainer . childCount === 1 &&
39- blockContent . type . spec . content === "inline*" &&
40- blockContent . content . content . length === 0
41- ) ;
42- }
43-
44- /**
45- * Removes all empty `column` nodes in a `columnList`. A `column` node is empty
46- * if it has only a single empty block. If, however, removing the `column`s
47- * leaves the `columnList` that has fewer than two, ProseMirror will re-add
48- * empty columns.
49- * @param tr The `Transaction` to add the changes to.
50- * @param columnListPos The position just before the `columnList` node.
51- */
52- function removeEmptyColumns ( tr : Transaction , columnListPos : number ) {
53- const $columnListPos = tr . doc . resolve ( columnListPos ) ;
54- const columnList = $columnListPos . nodeAfter ;
55- if ( ! columnList || columnList . type . name !== "columnList" ) {
56- throw new Error (
57- "Invalid columnListPos: does not point to columnList node." ,
58- ) ;
59- }
60-
61- for (
62- let columnIndex = columnList . childCount - 1 ;
63- columnIndex >= 0 ;
64- columnIndex --
65- ) {
66- const columnPos = tr . doc
67- . resolve ( $columnListPos . pos + 1 )
68- . posAtIndex ( columnIndex ) ;
69- const $columnPos = tr . doc . resolve ( columnPos ) ;
70- const column = $columnPos . nodeAfter ;
71- if ( ! column || column . type . name !== "column" ) {
72- throw new Error ( "Invalid columnPos: does not point to column node." ) ;
73- }
74-
75- if ( isEmptyColumn ( column ) ) {
76- tr . delete ( columnPos , columnPos + column ?. nodeSize ) ;
77- }
78- }
79- }
80-
81- /**
82- * Fixes potential issues in a `columnList` node after a
83- * `blockContainer`/`column` node is (re)moved from it:
84- *
85- * - Removes all empty `column` nodes. A `column` node is empty if it has only
86- * a single empty block.
87- * - If all but one `column` nodes are empty, replaces the `columnList` with
88- * the content of the non-empty `column`.
89- * - If all `column` nodes are empty, removes the `columnList` entirely.
90- * @param tr The `Transaction` to add the changes to.
91- * @param columnListPos
92- * @returns The position just before the `columnList` node.
93- */
94- export function fixColumnList ( tr : Transaction , columnListPos : number ) {
95- removeEmptyColumns ( tr , columnListPos ) ;
96-
97- const $columnListPos = tr . doc . resolve ( columnListPos ) ;
98- const columnList = $columnListPos . nodeAfter ;
99- if ( ! columnList || columnList . type . name !== "columnList" ) {
100- throw new Error (
101- "Invalid columnListPos: does not point to columnList node." ,
102- ) ;
103- }
104-
105- if ( columnList . childCount > 2 ) {
106- return ;
107- }
108-
109- const firstColumnBeforePos = columnListPos + 1 ;
110- const $firstColumnBeforePos = tr . doc . resolve ( firstColumnBeforePos ) ;
111- const firstColumn = $firstColumnBeforePos . nodeAfter ;
112-
113- const lastColumnAfterPos = columnListPos + columnList . nodeSize - 1 ;
114- const $lastColumnAfterPos = tr . doc . resolve ( lastColumnAfterPos ) ;
115- const lastColumn = $lastColumnAfterPos . nodeBefore ;
116-
117- if ( ! firstColumn || ! lastColumn ) {
118- throw new Error ( "Invalid columnList: does not have child node." ) ;
119- }
120-
121- const firstColumnEmpty = isEmptyColumn ( firstColumn ) ;
122- const lastColumnEmpty = isEmptyColumn ( lastColumn ) ;
123-
124- if ( firstColumnEmpty && lastColumnEmpty ) {
125- // Removes `columnList`
126- tr . delete ( columnListPos , columnListPos + columnList . nodeSize ) ;
127-
128- return ;
129- }
130-
131- if ( firstColumnEmpty ) {
132- tr . step (
133- new ReplaceAroundStep (
134- // Replaces `columnList`.
135- columnListPos ,
136- columnListPos + columnList . nodeSize ,
137- // Replaces with content of last `column`.
138- lastColumnAfterPos - lastColumn . nodeSize + 1 ,
139- lastColumnAfterPos - 1 ,
140- // Doesn't append anything.
141- Slice . empty ,
142- 0 ,
143- false ,
144- ) ,
145- ) ;
146-
147- return ;
148- }
149-
150- if ( lastColumnEmpty ) {
151- tr . step (
152- new ReplaceAroundStep (
153- // Replaces `columnList`.
154- columnListPos ,
155- columnListPos + columnList . nodeSize ,
156- // Replaces with content of first `column`.
157- firstColumnBeforePos + 1 ,
158- firstColumnBeforePos + firstColumn . nodeSize - 1 ,
159- // Doesn't append anything.
160- Slice . empty ,
161- 0 ,
162- false ,
163- ) ,
164- ) ;
165-
166- return ;
167- }
168- }
13+ import { fixColumnList } from "./util/fixColumnList.js" ;
16914
17015export function removeAndInsertBlocks <
17116 BSchema extends BlockSchema ,
0 commit comments