Skip to content

Commit 643eb36

Browse files
committed
feat: add XMLEditor implements Transactor<EditV2>
1 parent 2722c7a commit 643eb36

File tree

7 files changed

+861
-1716
lines changed

7 files changed

+861
-1716
lines changed

Editor.ts

Lines changed: 0 additions & 141 deletions
This file was deleted.

Transactor.d.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export interface CommitOptions {
2+
title?: string;
3+
squash?: boolean;
4+
}
5+
export interface Commit<Change> {
6+
undo: Change[];
7+
redo: Change[];
8+
title?: string;
9+
}
10+
export type TransactedCallback<Change> = (txRecord: Commit<Change>) => void;
11+
export interface Transactor<Change> {
12+
commit(change: Change, options?: CommitOptions): Commit<Change>;
13+
undo(): Commit<Change> | undefined;
14+
redo(): Commit<Change> | undefined;
15+
canUndo: boolean;
16+
canRedo: boolean;
17+
past: Commit<Change>[];
18+
future: Commit<Change>[];
19+
subscribe(
20+
txCallback: TransactedCallback<Change>,
21+
): () => TransactedCallback<Change>;
22+
}

Editor.spec.ts renamed to XMLEditor.spec.ts

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,23 @@ import {
1818

1919
import { EditV2, isSetAttributes, isSetTextContent } from "./editv2.js";
2020

21-
import { Editor, EditV2Editor } from "./Editor.js";
21+
import { XMLEditor } from "./XMLEditor.js";
22+
import { Transactor } from "./Transactor.js";
2223

2324
describe("Utility function to handle EditV2 edits", () => {
24-
let editor: Editor<EditV2>;
25+
let editor: Transactor<EditV2>;
2526
let sclDoc: XMLDocument;
2627

2728
beforeEach(async () => {
28-
editor = new EditV2Editor();
29+
editor = new XMLEditor();
2930
sclDoc = new DOMParser().parseFromString(sclDocString, "application/xml");
3031
});
3132

3233
it("inserts an element on Insert", () => {
3334
const parent = sclDoc.documentElement;
3435
const node = sclDoc.createElement("test");
3536
const reference = sclDoc.querySelector("Substation");
36-
editor.edit({ parent, node, reference }, {});
37+
editor.commit({ parent, node, reference });
3738
expect(sclDoc.documentElement.querySelector("test")).to.have.property(
3839
"nextSibling",
3940
reference,
@@ -42,14 +43,14 @@ describe("Utility function to handle EditV2 edits", () => {
4243

4344
it("removes an element on Remove", () => {
4445
const node = sclDoc.querySelector("Substation")!;
45-
editor.edit({ node }, {});
46+
editor.commit({ node });
4647

4748
expect(sclDoc.querySelector("Substation")).to.not.exist;
4849
});
4950

5051
it("updates an element's attributes on SetAttributes", () => {
5152
const element = sclDoc.querySelector("Substation")!;
52-
editor.edit(
53+
editor.commit(
5354
{
5455
element,
5556
attributes: {
@@ -90,7 +91,7 @@ describe("Utility function to handle EditV2 edits", () => {
9091
const element = sclDoc.querySelector("SCL")!;
9192

9293
const newTextContent = "someNewTextContent";
93-
editor.edit({
94+
editor.commit({
9495
element,
9596
textContent: newTextContent,
9697
});
@@ -129,25 +130,22 @@ describe("Utility function to handle EditV2 edits", () => {
129130
textContent: "someNewTextContent",
130131
};
131132

132-
editor.edit(edit1, {});
133-
editor.edit(edit2, { squash: true });
133+
editor.commit(edit1, {});
134+
editor.commit(edit2, { squash: true });
134135

135-
const history = editor.history;
136+
const history = editor.past;
136137
expect(history).to.have.length(1);
137138

138139
expect((history[0].undo as EditV2[])[0]).to.satisfy(isSetTextContent);
139140
expect((history[0].undo as EditV2[])[1]).to.satisfy(isSetAttributes);
140-
141-
expect(editor.docVersion).to.equal(2);
142-
expect(editor.editCount).to.equal(1);
143141
});
144142

145143
it("processes complex edits in the given order", () => {
146144
const parent = sclDoc.documentElement;
147145
const reference = sclDoc.querySelector("Substation");
148146
const node1 = sclDoc.createElement("test1");
149147
const node2 = sclDoc.createElement("test2");
150-
editor.edit(
148+
editor.commit(
151149
[
152150
{ parent, node: node1, reference },
153151
{ parent, node: node2, reference },
@@ -162,29 +160,25 @@ describe("Utility function to handle EditV2 edits", () => {
162160
"nextSibling",
163161
reference,
164162
);
165-
166-
expect(editor.docVersion).to.equal(1);
167163
});
168164

169165
it("undoes a committed edit on undo() call", () => {
170166
const node = sclDoc.querySelector("Substation")!;
171167

172-
editor.edit({ node });
168+
editor.commit({ node });
173169
editor.undo();
174170

175171
expect(sclDoc.querySelector("Substation")).to.exist;
176-
expect(editor.docVersion).to.equal(2);
177172
});
178173

179174
it("redoes an undone edit on redo() call", () => {
180175
const node = sclDoc.querySelector("Substation")!;
181176

182-
editor.edit({ node });
177+
editor.commit({ node });
183178
editor.undo();
184179
editor.redo();
185180

186181
expect(sclDoc.querySelector("Substation")).to.be.null;
187-
expect(editor.docVersion).to.equal(3);
188182
});
189183

190184
describe("generally", () => {
@@ -196,7 +190,7 @@ describe("Utility function to handle EditV2 edits", () => {
196190
return insert(nodes);
197191
}),
198192
(edit) => {
199-
editor.edit(edit);
193+
editor.commit(edit);
200194
if (isValidInsert(edit))
201195
return (
202196
edit.node.parentElement === edit.parent &&
@@ -215,7 +209,7 @@ describe("Utility function to handle EditV2 edits", () => {
215209
return setTextContent(nodes);
216210
}),
217211
(edit) => {
218-
editor.edit(edit);
212+
editor.commit(edit);
219213

220214
return edit.element.textContent === edit.textContent;
221215
},
@@ -227,7 +221,7 @@ describe("Utility function to handle EditV2 edits", () => {
227221
property(
228222
testDocs.chain(([{ nodes }]) => setAttributes(nodes)),
229223
(edit) => {
230-
editor.edit(edit);
224+
editor.commit(edit);
231225
return (
232226
Object.entries(edit.attributes)
233227
.filter(([name]) => xmlAttributeName.test(name))
@@ -263,7 +257,7 @@ describe("Utility function to handle EditV2 edits", () => {
263257
property(
264258
testDocs.chain(([{ nodes }]) => remove(nodes)),
265259
({ node }) => {
266-
editor.edit({ node });
260+
editor.commit({ node });
267261
return !node.parentNode;
268262
},
269263
),
@@ -278,9 +272,9 @@ describe("Utility function to handle EditV2 edits", () => {
278272
doc.cloneNode(true),
279273
);
280274
edits.forEach((a: EditV2) => {
281-
editor.edit(a, { squash });
275+
editor.commit(a, { squash });
282276
});
283-
if (editor.editCount) editor.undo(editor.editCount);
277+
while (editor.canUndo) editor.undo();
284278
expect(doc1).to.satisfy((doc: XMLDocument) =>
285279
doc.isEqualNode(oldDoc1),
286280
);
@@ -298,16 +292,14 @@ describe("Utility function to handle EditV2 edits", () => {
298292
testDocs.chain((docs) => undoRedoTestCases(...docs)),
299293
({ doc1, doc2, edits }: UndoRedoTestCase) => {
300294
edits.forEach((a: EditV2) => {
301-
editor.edit(a);
295+
editor.commit(a);
302296
});
303297
const [oldDoc1, oldDoc2] = [doc1, doc2].map((doc) =>
304298
new XMLSerializer().serializeToString(doc),
305299
);
306300

307-
if (edits.length) {
308-
editor.undo(edits.length + 1);
309-
editor.redo(edits.length + 1);
310-
}
301+
while (editor.canUndo) editor.undo();
302+
while (editor.canRedo) editor.redo();
311303
const [newDoc1, newDoc2] = [doc1, doc2].map((doc) =>
312304
new XMLSerializer().serializeToString(doc),
313305
);

0 commit comments

Comments
 (0)