Skip to content

Commit 522698d

Browse files
committed
feat(yata): fix test cases
1 parent 7d72940 commit 522698d

File tree

6 files changed

+111
-13
lines changed

6 files changed

+111
-13
lines changed

.vscode/launch.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@
44
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
55
"version": "0.2.0",
66
"configurations": [
7+
{
8+
"name": "prosemirror/yata npm run test",
9+
"request": "launch",
10+
"runtimeArgs": ["run-script", "test"],
11+
"runtimeExecutable": "npm",
12+
"skipFiles": ["<node_internals>/**"],
13+
"type": "node",
14+
"cwd": "${workspaceFolder}/libraries/prosemirror/yata"
15+
},
716
{
817
"type": "node",
918
"request": "launch",

libraries/prosemirror/yata/index.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,24 @@ import { EditorState } from 'prosemirror-state';
66
import { EditorView } from 'prosemirror-view';
77
import { exampleSetup } from 'prosemirror-example-setup';
88
import schema from './schema.js';
9+
import { Document } from './yata/index.js';
910

1011
const state = EditorState.create({
1112
schema,
1213
plugins: exampleSetup({ schema: schema }),
1314
});
1415

16+
const doc = Document.fromNodes(state.doc.content);
17+
1518
const view = new EditorView(document.querySelector('#editor'), {
1619
state,
20+
dispatchTransaction(tr) {
21+
view.updateState(view.state.apply(tr));
22+
tr.steps.forEach(function (step) {
23+
doc.applyStep(step);
24+
});
25+
},
1726
});
1827

1928
window.view = view;
29+
window.doc = doc;

libraries/prosemirror/yata/yata/__tests__/item.test.js

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
NodeItem,
1010
sliceToItems,
1111
} from '../item.js';
12+
import { Document, Position } from '../document.js';
1213

1314
describe('nodeToItems', function () {
1415
test('all nodes', function () {
@@ -27,7 +28,7 @@ describe('nodeToItems', function () {
2728
attrs: {},
2829
tagName: 'paragraph',
2930
type: 'openingTag',
30-
closingId: null,
31+
closingTagItem: null,
3132
},
3233
{
3334
marks: [
@@ -68,7 +69,7 @@ describe('nodeToItems', function () {
6869
{
6970
tagName: 'paragraph',
7071
type: 'closingTag',
71-
openingId: null,
72+
openingTagItem: null,
7273
},
7374
]);
7475
});
@@ -117,13 +118,13 @@ describe('sliceToItems', () => {
117118
{
118119
tagName: 'paragraph',
119120
type: 'closingTag',
120-
openingId: null,
121+
openingTagItem: null,
121122
},
122123
{
123124
attrs: {},
124125
tagName: 'paragraph',
125126
type: 'openingTag',
126-
closingId: null,
127+
closingTagItem: null,
127128
},
128129
{
129130
marks: [
@@ -164,7 +165,7 @@ describe('sliceToItems', () => {
164165
{
165166
tagName: 'paragraph',
166167
type: 'closingTag',
167-
openingId: null,
168+
openingTagItem: null,
168169
},
169170
]);
170171
});
@@ -194,3 +195,23 @@ describe('itemsToSlice', () => {
194195
expect(slice.size).toBe(items.length);
195196
});
196197
});
198+
199+
describe('integrate', function () {
200+
test('integrate into empty doc', function () {
201+
const doc = new Document();
202+
const pos = new Position(doc);
203+
const item = new TextItem('1');
204+
item.integrate(pos);
205+
expect(doc.head).toBe(item);
206+
expect(doc.clock).toBe(1);
207+
});
208+
209+
test('integrate into tags', function () {
210+
const doc = Document.fromNodes(Fragment.from([schema.node('paragraph')]));
211+
const pos = new Position(doc);
212+
pos.forward();
213+
const item = new TextItem('1');
214+
item.integrate(pos);
215+
expect(doc.clock).toBe(3);
216+
});
217+
});

libraries/prosemirror/yata/yata/document.js

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,18 @@
22
* @since 2022-03-12
33
* @author vivaxy
44
*/
5-
import { ReplaceStep } from 'prosemirror-transform';
6-
import { ClosingTagItem, OpeningTagItem, sliceToItems } from './item.js';
5+
import {
6+
AddMarkStep,
7+
RemoveMarkStep,
8+
ReplaceStep,
9+
ReplaceAroundStep,
10+
} from 'prosemirror-transform';
11+
import {
12+
ClosingTagItem,
13+
OpeningTagItem,
14+
sliceToItems,
15+
fragmentToItems,
16+
} from './item.js';
717

818
export class Position {
919
constructor(doc) {
@@ -25,6 +35,9 @@ export class Position {
2535
}
2636

2737
forwardItem() {
38+
if (!this.canForward()) {
39+
throw new Error(`Unexpected position ${this.pos + 1}`);
40+
}
2841
this.left = this.right;
2942
this.right = this.right.right;
3043
if (!this.left.deleted) {
@@ -49,6 +62,16 @@ export class Position {
4962
}
5063

5164
export class Document {
65+
static fromNodes(nodes) {
66+
const doc = new Document();
67+
const items = fragmentToItems(nodes);
68+
const pos = new Position(doc);
69+
items.forEach(function (item) {
70+
item.integrate(pos);
71+
});
72+
return doc;
73+
}
74+
5275
constructor() {
5376
this.head = null;
5477
this.client = Math.random().toString(36).slice(2);
@@ -101,13 +124,42 @@ export class Document {
101124
applyStep(step) {
102125
if (step instanceof ReplaceStep) {
103126
this.applyReplaceStep(step);
127+
} else if (step instanceof ReplaceAroundStep) {
128+
this.applyReplaceAroundStep(step);
129+
} else if (step instanceof AddMarkStep) {
130+
this.applyAddMarkStep(step);
131+
} else if (step instanceof RemoveMarkStep) {
132+
this.applyRemoveMarkStep(step);
133+
} else {
134+
throw new Error('Unexpected step');
104135
}
105136
}
106137

107138
applyReplaceStep(step) {
108139
this.replaceItems(step.from, step.to, sliceToItems(step.slice));
109140
}
110141

142+
applyReplaceAroundStep(step) {
143+
this.replaceItems(
144+
step.gapTo,
145+
step.to,
146+
sliceToItems(step.slice).slice(step.insert),
147+
);
148+
this.replaceItems(
149+
step.from,
150+
step.gapFrom,
151+
sliceToItems(step.slice).slice(0, step.insert),
152+
);
153+
}
154+
155+
applyAddMarkStep(step) {
156+
// TODO
157+
}
158+
159+
applyRemoveMarkStep(step) {
160+
// TODO
161+
}
162+
111163
applyItems() {
112164
// TODO
113165
}

libraries/prosemirror/yata/yata/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
* @since 2022-03-12
33
* @author vivaxy
44
*/
5+
export { Document } from './document.js';

libraries/prosemirror/yata/yata/item.js

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ export class Item {
6363

6464
integrate(position) {
6565
this.integrateSimple(position.doc, position.left, position.right);
66+
if (position.left === null && position.right === null) {
67+
// empty doc
68+
position.doc.head = this;
69+
}
6670
position.left = this;
6771
}
6872

@@ -78,6 +82,7 @@ export class TextItem extends Item {
7882
constructor(text, marks = []) {
7983
super();
8084
this.text = text;
85+
// todo marks should be items too
8186
this.marks = marks.map((mark) => {
8287
return mark.toJSON();
8388
});
@@ -118,7 +123,7 @@ export class OpeningTagItem extends Item {
118123
type: 'openingTag',
119124
tagName: this.tagName,
120125
attrs: this.attrs,
121-
closingTagItem: this.closingTagItem?.id,
126+
closingTagItem: this.closingTagItem.id,
122127
};
123128
}
124129

@@ -214,11 +219,11 @@ export function nodeToItems(node) {
214219
if (node.isAtom) {
215220
return [new NodeItem(node.type.name, node.attrs)];
216221
}
217-
return [
218-
new OpeningTagItem(node.type.name, node.attrs),
219-
...fragmentToItems(node.content),
220-
new ClosingTagItem(node.type.name, node.attrs),
221-
];
222+
const openingTagItem = new OpeningTagItem(node.type.name, node.attrs);
223+
const closingTagItem = new ClosingTagItem(node.type.name, node.attrs);
224+
openingTagItem.closingTagItem = closingTagItem;
225+
closingTagItem.openingTagItem = openingTagItem;
226+
return [openingTagItem, ...fragmentToItems(node.content), closingTagItem];
222227
}
223228

224229
export function itemsToSlice(items, schema) {

0 commit comments

Comments
 (0)