@kerebron/extension-basic-editor 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/esm/editor/src/CoreEditor.d.ts +28 -0
  2. package/esm/editor/src/CoreEditor.d.ts.map +1 -0
  3. package/esm/editor/src/CoreEditor.js +170 -0
  4. package/esm/editor/src/Extension.d.ts +26 -0
  5. package/esm/editor/src/Extension.d.ts.map +1 -0
  6. package/esm/editor/src/Extension.js +33 -0
  7. package/esm/editor/src/ExtensionManager.d.ts +32 -0
  8. package/esm/editor/src/ExtensionManager.d.ts.map +1 -0
  9. package/esm/editor/src/ExtensionManager.js +253 -0
  10. package/esm/editor/src/Mark.d.ts +18 -0
  11. package/esm/editor/src/Mark.d.ts.map +1 -0
  12. package/esm/editor/src/Mark.js +34 -0
  13. package/esm/editor/src/Node.d.ts +27 -0
  14. package/esm/editor/src/Node.d.ts.map +1 -0
  15. package/esm/editor/src/Node.js +43 -0
  16. package/esm/editor/src/commands/CommandManager.d.ts +20 -0
  17. package/esm/editor/src/commands/CommandManager.d.ts.map +1 -0
  18. package/esm/editor/src/commands/CommandManager.js +60 -0
  19. package/esm/editor/src/commands/createChainableState.d.ts +3 -0
  20. package/esm/editor/src/commands/createChainableState.d.ts.map +1 -0
  21. package/esm/editor/src/commands/createChainableState.js +29 -0
  22. package/esm/editor/src/commands/mod.d.ts +49 -0
  23. package/esm/editor/src/commands/mod.d.ts.map +1 -0
  24. package/esm/editor/src/commands/mod.js +928 -0
  25. package/esm/editor/src/mod.d.ts +5 -0
  26. package/esm/editor/src/mod.d.ts.map +1 -0
  27. package/esm/editor/src/mod.js +4 -0
  28. package/esm/editor/src/plugins/input-rules/InputRulesPlugin.d.ts +23 -0
  29. package/esm/editor/src/plugins/input-rules/InputRulesPlugin.d.ts.map +1 -0
  30. package/esm/editor/src/plugins/input-rules/InputRulesPlugin.js +163 -0
  31. package/esm/editor/src/plugins/input-rules/mod.d.ts +3 -0
  32. package/esm/editor/src/plugins/input-rules/mod.d.ts.map +1 -0
  33. package/esm/editor/src/plugins/input-rules/mod.js +2 -0
  34. package/esm/editor/src/plugins/input-rules/rulebuilders.d.ts +5 -0
  35. package/esm/editor/src/plugins/input-rules/rulebuilders.d.ts.map +1 -0
  36. package/esm/editor/src/plugins/input-rules/rulebuilders.js +50 -0
  37. package/esm/editor/src/types.d.ts +29 -0
  38. package/esm/editor/src/types.d.ts.map +1 -0
  39. package/esm/editor/src/types.js +1 -0
  40. package/esm/editor/src/utilities/createNodeFromContent.d.ts +12 -0
  41. package/esm/editor/src/utilities/createNodeFromContent.d.ts.map +1 -0
  42. package/esm/editor/src/utilities/createNodeFromContent.js +118 -0
  43. package/esm/editor/src/utilities/getHtmlAttributes.d.ts +4 -0
  44. package/esm/editor/src/utilities/getHtmlAttributes.d.ts.map +1 -0
  45. package/esm/editor/src/utilities/getHtmlAttributes.js +47 -0
  46. package/esm/editor/src/utilities/mod.d.ts +3 -0
  47. package/esm/editor/src/utilities/mod.d.ts.map +1 -0
  48. package/esm/editor/src/utilities/mod.js +2 -0
  49. package/esm/extension-automerge/src/CursorPlugin.d.ts +16 -0
  50. package/esm/extension-automerge/src/CursorPlugin.d.ts.map +1 -0
  51. package/esm/extension-automerge/src/CursorPlugin.js +114 -0
  52. package/esm/extension-automerge/src/ExtensionAutomerge.d.ts +26 -0
  53. package/esm/extension-automerge/src/ExtensionAutomerge.d.ts.map +1 -0
  54. package/esm/extension-automerge/src/ExtensionAutomerge.js +136 -0
  55. package/esm/extension-automerge/src/MarkUnknown.d.ts +8 -0
  56. package/esm/extension-automerge/src/MarkUnknown.d.ts.map +1 -0
  57. package/esm/extension-automerge/src/MarkUnknown.js +26 -0
  58. package/esm/extension-automerge/src/NodeUnknown.d.ts +8 -0
  59. package/esm/extension-automerge/src/NodeUnknown.d.ts.map +1 -0
  60. package/esm/extension-automerge/src/NodeUnknown.js +28 -0
  61. package/esm/extension-automerge/src/NodeUnknownBlock.d.ts +11 -0
  62. package/esm/extension-automerge/src/NodeUnknownBlock.d.ts.map +1 -0
  63. package/esm/extension-automerge/src/NodeUnknownBlock.js +36 -0
  64. package/esm/extension-automerge/src/SchemaAdapter.d.ts +70 -0
  65. package/esm/extension-automerge/src/SchemaAdapter.d.ts.map +1 -0
  66. package/esm/extension-automerge/src/SchemaAdapter.js +188 -0
  67. package/esm/extension-automerge/src/SyncPlugin.d.ts +16 -0
  68. package/esm/extension-automerge/src/SyncPlugin.d.ts.map +1 -0
  69. package/esm/extension-automerge/src/SyncPlugin.js +147 -0
  70. package/esm/extension-automerge/src/amToPm.d.ts +9 -0
  71. package/esm/extension-automerge/src/amToPm.d.ts.map +1 -0
  72. package/esm/extension-automerge/src/amToPm.js +245 -0
  73. package/esm/extension-automerge/src/amTraversal.d.ts +62 -0
  74. package/esm/extension-automerge/src/amTraversal.d.ts.map +1 -0
  75. package/esm/extension-automerge/src/amTraversal.js +688 -0
  76. package/esm/extension-automerge/src/loader.d.ts +8 -0
  77. package/esm/extension-automerge/src/loader.d.ts.map +1 -0
  78. package/esm/extension-automerge/src/loader.js +54 -0
  79. package/esm/extension-automerge/src/maintainSpans.d.ts +9 -0
  80. package/esm/extension-automerge/src/maintainSpans.d.ts.map +1 -0
  81. package/esm/extension-automerge/src/maintainSpans.js +464 -0
  82. package/esm/extension-automerge/src/pmToAm.d.ts +6 -0
  83. package/esm/extension-automerge/src/pmToAm.d.ts.map +1 -0
  84. package/esm/extension-automerge/src/pmToAm.js +183 -0
  85. package/esm/extension-automerge/src/pmTraversal.d.ts +26 -0
  86. package/esm/extension-automerge/src/pmTraversal.d.ts.map +1 -0
  87. package/esm/extension-automerge/src/pmTraversal.js +102 -0
  88. package/esm/extension-automerge/src/types.d.ts +42 -0
  89. package/esm/extension-automerge/src/types.d.ts.map +1 -0
  90. package/esm/extension-automerge/src/types.js +94 -0
  91. package/esm/extension-automerge/src/utils.d.ts +3 -0
  92. package/esm/extension-automerge/src/utils.d.ts.map +1 -0
  93. package/esm/extension-automerge/src/utils.js +18 -0
  94. package/esm/extension-basic-editor/src/ExtensionBaseKeymap.d.ts +8 -0
  95. package/esm/extension-basic-editor/src/ExtensionBaseKeymap.d.ts.map +1 -0
  96. package/esm/{ExtensionBaseKeymap.js → extension-basic-editor/src/ExtensionBaseKeymap.js} +2 -2
  97. package/esm/{ExtensionBasicEditor.d.ts → extension-basic-editor/src/ExtensionBasicEditor.d.ts} +1 -1
  98. package/esm/extension-basic-editor/src/ExtensionBasicEditor.d.ts.map +1 -0
  99. package/esm/{ExtensionBasicEditor.js → extension-basic-editor/src/ExtensionBasicEditor.js} +1 -1
  100. package/esm/{ExtensionDropcursor.d.ts → extension-basic-editor/src/ExtensionDropcursor.d.ts} +1 -1
  101. package/esm/extension-basic-editor/src/ExtensionDropcursor.d.ts.map +1 -0
  102. package/esm/{ExtensionDropcursor.js → extension-basic-editor/src/ExtensionDropcursor.js} +1 -1
  103. package/esm/{ExtensionGapcursor.d.ts → extension-basic-editor/src/ExtensionGapcursor.d.ts} +1 -1
  104. package/esm/extension-basic-editor/src/ExtensionGapcursor.d.ts.map +1 -0
  105. package/esm/{ExtensionGapcursor.js → extension-basic-editor/src/ExtensionGapcursor.js} +1 -1
  106. package/esm/{ExtensionHistory.d.ts → extension-basic-editor/src/ExtensionHistory.d.ts} +2 -2
  107. package/esm/extension-basic-editor/src/ExtensionHistory.d.ts.map +1 -0
  108. package/esm/{ExtensionHistory.js → extension-basic-editor/src/ExtensionHistory.js} +1 -1
  109. package/esm/{MarkCode.d.ts → extension-basic-editor/src/MarkCode.d.ts} +2 -2
  110. package/esm/extension-basic-editor/src/MarkCode.d.ts.map +1 -0
  111. package/esm/{MarkCode.js → extension-basic-editor/src/MarkCode.js} +2 -2
  112. package/esm/{MarkItalic.d.ts → extension-basic-editor/src/MarkItalic.d.ts} +2 -2
  113. package/esm/extension-basic-editor/src/MarkItalic.d.ts.map +1 -0
  114. package/esm/{MarkItalic.js → extension-basic-editor/src/MarkItalic.js} +2 -2
  115. package/esm/{MarkLink.d.ts → extension-basic-editor/src/MarkLink.d.ts} +1 -1
  116. package/esm/extension-basic-editor/src/MarkLink.d.ts.map +1 -0
  117. package/esm/{MarkLink.js → extension-basic-editor/src/MarkLink.js} +1 -1
  118. package/esm/{MarkStrong.d.ts → extension-basic-editor/src/MarkStrong.d.ts} +2 -2
  119. package/esm/extension-basic-editor/src/MarkStrong.d.ts.map +1 -0
  120. package/esm/{MarkStrong.js → extension-basic-editor/src/MarkStrong.js} +2 -2
  121. package/esm/{MarkUnderline.d.ts → extension-basic-editor/src/MarkUnderline.d.ts} +2 -2
  122. package/esm/extension-basic-editor/src/MarkUnderline.d.ts.map +1 -0
  123. package/esm/{MarkUnderline.js → extension-basic-editor/src/MarkUnderline.js} +2 -2
  124. package/esm/{NodeAside.d.ts → extension-basic-editor/src/NodeAside.d.ts} +1 -1
  125. package/esm/extension-basic-editor/src/NodeAside.d.ts.map +1 -0
  126. package/esm/{NodeAside.js → extension-basic-editor/src/NodeAside.js} +1 -1
  127. package/esm/{NodeBlockquote.d.ts → extension-basic-editor/src/NodeBlockquote.d.ts} +3 -3
  128. package/esm/extension-basic-editor/src/NodeBlockquote.d.ts.map +1 -0
  129. package/esm/{NodeBlockquote.js → extension-basic-editor/src/NodeBlockquote.js} +3 -3
  130. package/esm/{NodeBulletList.d.ts → extension-basic-editor/src/NodeBulletList.d.ts} +3 -3
  131. package/esm/extension-basic-editor/src/NodeBulletList.d.ts.map +1 -0
  132. package/esm/{NodeBulletList.js → extension-basic-editor/src/NodeBulletList.js} +3 -3
  133. package/esm/{NodeDocument.d.ts → extension-basic-editor/src/NodeDocument.d.ts} +1 -1
  134. package/esm/extension-basic-editor/src/NodeDocument.d.ts.map +1 -0
  135. package/esm/{NodeDocument.js → extension-basic-editor/src/NodeDocument.js} +1 -1
  136. package/esm/{NodeHardBreak.d.ts → extension-basic-editor/src/NodeHardBreak.d.ts} +2 -2
  137. package/esm/extension-basic-editor/src/NodeHardBreak.d.ts.map +1 -0
  138. package/esm/{NodeHardBreak.js → extension-basic-editor/src/NodeHardBreak.js} +2 -2
  139. package/esm/{NodeHeading.d.ts → extension-basic-editor/src/NodeHeading.d.ts} +3 -3
  140. package/esm/extension-basic-editor/src/NodeHeading.d.ts.map +1 -0
  141. package/esm/{NodeHeading.js → extension-basic-editor/src/NodeHeading.js} +3 -3
  142. package/esm/{NodeHorizontalRule.d.ts → extension-basic-editor/src/NodeHorizontalRule.d.ts} +2 -2
  143. package/esm/extension-basic-editor/src/NodeHorizontalRule.d.ts.map +1 -0
  144. package/esm/{NodeHorizontalRule.js → extension-basic-editor/src/NodeHorizontalRule.js} +1 -1
  145. package/esm/{NodeImage.d.ts → extension-basic-editor/src/NodeImage.d.ts} +2 -2
  146. package/esm/extension-basic-editor/src/NodeImage.d.ts.map +1 -0
  147. package/esm/{NodeImage.js → extension-basic-editor/src/NodeImage.js} +1 -1
  148. package/esm/{NodeListItem.d.ts → extension-basic-editor/src/NodeListItem.d.ts} +2 -2
  149. package/esm/extension-basic-editor/src/NodeListItem.d.ts.map +1 -0
  150. package/esm/{NodeListItem.js → extension-basic-editor/src/NodeListItem.js} +1 -1
  151. package/esm/{NodeOrderedList.d.ts → extension-basic-editor/src/NodeOrderedList.d.ts} +3 -3
  152. package/esm/extension-basic-editor/src/NodeOrderedList.d.ts.map +1 -0
  153. package/esm/{NodeOrderedList.js → extension-basic-editor/src/NodeOrderedList.js} +5 -5
  154. package/esm/{NodeParagraph.d.ts → extension-basic-editor/src/NodeParagraph.d.ts} +2 -2
  155. package/esm/extension-basic-editor/src/NodeParagraph.d.ts.map +1 -0
  156. package/esm/{NodeParagraph.js → extension-basic-editor/src/NodeParagraph.js} +2 -2
  157. package/esm/{NodeText.d.ts → extension-basic-editor/src/NodeText.d.ts} +1 -1
  158. package/esm/extension-basic-editor/src/NodeText.d.ts.map +1 -0
  159. package/esm/{NodeText.js → extension-basic-editor/src/NodeText.js} +1 -1
  160. package/package.json +31 -25
  161. package/esm/ExtensionBaseKeymap.d.ts +0 -8
  162. package/esm/ExtensionBaseKeymap.d.ts.map +0 -1
  163. package/esm/ExtensionBasicEditor.d.ts.map +0 -1
  164. package/esm/ExtensionDropcursor.d.ts.map +0 -1
  165. package/esm/ExtensionGapcursor.d.ts.map +0 -1
  166. package/esm/ExtensionHistory.d.ts.map +0 -1
  167. package/esm/MarkCode.d.ts.map +0 -1
  168. package/esm/MarkItalic.d.ts.map +0 -1
  169. package/esm/MarkLink.d.ts.map +0 -1
  170. package/esm/MarkStrong.d.ts.map +0 -1
  171. package/esm/MarkUnderline.d.ts.map +0 -1
  172. package/esm/NodeAside.d.ts.map +0 -1
  173. package/esm/NodeBlockquote.d.ts.map +0 -1
  174. package/esm/NodeBulletList.d.ts.map +0 -1
  175. package/esm/NodeDocument.d.ts.map +0 -1
  176. package/esm/NodeHardBreak.d.ts.map +0 -1
  177. package/esm/NodeHeading.d.ts.map +0 -1
  178. package/esm/NodeHorizontalRule.d.ts.map +0 -1
  179. package/esm/NodeImage.d.ts.map +0 -1
  180. package/esm/NodeListItem.d.ts.map +0 -1
  181. package/esm/NodeOrderedList.d.ts.map +0 -1
  182. package/esm/NodeParagraph.d.ts.map +0 -1
  183. package/esm/NodeText.d.ts.map +0 -1
@@ -0,0 +1,688 @@
1
+ import { next as automerge } from '@automerge/automerge/slim';
2
+ import { Fragment, } from 'prosemirror-model';
3
+ import { amSpanToSpan, isBlockMarker } from './types.js';
4
+ import { amMarksFromPmMarks, pmMarksFromAmMarks, } from './SchemaAdapter.js';
5
+ /**
6
+ * Convert an array of AutoMerge spans into a ProseMirror doc.
7
+ * @param adapter
8
+ * @param spans
9
+ * @returns
10
+ */
11
+ export function amSpansToDoc(adapter, spans) {
12
+ const events = traverseSpans(adapter, spans);
13
+ const stack = [
14
+ {
15
+ tag: 'doc',
16
+ attrs: {},
17
+ children: [],
18
+ },
19
+ ];
20
+ let nextBlockAmgAttrs = null;
21
+ for (const event of events) {
22
+ if (event.type === 'openTag') {
23
+ const attrs = Object.assign({}, nextBlockAmgAttrs, event.attrs);
24
+ stack.push({
25
+ tag: event.tag,
26
+ attrs,
27
+ children: [],
28
+ });
29
+ }
30
+ else if (event.type === 'closeTag') {
31
+ //eslint-disable-next-line @typescript-eslint/no-non-null-assertion
32
+ const { children, attrs, tag } = stack.pop();
33
+ const node = constructNode(adapter.schema, tag, attrs, children);
34
+ stack[stack.length - 1].children.push(node);
35
+ }
36
+ else if (event.type === 'leafNode') {
37
+ stack[stack.length - 1].children.push(constructNode(adapter.schema, event.tag, nextBlockAmgAttrs || {}, []));
38
+ }
39
+ else if (event.type === 'text') {
40
+ const pmMarks = pmMarksFromAmMarks(adapter, event.marks);
41
+ stack[stack.length - 1].children.push(adapter.schema.text(event.text, pmMarks));
42
+ }
43
+ if (event.type === 'block') {
44
+ nextBlockAmgAttrs = { isAmgBlock: true, ...event.block.attrs };
45
+ if (event.isUnknown) {
46
+ nextBlockAmgAttrs.unknownBlock = event.block;
47
+ }
48
+ }
49
+ else {
50
+ nextBlockAmgAttrs = null;
51
+ }
52
+ }
53
+ if (stack.length !== 1) {
54
+ throw new Error('Invalid stack length');
55
+ }
56
+ else {
57
+ const { children, attrs, tag } = stack[0];
58
+ return constructNode(adapter.schema, tag, attrs, children);
59
+ }
60
+ }
61
+ function constructNode(schema, nodeName,
62
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
63
+ attrs, children) {
64
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
65
+ const knownAttrs = {};
66
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
67
+ const unknownAttrs = {};
68
+ let hasUnknownAttr = false;
69
+ for (const name of Object.keys(attrs)) {
70
+ if (name === 'isAmgBlock' ||
71
+ name === 'unknownBlock' ||
72
+ name === 'unknownAttrs') {
73
+ knownAttrs[name] = attrs[name];
74
+ continue;
75
+ }
76
+ const attrSpec = schema.nodes[nodeName]?.spec?.attrs?.[name];
77
+ if (attrSpec != null) {
78
+ knownAttrs[name] = attrs[name];
79
+ }
80
+ else {
81
+ hasUnknownAttr = true;
82
+ unknownAttrs[name] = attrs[name];
83
+ }
84
+ }
85
+ if (hasUnknownAttr) {
86
+ knownAttrs.unknownAttrs = unknownAttrs;
87
+ }
88
+ return schema.node(nodeName, knownAttrs, children);
89
+ }
90
+ export function amSpliceIdxToPmIdx(adapter, spans, target) {
91
+ const events = eventsWithIndexChanges(traverseSpans(adapter, spans));
92
+ let maxInsertableIndex = null;
93
+ for (const state of events) {
94
+ if (state.before.amIdx >= target && maxInsertableIndex != null) {
95
+ return maxInsertableIndex;
96
+ }
97
+ if (state.event.type === 'openTag') {
98
+ if (adapter.schema.nodes[state.event.tag].isTextblock) {
99
+ maxInsertableIndex = state.after.pmIdx;
100
+ }
101
+ }
102
+ else if (state.event.type === 'leafNode') {
103
+ maxInsertableIndex = state.after.pmIdx;
104
+ }
105
+ else if (state.event.type === 'text') {
106
+ maxInsertableIndex = state.after.pmIdx;
107
+ if (state.after.amIdx >= target) {
108
+ if (state.before.amIdx + state.event.text.length >= target) {
109
+ const diff = target - state.before.amIdx;
110
+ return state.before.pmIdx + diff - 1;
111
+ }
112
+ }
113
+ }
114
+ }
115
+ return maxInsertableIndex;
116
+ }
117
+ export function amIdxToPmBlockIdx(adapter, spans, target) {
118
+ const events = eventsWithIndexChanges(traverseSpans(adapter, spans));
119
+ let lastBlockStart = null;
120
+ let isFirstTag = true;
121
+ for (const state of events) {
122
+ if (state.event.type === 'openTag') {
123
+ if (state.event.role === 'explicit') {
124
+ lastBlockStart = state.after.pmIdx;
125
+ }
126
+ else if (adapter.schema.nodes[state.event.tag].isTextblock &&
127
+ isFirstTag) {
128
+ // If there's a render-only opening paragraph then everything before
129
+ // the first block marker should be inside it
130
+ lastBlockStart = state.after.pmIdx;
131
+ }
132
+ isFirstTag = false;
133
+ }
134
+ else if (state.event.type === 'block') {
135
+ if (state.after.amIdx === target) {
136
+ return state.after.pmIdx + 1;
137
+ }
138
+ }
139
+ if (state.after.amIdx >= target) {
140
+ return lastBlockStart;
141
+ }
142
+ }
143
+ return lastBlockStart;
144
+ }
145
+ export function* eventsWithIndexChanges(events) {
146
+ let pmOffset = 0;
147
+ let amOffset = -1;
148
+ while (true) {
149
+ const next = events.next();
150
+ if (next.done) {
151
+ return;
152
+ }
153
+ const event = next.value;
154
+ const before = { amIdx: amOffset, pmIdx: pmOffset };
155
+ if (event.type === 'openTag' && event.tag !== 'doc') {
156
+ pmOffset += 1;
157
+ }
158
+ else if (event.type === 'closeTag' && event.tag !== 'doc') {
159
+ pmOffset += 1;
160
+ }
161
+ else if (event.type === 'leafNode') {
162
+ pmOffset += 1;
163
+ }
164
+ else if (event.type === 'text') {
165
+ amOffset += event.text.length;
166
+ pmOffset += event.text.length;
167
+ }
168
+ else if (event.type === 'block') {
169
+ amOffset += 1;
170
+ }
171
+ const after = { amIdx: amOffset, pmIdx: pmOffset };
172
+ yield { event, before, after };
173
+ }
174
+ }
175
+ export function* traverseNode(adapter, node) {
176
+ const toProcess = [
177
+ {
178
+ node,
179
+ parent: null,
180
+ indexInParent: 0,
181
+ numChildrenInParent: node.childCount,
182
+ type: 'node',
183
+ },
184
+ ];
185
+ const nodePath = [];
186
+ while (toProcess.length > 0) {
187
+ const next = toProcess.pop();
188
+ if (next == null) {
189
+ return;
190
+ }
191
+ if (next.type === 'node') {
192
+ const cur = next.node;
193
+ if (cur.isText) {
194
+ const marks = amMarksFromPmMarks(adapter, cur.marks);
195
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
196
+ yield { type: 'text', text: cur.text, marks };
197
+ }
198
+ else {
199
+ const maybeBlock = blockForNode(adapter, cur, nodePath, next.indexInParent, next.numChildrenInParent);
200
+ const role = maybeBlock != null ? 'explicit' : 'render-only';
201
+ if (maybeBlock != null) {
202
+ const { block, isUnknown } = maybeBlock;
203
+ yield {
204
+ type: 'block',
205
+ isUnknown,
206
+ block,
207
+ };
208
+ }
209
+ if (cur.isLeaf) {
210
+ yield { type: 'leafNode', tag: cur.type.name, role };
211
+ }
212
+ else {
213
+ yield { type: 'openTag', tag: cur.type.name, role };
214
+ // nodePath.push({ node: cur, idx: 0 });
215
+ nodePath.push(cur);
216
+ toProcess.push({ type: 'closeTag', tag: cur.type.name, role });
217
+ for (let i = cur.childCount - 1; i >= 0; i--) {
218
+ toProcess.push({
219
+ parent: cur,
220
+ indexInParent: i,
221
+ numChildrenInParent: cur.childCount,
222
+ type: 'node',
223
+ node: cur.child(i),
224
+ });
225
+ }
226
+ }
227
+ }
228
+ }
229
+ else {
230
+ if (next.type === 'closeTag') {
231
+ nodePath.pop();
232
+ }
233
+ yield next;
234
+ }
235
+ }
236
+ }
237
+ function blockForNode(adapter, node, nodePath, indexInParent, numChildrenInParent) {
238
+ // Round trip unknown blocks through the editor
239
+ if (node.attrs.unknownBlock != null) {
240
+ return {
241
+ isUnknown: true,
242
+ block: node.attrs.unknownBlock,
243
+ };
244
+ }
245
+ const blockMapping = blockMappingForNode(adapter, node);
246
+ if (blockMapping == null) {
247
+ if (node.attrs.isAmgBlock) {
248
+ throw new Error('no mapping found for node which is marked as a block');
249
+ }
250
+ return null;
251
+ }
252
+ const attrs = blockMapping.attrParsers?.fromProsemirror(node) || {};
253
+ // make sure to round trip unknown attributes
254
+ if (node.attrs.unknownAttrs != null) {
255
+ for (const key of Object.keys(node.attrs.unknownAttrs)) {
256
+ attrs[key] = node.attrs.unknownAttrs[key];
257
+ }
258
+ }
259
+ // We have a few things to do
260
+ // 1. If this node has `isAmgBlock: true` then we just need to get the block
261
+ // mapping and emit the correct block
262
+ // 2. If this node has `isAmgBlock: false` then we have to decide, based on
263
+ // it's descendants, whether we should emit a block at this point
264
+ if (node.attrs.isAmgBlock) {
265
+ return {
266
+ isUnknown: false,
267
+ block: {
268
+ type: blockMapping.blockName,
269
+ parents: findParents(adapter, nodePath),
270
+ attrs,
271
+ isEmbed: blockMapping.isEmbed || false,
272
+ },
273
+ };
274
+ }
275
+ else if (blockMapping && blockMapping.isEmbed) {
276
+ return {
277
+ isUnknown: false,
278
+ block: {
279
+ type: blockMapping.blockName,
280
+ parents: findParents(adapter, nodePath),
281
+ attrs,
282
+ isEmbed: true,
283
+ },
284
+ };
285
+ }
286
+ else {
287
+ // Two possibilities:
288
+ //
289
+ // 1. The block is a container for an `isAmgBlock: true` block
290
+ // 2. The block is a newly inserted block
291
+ const explicitChildren = findExplicitChildren(node);
292
+ if (explicitChildren != null) {
293
+ // This block has explicit children. So we only need to emit a block
294
+ // marker if the content before the first explicit child is different to
295
+ // that which would be emitted by the default schema
296
+ const defaultContent = blockMapping.content.contentMatch.fillBefore(Fragment.from([explicitChildren.first]), true);
297
+ if (defaultContent == null) {
298
+ throw new Error('schema could not find wrapping');
299
+ }
300
+ if (defaultContent.eq(explicitChildren.contentBeforeFirst)) {
301
+ return null;
302
+ }
303
+ }
304
+ let emitBlock = false;
305
+ if (node.isTextblock) {
306
+ const lastParent = nodePath[nodePath.length - 1];
307
+ const lastParentNode = lastParent;
308
+ // const lastParentNode = lastParent.node;
309
+ if (lastParentNode == null ||
310
+ (lastParentNode.type === adapter.schema.nodes.doc &&
311
+ numChildrenInParent > 1)) {
312
+ // we're at the top level and there are multiple children, so we need to emit a block marker
313
+ emitBlock = true;
314
+ }
315
+ else {
316
+ // If we're the first node in our parent, and we're the default textblock
317
+ // for that parent then we don't emit a block marker
318
+ const isTextWrapper = lastParentNode.type.contentMatch.defaultType === node.type &&
319
+ indexInParent === 0 &&
320
+ !node.attrs.isAmgBlock;
321
+ if (!isTextWrapper) {
322
+ emitBlock = true;
323
+ }
324
+ }
325
+ }
326
+ else if (hasImmediateTextChild(node)) {
327
+ emitBlock = true;
328
+ }
329
+ if (emitBlock) {
330
+ return {
331
+ isUnknown: blockMapping.content === adapter.unknownBlock,
332
+ block: {
333
+ type: blockMapping.blockName,
334
+ parents: findParents(adapter, nodePath),
335
+ attrs,
336
+ isEmbed: blockMapping.isEmbed || false,
337
+ },
338
+ };
339
+ }
340
+ else {
341
+ return null;
342
+ }
343
+ }
344
+ }
345
+ function hasImmediateTextChild(node) {
346
+ for (let i = 0; i < node.childCount; i++) {
347
+ if (node.child(i).isTextblock) {
348
+ return true;
349
+ }
350
+ }
351
+ return false;
352
+ }
353
+ /**
354
+ * Find the first child of this node which either has `isAmgBlock: true` or
355
+ * has a descendant with `isAmgBlock: true`
356
+ */
357
+ function findExplicitChildren(node) {
358
+ let numExplicitChildren = 0;
359
+ let firstExplicitChild = null;
360
+ const contentBeforeFirst = [];
361
+ for (let i = 0; i < node.childCount; i++) {
362
+ const child = node.child(i);
363
+ let hasExplicitDescendant = false;
364
+ if (child.attrs.isAmgBlock) {
365
+ hasExplicitDescendant = true;
366
+ }
367
+ else {
368
+ child.descendants((desc) => {
369
+ if (desc.attrs.isAmgBlock) {
370
+ hasExplicitDescendant = true;
371
+ return false;
372
+ }
373
+ return true;
374
+ });
375
+ }
376
+ if (hasExplicitDescendant) {
377
+ numExplicitChildren++;
378
+ if (firstExplicitChild == null) {
379
+ firstExplicitChild = child;
380
+ }
381
+ }
382
+ if (firstExplicitChild == null) {
383
+ contentBeforeFirst.push(child);
384
+ }
385
+ if (numExplicitChildren > 1) {
386
+ break;
387
+ }
388
+ }
389
+ if (numExplicitChildren > 0) {
390
+ return {
391
+ contentBeforeFirst: Fragment.from(contentBeforeFirst),
392
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
393
+ first: firstExplicitChild,
394
+ };
395
+ }
396
+ else {
397
+ return null;
398
+ }
399
+ }
400
+ function blockMappingForNode(adapter, node) {
401
+ if (node.type === adapter.unknownBlock && node.attrs.unknownParentBlock) {
402
+ return {
403
+ blockName: node.attrs.unknownParentBlock,
404
+ content: node.type,
405
+ isEmbed: false,
406
+ };
407
+ }
408
+ const possibleMappings = adapter.nodeMappings.filter((m) => m.content === node.type);
409
+ if (possibleMappings.length === 0) {
410
+ return null;
411
+ }
412
+ return possibleMappings[0];
413
+ }
414
+ function findParents(adapter, parentNodes) {
415
+ const parents = [];
416
+ for (const [index, parent] of parentNodes.entries()) {
417
+ const node = parent; // .node;
418
+ if (index === parentNodes.length - 1 &&
419
+ node.isTextblock &&
420
+ !node.attrs.isAmgBlock) {
421
+ // If the last node is a render-only text block then we don't need to emit it, the
422
+ // schema will take care of inserting it around the content for us
423
+ continue;
424
+ }
425
+ const mapping = blockMappingForNode(adapter, node);
426
+ if (mapping == null) {
427
+ continue;
428
+ }
429
+ parents.push(mapping.blockName);
430
+ }
431
+ return parents;
432
+ }
433
+ export function* traverseSpans(adapter, amSpans) {
434
+ const blockSpans = amSpans.map(amSpanToSpan);
435
+ if (blockSpans.length === 0) {
436
+ return yield* [
437
+ { type: 'openTag', tag: 'paragraph', role: 'render-only' },
438
+ { type: 'closeTag', tag: 'paragraph', role: 'render-only' },
439
+ ];
440
+ }
441
+ const state = new TraverseState(adapter);
442
+ for (const span of blockSpans) {
443
+ if (span.type === 'block') {
444
+ yield* state.newBlock(span.value);
445
+ }
446
+ else {
447
+ yield* state.newText(span.value, span.marks || {});
448
+ }
449
+ }
450
+ yield* state.finish();
451
+ }
452
+ class TraverseState {
453
+ constructor(adapter) {
454
+ Object.defineProperty(this, "adapter", {
455
+ enumerable: true,
456
+ configurable: true,
457
+ writable: true,
458
+ value: void 0
459
+ });
460
+ Object.defineProperty(this, "lastBlock", {
461
+ enumerable: true,
462
+ configurable: true,
463
+ writable: true,
464
+ value: null
465
+ });
466
+ Object.defineProperty(this, "stack", {
467
+ enumerable: true,
468
+ configurable: true,
469
+ writable: true,
470
+ value: []
471
+ });
472
+ Object.defineProperty(this, "topMatch", {
473
+ enumerable: true,
474
+ configurable: true,
475
+ writable: true,
476
+ value: void 0
477
+ });
478
+ this.adapter = adapter;
479
+ this.stack = [];
480
+ this.topMatch = this.adapter.schema.nodes.doc.contentMatch;
481
+ }
482
+ set currentMatch(match) {
483
+ if (match === null) {
484
+ throw new Error('Match cannot be null');
485
+ }
486
+ if (this.stack.length > 0) {
487
+ this.stack[this.stack.length - 1].lastMatch = match;
488
+ }
489
+ else {
490
+ this.topMatch = match;
491
+ }
492
+ }
493
+ get currentMatch() {
494
+ if (this.stack.length > 0) {
495
+ return this.stack[this.stack.length - 1].lastMatch;
496
+ }
497
+ else {
498
+ return this.topMatch;
499
+ }
500
+ }
501
+ *newBlock(block) {
502
+ if (block.isEmbed) {
503
+ const { content } = nodesForBlock(this.adapter, block.type.val, block.isEmbed);
504
+ const wrapping = this.currentMatch.findWrapping(content);
505
+ if (wrapping) {
506
+ for (let i = 0; i < wrapping.length; i++) {
507
+ yield this.pushNode(wrapping[i], null, 'render-only');
508
+ }
509
+ }
510
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
511
+ this.currentMatch = this.currentMatch.matchType(content);
512
+ yield blockEvent(this.adapter, block);
513
+ yield { type: 'leafNode', tag: content.name, role: 'explicit' };
514
+ return;
515
+ }
516
+ const newOuter = outerNodeTypes(this.adapter, block);
517
+ let i = 0;
518
+ while (i < newOuter.length && i < this.stack.length) {
519
+ if (this.stack[i].node !== newOuter[i].type) {
520
+ break;
521
+ }
522
+ i++;
523
+ }
524
+ const toClose = this.stack.splice(i);
525
+ for (const { node, role, lastMatch } of toClose.toReversed()) {
526
+ yield* this.finishStackFrame({ node, role, lastMatch });
527
+ yield { type: 'closeTag', tag: node.name, role };
528
+ }
529
+ for (let j = i; j < newOuter.length; j++) {
530
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
531
+ const { type: next, attrs } = newOuter[j];
532
+ yield* this.fillBefore(next);
533
+ yield this.pushNode(next, attrs, 'render-only');
534
+ }
535
+ yield blockEvent(this.adapter, block);
536
+ const { content } = nodesForBlock(this.adapter, block.type.val, block.isEmbed || false);
537
+ yield this.pushNode(content, null, 'explicit');
538
+ }
539
+ pushNode(node,
540
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
541
+ attrs, role) {
542
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
543
+ this.currentMatch = this.currentMatch.matchType(node);
544
+ this.stack.push({ node, role, lastMatch: node.contentMatch });
545
+ return { type: 'openTag', tag: node.name, role, ...(attrs && { attrs }) };
546
+ }
547
+ *newText(text, marks) {
548
+ const wrapping = this.currentMatch.findWrapping(this.adapter.schema.nodes.text);
549
+ if (wrapping) {
550
+ for (let i = 0; i < wrapping.length; i++) {
551
+ yield this.pushNode(wrapping[i], null, 'render-only');
552
+ }
553
+ }
554
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
555
+ this.currentMatch = this.currentMatch.matchType(this.adapter.schema.nodes.text);
556
+ yield { type: 'text', text, marks };
557
+ }
558
+ *finish() {
559
+ for (const { node, role, lastMatch } of this.stack.toReversed()) {
560
+ yield* this.finishStackFrame({ node, role, lastMatch });
561
+ yield { type: 'closeTag', tag: node.name, role };
562
+ }
563
+ }
564
+ *fillBefore(node) {
565
+ const fill = this.currentMatch.fillBefore(Fragment.from(node.create()));
566
+ if (fill != null) {
567
+ yield* this.emitFragment(fill);
568
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
569
+ this.currentMatch = this.currentMatch.matchFragment(fill);
570
+ }
571
+ }
572
+ *emitFragment(fragment) {
573
+ const toProcess = [];
574
+ for (let i = fragment.childCount - 1; i >= 0; i--) {
575
+ toProcess.push({ type: 'open', node: fragment.child(i) });
576
+ }
577
+ while (toProcess.length > 0) {
578
+ const next = toProcess.pop();
579
+ if (next == null) {
580
+ return;
581
+ }
582
+ if (next.type === 'open') {
583
+ yield {
584
+ type: 'openTag',
585
+ tag: next.node.type.name,
586
+ role: 'render-only',
587
+ };
588
+ if (next.node.isText) {
589
+ // TODO: Calculate marks
590
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
591
+ yield { type: 'text', text: next.node.text, marks: {} };
592
+ yield {
593
+ type: 'closeTag',
594
+ tag: next.node.type.name,
595
+ role: 'render-only',
596
+ };
597
+ }
598
+ else {
599
+ toProcess.push({ type: 'close', node: next.node.type });
600
+ for (let i = next.node.childCount - 1; i >= 0; i--) {
601
+ toProcess.push({ type: 'open', node: next.node.child(i) });
602
+ }
603
+ }
604
+ }
605
+ else {
606
+ yield { type: 'closeTag', tag: next.node.name, role: 'render-only' };
607
+ }
608
+ }
609
+ }
610
+ *finishStackFrame(frame) {
611
+ const fill = frame.lastMatch.fillBefore(Fragment.empty, true);
612
+ if (fill) {
613
+ yield* this.emitFragment(fill);
614
+ }
615
+ }
616
+ }
617
+ function outerNodeTypes(adapter, block) {
618
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
619
+ const result = [];
620
+ for (const parent of block.parents) {
621
+ const { content, attrs } = nodesForBlock(adapter, parent.val, false);
622
+ result.push({ type: content, attrs: attrs || null });
623
+ }
624
+ return result;
625
+ }
626
+ function blockEvent(adapter, block) {
627
+ const mapping = adapter.nodeMappings.find((m) => m.blockName === block.type.val);
628
+ const attrs = { ...block.attrs };
629
+ for (const [key, value] of Object.entries(attrs)) {
630
+ if (value instanceof automerge.RawString) {
631
+ attrs[key] = value.val;
632
+ }
633
+ else if ('string' === typeof value?.val) {
634
+ attrs[key] = value?.val;
635
+ }
636
+ }
637
+ return {
638
+ type: 'block',
639
+ isUnknown: mapping == null,
640
+ block: {
641
+ attrs,
642
+ parents: block.parents.map((p) => p.val),
643
+ type: block.type.val,
644
+ isEmbed: block.isEmbed || false,
645
+ },
646
+ };
647
+ }
648
+ export function blockAtIdx(spans, target) {
649
+ let idx = 0;
650
+ let block = null;
651
+ for (const span of spans) {
652
+ if (idx > target) {
653
+ return block;
654
+ }
655
+ if (span.type === 'text') {
656
+ if (idx + span.value.length > target) {
657
+ return block;
658
+ }
659
+ idx += span.value.length;
660
+ }
661
+ else {
662
+ if (isBlockMarker(span.value)) {
663
+ block = { index: idx, block: span.value };
664
+ }
665
+ idx += 1;
666
+ }
667
+ }
668
+ return block;
669
+ }
670
+ function nodesForBlock(adapter, blockType, isEmbed) {
671
+ const mapping = adapter.nodeMappings.find((m) => m.blockName === blockType);
672
+ if (mapping == null) {
673
+ if (isEmbed) {
674
+ return {
675
+ content: adapter.unknownLeaf,
676
+ };
677
+ }
678
+ else {
679
+ return {
680
+ content: adapter.unknownBlock,
681
+ attrs: { unknownParentBlock: blockType },
682
+ };
683
+ }
684
+ }
685
+ return {
686
+ content: mapping.content,
687
+ };
688
+ }
@@ -0,0 +1,8 @@
1
+ import { next as automerge } from '@automerge/automerge';
2
+ import type { Node as ProseMirrorNode } from 'prosemirror-model';
3
+ import type { SchemaAdapter } from './SchemaAdapter.js';
4
+ import { DocHandle } from '@automerge/automerge-repo';
5
+ export declare function createEmptyDocFromExisting(doc: ProseMirrorNode): ProseMirrorNode | null;
6
+ export declare function pmDocToAm<T>(basicSchemaAdapter: SchemaAdapter, amDoc: automerge.Doc<T>, docToLoad: ProseMirrorNode, pathToTextField?: string[]): automerge.Doc<T>;
7
+ export declare function pmDocToAmHandle<T>(basicSchemaAdapter: SchemaAdapter, handle: DocHandle<T>, docToLoad: ProseMirrorNode, pathToTextField?: string[]): void;
8
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/extension-automerge/src/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,IAAI,IAAI,eAAe,EAAU,MAAM,mBAAmB,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGxD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAkCtD,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,eAAe,0BAE9D;AAED,wBAAgB,SAAS,CAAC,CAAC,EACzB,kBAAkB,EAAE,aAAa,EACjC,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EACvB,SAAS,EAAE,eAAe,EAC1B,eAAe,WAAW,GACzB,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAYlB;AAED,wBAAgB,eAAe,CAAC,CAAC,EAC/B,kBAAkB,EAAE,aAAa,EACjC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EACpB,SAAS,EAAE,eAAe,EAC1B,eAAe,WAAW,QAc3B"}