@kerebron/extension-basic-editor 0.1.2 → 0.1.3

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 (49) hide show
  1. package/esm/extension-basic-editor/src/NodeImage.d.ts +1 -19
  2. package/esm/extension-basic-editor/src/NodeImage.d.ts.map +1 -1
  3. package/esm/extension-basic-editor/src/NodeImage.js +0 -22
  4. package/package.json +1 -4
  5. package/esm/extension-automerge/src/CursorPlugin.d.ts +0 -16
  6. package/esm/extension-automerge/src/CursorPlugin.d.ts.map +0 -1
  7. package/esm/extension-automerge/src/CursorPlugin.js +0 -114
  8. package/esm/extension-automerge/src/ExtensionAutomerge.d.ts +0 -26
  9. package/esm/extension-automerge/src/ExtensionAutomerge.d.ts.map +0 -1
  10. package/esm/extension-automerge/src/ExtensionAutomerge.js +0 -136
  11. package/esm/extension-automerge/src/MarkUnknown.d.ts +0 -8
  12. package/esm/extension-automerge/src/MarkUnknown.d.ts.map +0 -1
  13. package/esm/extension-automerge/src/MarkUnknown.js +0 -26
  14. package/esm/extension-automerge/src/NodeUnknown.d.ts +0 -8
  15. package/esm/extension-automerge/src/NodeUnknown.d.ts.map +0 -1
  16. package/esm/extension-automerge/src/NodeUnknown.js +0 -28
  17. package/esm/extension-automerge/src/NodeUnknownBlock.d.ts +0 -11
  18. package/esm/extension-automerge/src/NodeUnknownBlock.d.ts.map +0 -1
  19. package/esm/extension-automerge/src/NodeUnknownBlock.js +0 -36
  20. package/esm/extension-automerge/src/SchemaAdapter.d.ts +0 -70
  21. package/esm/extension-automerge/src/SchemaAdapter.d.ts.map +0 -1
  22. package/esm/extension-automerge/src/SchemaAdapter.js +0 -188
  23. package/esm/extension-automerge/src/SyncPlugin.d.ts +0 -16
  24. package/esm/extension-automerge/src/SyncPlugin.d.ts.map +0 -1
  25. package/esm/extension-automerge/src/SyncPlugin.js +0 -147
  26. package/esm/extension-automerge/src/amToPm.d.ts +0 -9
  27. package/esm/extension-automerge/src/amToPm.d.ts.map +0 -1
  28. package/esm/extension-automerge/src/amToPm.js +0 -245
  29. package/esm/extension-automerge/src/amTraversal.d.ts +0 -62
  30. package/esm/extension-automerge/src/amTraversal.d.ts.map +0 -1
  31. package/esm/extension-automerge/src/amTraversal.js +0 -688
  32. package/esm/extension-automerge/src/loader.d.ts +0 -8
  33. package/esm/extension-automerge/src/loader.d.ts.map +0 -1
  34. package/esm/extension-automerge/src/loader.js +0 -54
  35. package/esm/extension-automerge/src/maintainSpans.d.ts +0 -9
  36. package/esm/extension-automerge/src/maintainSpans.d.ts.map +0 -1
  37. package/esm/extension-automerge/src/maintainSpans.js +0 -464
  38. package/esm/extension-automerge/src/pmToAm.d.ts +0 -6
  39. package/esm/extension-automerge/src/pmToAm.d.ts.map +0 -1
  40. package/esm/extension-automerge/src/pmToAm.js +0 -183
  41. package/esm/extension-automerge/src/pmTraversal.d.ts +0 -26
  42. package/esm/extension-automerge/src/pmTraversal.d.ts.map +0 -1
  43. package/esm/extension-automerge/src/pmTraversal.js +0 -102
  44. package/esm/extension-automerge/src/types.d.ts +0 -42
  45. package/esm/extension-automerge/src/types.d.ts.map +0 -1
  46. package/esm/extension-automerge/src/types.js +0 -94
  47. package/esm/extension-automerge/src/utils.d.ts +0 -3
  48. package/esm/extension-automerge/src/utils.d.ts.map +0 -1
  49. package/esm/extension-automerge/src/utils.js +0 -18
@@ -1,188 +0,0 @@
1
- export class SchemaAdapter {
2
- constructor(schema) {
3
- Object.defineProperty(this, "nodeMappings", {
4
- enumerable: true,
5
- configurable: true,
6
- writable: true,
7
- value: void 0
8
- });
9
- Object.defineProperty(this, "markMappings", {
10
- enumerable: true,
11
- configurable: true,
12
- writable: true,
13
- value: void 0
14
- });
15
- Object.defineProperty(this, "unknownBlock", {
16
- enumerable: true,
17
- configurable: true,
18
- writable: true,
19
- value: void 0
20
- });
21
- Object.defineProperty(this, "unknownLeaf", {
22
- enumerable: true,
23
- configurable: true,
24
- writable: true,
25
- value: void 0
26
- });
27
- Object.defineProperty(this, "unknownMark", {
28
- enumerable: true,
29
- configurable: true,
30
- writable: true,
31
- value: void 0
32
- });
33
- Object.defineProperty(this, "schema", {
34
- enumerable: true,
35
- configurable: true,
36
- writable: true,
37
- value: void 0
38
- });
39
- const nodeMappings = [];
40
- const markMappings = [];
41
- let unknownBlock = null;
42
- for (const [nodeName, nodeSpec] of Object.entries(schema.nodes)) {
43
- const adaptSpec = nodeSpec.spec.automerge;
44
- if (adaptSpec == null) {
45
- continue;
46
- }
47
- if (adaptSpec.unknownBlock) {
48
- if (unknownBlock != null) {
49
- throw new Error('only one node can be marked as unknownBlock');
50
- }
51
- unknownBlock = schema.nodes[nodeName];
52
- }
53
- if (adaptSpec.block != null) {
54
- const nodeMapping = {
55
- blockName: adaptSpec.block,
56
- content: schema.nodes[nodeName],
57
- isEmbed: adaptSpec.isEmbed || false,
58
- };
59
- if (adaptSpec.attrParsers != null) {
60
- nodeMapping.attrParsers = adaptSpec.attrParsers;
61
- }
62
- nodeMappings.push(nodeMapping);
63
- }
64
- }
65
- for (const [markName, markSpec] of Object.entries(schema.marks || {})) {
66
- const adaptSpec = markSpec.spec.automerge;
67
- if (adaptSpec == null) {
68
- continue;
69
- }
70
- if (adaptSpec.markName != null) {
71
- let parsers;
72
- if (adaptSpec.parsers != null) {
73
- parsers = adaptSpec.parsers;
74
- }
75
- else {
76
- parsers = {
77
- fromAutomerge: () => ({}),
78
- fromProsemirror: () => true,
79
- };
80
- }
81
- markMappings.push({
82
- automergeMarkName: adaptSpec.markName,
83
- prosemirrorMark: schema.marks[markName],
84
- parsers,
85
- });
86
- }
87
- }
88
- if (unknownBlock == null) {
89
- throw new Error(`no unknown block specified: one node must be marked as the unknownblock
90
- by setting the automerge.unknownBlock property to true`);
91
- }
92
- this.unknownMark = schema.marks.unknownMark;
93
- this.nodeMappings = nodeMappings;
94
- this.markMappings = markMappings;
95
- this.unknownLeaf = schema.nodes.unknownLeaf;
96
- this.unknownBlock = unknownBlock;
97
- this.schema = schema;
98
- }
99
- }
100
- function shallowClone(spec) {
101
- const nodes = {};
102
- for (const [nodeName, node] of Object.entries(spec.nodes)) {
103
- const shallowCopy = Object.assign({}, node);
104
- if (node.attrs != null) {
105
- shallowCopy.attrs = Object.assign({}, node.attrs);
106
- }
107
- nodes[nodeName] = shallowCopy;
108
- }
109
- const marks = {};
110
- if (spec.marks != null) {
111
- for (const [markName, mark] of Object.entries(spec.marks)) {
112
- const shallowCopy = Object.assign({}, mark);
113
- if (mark.attrs != null) {
114
- shallowCopy.attrs = Object.assign({}, mark.attrs);
115
- }
116
- marks[markName] = shallowCopy;
117
- }
118
- }
119
- return { nodes, marks };
120
- }
121
- export function addAmgNodeStateAttrs(nodes) {
122
- for (const [name, nodeSpec] of Object.entries(nodes)) {
123
- if (name !== 'text') {
124
- if (nodeSpec.attrs == null) {
125
- nodeSpec.attrs = {
126
- isAmgBlock: { default: false },
127
- unknownAttrs: { default: null },
128
- };
129
- }
130
- else {
131
- nodeSpec.attrs.isAmgBlock = { default: false };
132
- nodeSpec.attrs.unknownAttrs = { default: null };
133
- }
134
- }
135
- if (nodeSpec.automerge?.unknownBlock) {
136
- if (nodeSpec.attrs == null) {
137
- nodeSpec.attrs = {
138
- unknownParentBlock: { default: null },
139
- unknownBlock: { default: null },
140
- };
141
- }
142
- else {
143
- nodeSpec.attrs.unknownParentBlock = { default: null };
144
- nodeSpec.attrs.unknownBlock = { default: null };
145
- }
146
- }
147
- }
148
- return nodes;
149
- }
150
- export function amMarksFromPmMarks(adapter, marks) {
151
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
152
- const result = {};
153
- marks.forEach((mark) => {
154
- const markMapping = adapter.markMappings.find((m) => m.prosemirrorMark === mark.type);
155
- if (markMapping != null) {
156
- result[markMapping.automergeMarkName] = markMapping.parsers
157
- .fromProsemirror(mark);
158
- }
159
- else if (mark.type === adapter.unknownMark) {
160
- for (const [key, value] of Object.entries(mark.attrs.unknownMarks)) {
161
- result[key] = value;
162
- }
163
- }
164
- });
165
- return result;
166
- }
167
- export function pmMarksFromAmMarks(adapter, amMarks) {
168
- const unknownMarks = {};
169
- let hasUnknownMark = false;
170
- const pmMarks = [];
171
- for (const [markName, markValue] of Object.entries(amMarks)) {
172
- // Filter tombstoned marks (https://github.com/automerge/automerge/issues/715).
173
- if (markValue == null)
174
- continue;
175
- const mapping = adapter.markMappings.find((m) => m.automergeMarkName === markName);
176
- if (mapping == null) {
177
- unknownMarks[markName] = markValue;
178
- hasUnknownMark = true;
179
- }
180
- else {
181
- pmMarks.push(mapping.prosemirrorMark.create(mapping.parsers.fromAutomerge(markValue)));
182
- }
183
- }
184
- if (hasUnknownMark) {
185
- pmMarks.push(adapter.unknownMark.create({ unknownMarks }));
186
- }
187
- return pmMarks;
188
- }
@@ -1,16 +0,0 @@
1
- import { Plugin, PluginKey } from 'prosemirror-state';
2
- import { next as automerge } from '@automerge/automerge/slim';
3
- import { SchemaAdapter } from './SchemaAdapter.js';
4
- import { DocHandle, DocHandleChangePayload } from './types.js';
5
- export declare const syncPluginKey: PluginKey<any>;
6
- export declare class SyncPlugin<T> extends Plugin {
7
- private adapter;
8
- private path;
9
- ignoreTr: boolean;
10
- onAutoMergeChange: (args: DocHandleChangePayload<unknown>) => void;
11
- private handle;
12
- private view;
13
- constructor(adapter: SchemaAdapter, path: automerge.Prop[], handle: DocHandle<T>);
14
- changeHandle(handle: DocHandle<any>): void;
15
- }
16
- //# sourceMappingURL=SyncPlugin.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SyncPlugin.d.ts","sourceRoot":"","sources":["../../../src/extension-automerge/src/SyncPlugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAa,MAAM,mBAAmB,CAAC;AAGjE,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAI9D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAG/D,eAAO,MAAM,aAAa,gBAAkC,CAAC;AAE7D,qBAAa,UAAU,CAAC,CAAC,CAAE,SAAQ,MAAM;IAQrC,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,IAAI;IARd,QAAQ,UAAS;IACjB,iBAAiB,EAAG,CAAC,IAAI,EAAE,sBAAsB,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IAEpE,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,IAAI,CAAc;gBAGhB,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,EAC9B,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IAiGtB,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC;CAwCpC"}
@@ -1,147 +0,0 @@
1
- import { Plugin, PluginKey, Selection } from 'prosemirror-state';
2
- import { ChangeSet } from 'prosemirror-changeset';
3
- import { next as automerge } from '@automerge/automerge/slim';
4
- import { pmToAm } from './pmToAm.js';
5
- import { amToPm } from './amToPm.js';
6
- import { amSpansToDoc } from './amTraversal.js';
7
- import { isArrayEqual } from './utils.js';
8
- export const syncPluginKey = new PluginKey('automerge-sync');
9
- export class SyncPlugin extends Plugin {
10
- constructor(adapter, path, handle) {
11
- super({
12
- key: syncPluginKey,
13
- view: (view) => {
14
- this.view = view;
15
- this.changeHandle(handle);
16
- return {
17
- destroy: () => {
18
- if (this.handle) {
19
- this.handle.off('change', this.onAutoMergeChange);
20
- }
21
- },
22
- };
23
- },
24
- appendTransaction(transactions, oldState, state) {
25
- if (this.ignoreTr)
26
- return;
27
- transactions = transactions.filter((tx) => tx.docChanged);
28
- if (transactions.length === 0)
29
- return undefined;
30
- //eslint-disable-next-line @typescript-eslint/no-non-null-assertion
31
- const docBefore = this.handle.docSync();
32
- const headsBefore = automerge.getHeads(docBefore);
33
- const spansBefore = automerge.spans(docBefore, path);
34
- // Apply transactions to the automerge doc
35
- this.ignoreTr = true;
36
- this.handle.change((doc) => {
37
- for (const tx of transactions) {
38
- const spans = automerge.spans(doc, path);
39
- pmToAm(adapter, spans, tx.steps, doc, tx.docs[0], path);
40
- }
41
- });
42
- this.ignoreTr = false;
43
- //eslint-disable-next-line @typescript-eslint/no-non-null-assertion
44
- const docAfter = this.handle.docSync();
45
- const headsAfter = automerge.getHeads(docAfter);
46
- const spansAfter = automerge.spans(docAfter, path);
47
- // Ignore if nothing changed.
48
- if (isArrayEqual(headsBefore, headsAfter))
49
- return undefined;
50
- // Check if ProseMirror doc matches the AutoMerge doc
51
- // by comparing changesets between the two transactions.
52
- const patches = automerge.diff(docAfter, headsBefore, headsAfter);
53
- const tx = amToPm(adapter, spansBefore, patches, path, oldState.tr);
54
- let amChangeSet = ChangeSet.create(oldState.doc);
55
- amChangeSet = amChangeSet.addSteps(oldState.doc, tx.mapping.maps, undefined);
56
- let pmChangeSet = ChangeSet.create(oldState.doc);
57
- for (const tr of transactions) {
58
- pmChangeSet = pmChangeSet.addSteps(tr.docs[0], tr.mapping.maps, undefined);
59
- }
60
- const diff = pmChangeSet.changedRange(amChangeSet);
61
- if (!diff || diff.from === diff.to)
62
- return undefined;
63
- console.warn("Warning: ProseMirror doc doesn't match AutoMerge spans.\n\n" +
64
- 'State will be automatically fixed with a tr. File an issue at https://github.com/automerge/automerge-repo.\n', {
65
- spansBefore,
66
- steps: transactions.map((tr) => tr.steps.map((s) => s.toJSON())),
67
- });
68
- // Replace the diff range in ProseMirror doc from the AutoMerge doc.
69
- const doc = amSpansToDoc(adapter, spansAfter);
70
- const slice = doc.slice(diff.from, diff.to);
71
- const tr = state.tr;
72
- tr.replace(diff.from, diff.to, slice);
73
- try {
74
- tr.setSelection(Selection.fromJSON(tr.doc, state.selection.toJSON()));
75
- }
76
- catch (e) {
77
- if (e instanceof RangeError) {
78
- // Sometimes the selection can't be mapped for some reason, so we just give up and hope for the best
79
- }
80
- else {
81
- throw e;
82
- }
83
- }
84
- tr.setStoredMarks(state.storedMarks);
85
- return tr;
86
- },
87
- });
88
- Object.defineProperty(this, "adapter", {
89
- enumerable: true,
90
- configurable: true,
91
- writable: true,
92
- value: adapter
93
- });
94
- Object.defineProperty(this, "path", {
95
- enumerable: true,
96
- configurable: true,
97
- writable: true,
98
- value: path
99
- });
100
- Object.defineProperty(this, "ignoreTr", {
101
- enumerable: true,
102
- configurable: true,
103
- writable: true,
104
- value: false
105
- });
106
- Object.defineProperty(this, "onAutoMergeChange", {
107
- enumerable: true,
108
- configurable: true,
109
- writable: true,
110
- value: void 0
111
- });
112
- Object.defineProperty(this, "handle", {
113
- enumerable: true,
114
- configurable: true,
115
- writable: true,
116
- value: void 0
117
- });
118
- Object.defineProperty(this, "view", {
119
- enumerable: true,
120
- configurable: true,
121
- writable: true,
122
- value: void 0
123
- });
124
- }
125
- changeHandle(handle) {
126
- if (!this.view) {
127
- return;
128
- }
129
- if (this.handle) {
130
- this.handle.off('change', this.onAutoMergeChange);
131
- }
132
- const onAutoMergeChange = ({ doc, patches, patchInfo, }) => {
133
- if (this.ignoreTr)
134
- return;
135
- const headsBefore = automerge.getHeads(patchInfo.before);
136
- const spans = automerge.spans(automerge.view(doc, headsBefore), this.path);
137
- const tr = amToPm(this.adapter, spans, patches, this.path, this.view.state.tr);
138
- tr.setMeta('addToHistory', false); // remote changes should not be added to local stack
139
- this.ignoreTr = true;
140
- this.view.dispatch(tr);
141
- this.ignoreTr = false;
142
- };
143
- this.onAutoMergeChange = onAutoMergeChange;
144
- handle.on('change', this.onAutoMergeChange);
145
- this.handle = handle;
146
- }
147
- }
@@ -1,9 +0,0 @@
1
- import { next as automerge, Patch, type Prop } from '@automerge/automerge/slim';
2
- import { Transaction } from 'prosemirror-state';
3
- import { SchemaAdapter } from './SchemaAdapter.js';
4
- type SpliceTextPatch = automerge.SpliceTextPatch;
5
- export declare function amToPm(adapter: SchemaAdapter, spansAtStart: automerge.Span[], patches: Array<Patch>, path: Prop[], tx: Transaction): Transaction;
6
- export declare function handleSplice(adapter: SchemaAdapter, spans: automerge.Span[], patch: SpliceTextPatch, path: Prop[], tx: Transaction): Transaction;
7
- export declare function handleBlockChange(adapter: SchemaAdapter, atPath: automerge.Prop[], spans: automerge.Span[], _blockIdx: number, patches: automerge.Patch[], tx: Transaction): Transaction;
8
- export {};
9
- //# sourceMappingURL=amToPm.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"amToPm.d.ts","sourceRoot":"","sources":["../../../src/extension-automerge/src/amToPm.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,IAAI,IAAI,SAAS,EACjB,KAAK,EACL,KAAK,IAAI,EACV,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAMhD,OAAO,EAAsB,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEvE,KAAK,eAAe,GAAG,SAAS,CAAC,eAAe,CAAC;AAQjD,wBAAgB,MAAM,CACpB,OAAO,EAAE,aAAa,EACtB,YAAY,EAAE,SAAS,CAAC,IAAI,EAAE,EAC9B,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,EACrB,IAAI,EAAE,IAAI,EAAE,EACZ,EAAE,EAAE,WAAW,GACd,WAAW,CA0Cb;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,SAAS,CAAC,IAAI,EAAE,EACvB,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,IAAI,EAAE,EACZ,EAAE,EAAE,WAAW,GACd,WAAW,CAQb;AAkDD,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,SAAS,CAAC,IAAI,EAAE,EACxB,KAAK,EAAE,SAAS,CAAC,IAAI,EAAE,EACvB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,SAAS,CAAC,KAAK,EAAE,EAC1B,EAAE,EAAE,WAAW,GACd,WAAW,CA0Cb"}
@@ -1,245 +0,0 @@
1
- import { Fragment, Slice } from 'prosemirror-model';
2
- import { ReplaceStep } from 'prosemirror-transform';
3
- import { amSpansToDoc, amSpliceIdxToPmIdx } from './amTraversal.js';
4
- import { findBlockAtCharIdx, patchSpans } from './maintainSpans.js';
5
- import { isArrayEqual, isPrefixOfArray } from './utils.js';
6
- import { pmMarksFromAmMarks } from './SchemaAdapter.js';
7
- export function amToPm(adapter, spansAtStart, patches, path, tx) {
8
- const gathered = gatherPatches(path, patches);
9
- for (const patchGroup of gathered) {
10
- if (patchGroup.type === 'text') {
11
- for (const patch of patchGroup.patches) {
12
- if (patch.action === 'splice') {
13
- tx = handleSplice(adapter, spansAtStart, patch, path, tx);
14
- patchSpans(path, spansAtStart, patch);
15
- }
16
- else if (patch.action === 'del') {
17
- const patchIndex = patch.path[patch.path.length - 1];
18
- const block = findBlockAtCharIdx(spansAtStart, patchIndex);
19
- if (block != null) {
20
- tx = handleBlockChange(adapter, path, spansAtStart, patchIndex, [patch], tx);
21
- }
22
- else {
23
- tx = handleDelete(adapter, spansAtStart, patch, path, tx);
24
- }
25
- patchSpans(path, spansAtStart, patch);
26
- }
27
- else if (patch.action === 'mark') {
28
- tx = handleMark(adapter, spansAtStart, patch, path, tx);
29
- patchSpans(path, spansAtStart, patch);
30
- }
31
- }
32
- }
33
- else {
34
- tx = handleBlockChange(adapter, path, spansAtStart, patchGroup.index, patchGroup.patches, tx);
35
- }
36
- }
37
- return tx;
38
- }
39
- export function handleSplice(adapter, spans, patch, path, tx) {
40
- const index = charPath(path, patch.path);
41
- if (index === null)
42
- return tx;
43
- const pmIdx = amSpliceIdxToPmIdx(adapter, spans, index);
44
- if (pmIdx == null)
45
- throw new Error('Invalid index');
46
- const content = patchContentToFragment(adapter, patch.value, patch.marks);
47
- tx = tx.step(new ReplaceStep(pmIdx, pmIdx, new Slice(content, 0, 0)));
48
- return tx;
49
- }
50
- function handleDelete(adapter, spans, patch, path, tx) {
51
- const index = charPath(path, patch.path);
52
- if (index === null)
53
- return tx;
54
- const start = amSpliceIdxToPmIdx(adapter, spans, index);
55
- if (start == null)
56
- throw new Error('Invalid index');
57
- const end = start + (patch.length || 1);
58
- return tx.delete(start, end);
59
- }
60
- function handleMark(adapter, spans, patch, path, tx) {
61
- if (isArrayEqual(patch.path, path)) {
62
- for (const mark of patch.marks) {
63
- const pmStart = amSpliceIdxToPmIdx(adapter, spans, mark.start);
64
- const pmEnd = amSpliceIdxToPmIdx(adapter, spans, mark.end);
65
- if (pmStart == null || pmEnd == null)
66
- throw new Error('Invalid index');
67
- if (mark.value == null) {
68
- const markMapping = adapter.markMappings.find((m) => m.automergeMarkName === mark.name);
69
- const markType = markMapping
70
- ? markMapping.prosemirrorMark
71
- : adapter.unknownMark;
72
- tx = tx.removeMark(pmStart, pmEnd, markType);
73
- }
74
- else {
75
- const pmMarks = pmMarksFromAmMarks(adapter, {
76
- [mark.name]: mark.value,
77
- });
78
- for (const pmMark of pmMarks) {
79
- tx = tx.addMark(pmStart, pmEnd, pmMark);
80
- }
81
- }
82
- }
83
- }
84
- return tx;
85
- }
86
- export function handleBlockChange(adapter, atPath, spans, _blockIdx, patches, tx) {
87
- for (const patch of patches) {
88
- patchSpans(atPath, spans, patch);
89
- }
90
- const docAfter = amSpansToDoc(adapter, spans);
91
- const change = findDiff(tx.doc.content, docAfter.content);
92
- if (change == null)
93
- return tx;
94
- const $from = docAfter.resolve(change.start);
95
- const $to = docAfter.resolve(change.endB);
96
- const $fromA = tx.doc.resolve(change.start);
97
- const inlineChange = $from.sameParent($to) &&
98
- $from.parent.inlineContent &&
99
- $fromA.end() >= change.endA;
100
- const chFrom = change.start;
101
- const chTo = change.endA;
102
- let handledByInline = false;
103
- if (inlineChange) {
104
- if ($from.pos == $to.pos) {
105
- // Deletion
106
- handledByInline = true;
107
- tx = tx.delete(chFrom, chTo);
108
- }
109
- else if ($from.parent.child($from.index()).isText &&
110
- $from.index() == $to.index() - ($to.textOffset ? 0 : 1)) {
111
- handledByInline = true;
112
- // Both positions in the same text node -- simply insert text
113
- const text = $from.parent.textBetween($from.parentOffset, $to.parentOffset);
114
- tx = tx.insertText(text, chFrom, chTo);
115
- }
116
- }
117
- if (!handledByInline) {
118
- tx = tx.replace(chFrom, chTo, docAfter.slice(change.start, change.endB));
119
- }
120
- return tx;
121
- }
122
- function findDiff(a, b) {
123
- let start = a.findDiffStart(b);
124
- if (start == null)
125
- return null;
126
- //eslint-disable-next-line @typescript-eslint/no-non-null-assertion
127
- let { a: endA, b: endB } = a.findDiffEnd(b);
128
- if (endA < start && a.size < b.size) {
129
- if (start &&
130
- start < b.size &&
131
- isSurrogatePair(b.textBetween(start - 1, start + 1))) {
132
- start -= 1;
133
- }
134
- endB = start + (endB - endA);
135
- endA = start;
136
- }
137
- else if (endB < start) {
138
- if (start &&
139
- start < a.size &&
140
- isSurrogatePair(a.textBetween(start - 1, start + 1))) {
141
- start -= 1;
142
- }
143
- endA = start + (endA - endB);
144
- endB = start;
145
- }
146
- return { start, endA, endB };
147
- }
148
- function isSurrogatePair(str) {
149
- if (str.length != 2)
150
- return false;
151
- const a = str.charCodeAt(0), b = str.charCodeAt(1);
152
- return a >= 0xdc00 && a <= 0xdfff && b >= 0xd800 && b <= 0xdbff;
153
- }
154
- // If the path of the patch is of the form [path, <index>] then we know this is
155
- // a path to a character within the sequence given by path
156
- function charPath(textPath, candidatePath) {
157
- if (candidatePath.length !== textPath.length + 1)
158
- return null;
159
- for (let i = 0; i < textPath.length; i++) {
160
- if (textPath[i] !== candidatePath[i])
161
- return null;
162
- }
163
- const index = candidatePath[candidatePath.length - 1];
164
- if (typeof index === 'number')
165
- return index;
166
- return null;
167
- }
168
- function patchContentToFragment(adapter, patchContent, marks) {
169
- let pmMarks = undefined;
170
- if (marks != null) {
171
- pmMarks = pmMarksFromAmMarks(adapter, marks);
172
- }
173
- // Splice is only ever called once a block has already been created so we're
174
- // only inserting text. This means we don't have to think about openStart
175
- // and openEnd
176
- return Fragment.from(adapter.schema.text(patchContent, pmMarks));
177
- }
178
- function gatherPatches(textPath, diff) {
179
- const result = [];
180
- let state = { type: 'gatheringText', gathered: [] };
181
- function flush() {
182
- if (state.type === 'gatheringBlock') {
183
- result.push({
184
- type: 'block',
185
- index: state.index,
186
- patches: state.gathered,
187
- });
188
- }
189
- else if (state.type === 'gatheringText') {
190
- result.push({ type: 'text', patches: state.gathered });
191
- }
192
- state = { type: 'transitioning' };
193
- }
194
- for (const patch of diff) {
195
- if (!isPrefixOfArray(textPath, patch.path)) {
196
- continue;
197
- }
198
- if (isArrayEqual(textPath, patch.path) && patch.action === 'mark') {
199
- if (state.type === 'gatheringText') {
200
- state.gathered.push(patch);
201
- }
202
- else {
203
- flush();
204
- state = { type: 'gatheringText', gathered: [patch] };
205
- }
206
- }
207
- else if (patch.path.length === textPath.length + 1) {
208
- const lastElem = patch.path[patch.path.length - 1];
209
- if (typeof lastElem === 'number') {
210
- if (patch.action === 'splice' || patch.action === 'del') {
211
- if (state.type === 'gatheringText') {
212
- state.gathered.push(patch);
213
- }
214
- else {
215
- flush();
216
- state = { type: 'gatheringText', gathered: [patch] };
217
- }
218
- }
219
- else if (patch.action === 'insert') {
220
- flush();
221
- state = {
222
- type: 'gatheringBlock',
223
- index: lastElem,
224
- gathered: [patch],
225
- };
226
- }
227
- }
228
- }
229
- else {
230
- const index = patch.path[textPath.length];
231
- if (typeof index !== 'number') {
232
- continue;
233
- }
234
- if (state.type === 'gatheringBlock' && state.index === index) {
235
- state.gathered.push(patch);
236
- }
237
- else {
238
- flush();
239
- state = { type: 'gatheringBlock', index: index, gathered: [patch] };
240
- }
241
- }
242
- }
243
- flush();
244
- return result;
245
- }
@@ -1,62 +0,0 @@
1
- import { next as automerge } from '@automerge/automerge/slim';
2
- import { Node } from 'prosemirror-model';
3
- import { BlockMarker } from './types.js';
4
- import { SchemaAdapter } from './SchemaAdapter.js';
5
- type RenderRole = 'explicit' | 'render-only';
6
- export type TraversalEvent = {
7
- type: 'openTag';
8
- tag: string;
9
- role: RenderRole;
10
- attrs?: {
11
- [key: string]: any;
12
- };
13
- } | {
14
- type: 'closeTag';
15
- tag: string;
16
- role: RenderRole;
17
- } | {
18
- type: 'leafNode';
19
- tag: string;
20
- role: RenderRole;
21
- } | {
22
- type: 'text';
23
- text: string;
24
- marks: automerge.MarkSet;
25
- } | {
26
- type: 'block';
27
- isUnknown?: boolean;
28
- block: {
29
- type: string;
30
- parents: string[];
31
- attrs: {
32
- [key: string]: automerge.MaterializeValue;
33
- };
34
- isEmbed: boolean;
35
- };
36
- };
37
- /**
38
- * Convert an array of AutoMerge spans into a ProseMirror doc.
39
- * @param adapter
40
- * @param spans
41
- * @returns
42
- */
43
- export declare function amSpansToDoc(adapter: SchemaAdapter, spans: automerge.Span[]): Node;
44
- export declare function amSpliceIdxToPmIdx(adapter: SchemaAdapter, spans: automerge.Span[], target: number): number | null;
45
- export declare function amIdxToPmBlockIdx(adapter: SchemaAdapter, spans: automerge.Span[], target: number): number | null;
46
- type Indexes = {
47
- amIdx: number;
48
- pmIdx: number;
49
- };
50
- export declare function eventsWithIndexChanges(events: IterableIterator<TraversalEvent>): IterableIterator<{
51
- event: TraversalEvent;
52
- before: Indexes;
53
- after: Indexes;
54
- }>;
55
- export declare function traverseNode(adapter: SchemaAdapter, node: Node): IterableIterator<TraversalEvent>;
56
- export declare function traverseSpans(adapter: SchemaAdapter, amSpans: automerge.Span[]): IterableIterator<TraversalEvent>;
57
- export declare function blockAtIdx(spans: automerge.Span[], target: number): {
58
- index: number;
59
- block: BlockMarker;
60
- } | null;
61
- export {};
62
- //# sourceMappingURL=amTraversal.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"amTraversal.d.ts","sourceRoot":"","sources":["../../../src/extension-automerge/src/amTraversal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAGL,IAAI,EAGL,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAgB,WAAW,EAAiB,MAAM,YAAY,CAAC;AACtE,OAAO,EAIL,aAAa,EACd,MAAM,oBAAoB,CAAC;AAE5B,KAAK,UAAU,GAAG,UAAU,GAAG,aAAa,CAAC;AAO7C,MAAM,MAAM,cAAc,GACtB;IACA,IAAI,EAAE,SAAS,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,UAAU,CAAC;IAEjB,KAAK,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;CAChC,GACC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAC,OAAO,CAAA;CAAE,GACxD;IACA,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,KAAK,EAAE;YAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC,gBAAgB,CAAA;SAAE,CAAC;QACrD,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC;CACH,CAAC;AAEJ;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,SAAS,CAAC,IAAI,EAAE,GACtB,IAAI,CAyDN;AAqCD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,SAAS,CAAC,IAAI,EAAE,EACvB,MAAM,EAAE,MAAM,GACb,MAAM,GAAG,IAAI,CAyBf;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,SAAS,CAAC,IAAI,EAAE,EACvB,MAAM,EAAE,MAAM,GACb,MAAM,GAAG,IAAI,CA4Bf;AAED,KAAK,OAAO,GAAG;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAiB,sBAAsB,CACrC,MAAM,EAAE,gBAAgB,CAAC,cAAc,CAAC,GACvC,gBAAgB,CAAC;IAClB,KAAK,EAAE,cAAc,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC,CA2BD;AAED,wBAAiB,YAAY,CAC3B,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,IAAI,GACT,gBAAgB,CAAC,cAAc,CAAC,CA4ElC;AAwPD,wBAAiB,aAAa,CAC5B,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,SAAS,CAAC,IAAI,EAAE,GACxB,gBAAgB,CAAC,cAAc,CAAC,CAkBlC;AAmOD,wBAAgB,UAAU,CACxB,KAAK,EAAE,SAAS,CAAC,IAAI,EAAE,EACvB,MAAM,EAAE,MAAM,GACb;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,GAAG,IAAI,CAoB9C"}