diff --git a/src/json-crdt-extensions/peritext/block/Fragment.ts b/src/json-crdt-extensions/peritext/block/Fragment.ts
index 7c7fb875a1..be021219b3 100644
--- a/src/json-crdt-extensions/peritext/block/Fragment.ts
+++ b/src/json-crdt-extensions/peritext/block/Fragment.ts
@@ -33,7 +33,9 @@ export class Fragment extends Range implements Printable, Stateful {
// ------------------------------------------------------------------- export
public toJson(): PeritextMlElement {
- return this.root.toJson();
+ const node = this.root.toJson();
+ node[0] = '';
+ return node;
}
// ---------------------------------------------------------------- Printable
diff --git a/src/json-crdt-extensions/peritext/block/__tests__/Fragment-export.spec.ts b/src/json-crdt-extensions/peritext/block/__tests__/Fragment-export.spec.ts
index 750329e85a..6a36dd9b07 100644
--- a/src/json-crdt-extensions/peritext/block/__tests__/Fragment-export.spec.ts
+++ b/src/json-crdt-extensions/peritext/block/__tests__/Fragment-export.spec.ts
@@ -1,7 +1,5 @@
-import {
- type Kit,
- setupAlphabetKit,
-} from '../../__tests__/setup';
+import {type Kit, runAlphabetKitTestSuite} from '../../__tests__/setup';
+import {toJsonMl} from '../../export/toJsonMl';
import {CommonSliceType} from '../../slice';
const runTests = (setup: () => Kit) => {
@@ -12,30 +10,44 @@ const runTests = (setup: () => Kit) => {
peritext.refresh();
const fragment = peritext.fragment(peritext.rangeAt(4, 10));
fragment.refresh();
- expect(fragment.toJsonMl()).toEqual([
- 'div',
- {},
- ['p', {}, 'efghij'],
- ['p', {}, 'klm'],
+ const html = toJsonMl(fragment.toJson());
+ expect(html).toEqual([
+ '',
+ null,
+ ['p', null, 'efghij'],
+ ['p', null, 'klm'],
]);
- expect(fragment.toHtml()).toBe('
');
});
-};
-describe('Fragment.toJsonMl()', () => {
- describe('basic alphabet', () => {
- runTests(setupAlphabetKit);
+ test('can export two paragraphs with inline formatting', () => {
+ const {editor, peritext} = setup();
+ editor.cursor.setAt(10);
+ editor.saved.insMarker(CommonSliceType.p);
+ editor.cursor.setAt(6, 2);
+ editor.saved.insOverwrite(CommonSliceType.b);
+ editor.cursor.setAt(7, 2);
+ editor.saved.insOverwrite(CommonSliceType.i);
+ peritext.refresh();
+ const fragment = peritext.fragment(peritext.rangeAt(4, 10));
+ fragment.refresh();
+ const html = toJsonMl(fragment.toJson());
+ expect(html).toEqual([
+ '',
+ null,
+ ['p', null,
+ 'ef',
+ ['b', null, 'g'],
+ ['i', null,
+ ['b', null, 'h'],
+ ],
+ ['i', null, 'i'],
+ 'j',
+ ],
+ ['p', null, 'klm'],
+ ]);
});
+};
- // describe('alphabet with two chunks', () => {
- // runTests(setupAlphabetWithTwoChunksKit);
- // });
-
- // describe('alphabet with chunk split', () => {
- // runTests(setupAlphabetChunkSplitKit);
- // });
-
- // describe('alphabet with deletes', () => {
- // runTests(setupAlphabetWithDeletesKit);
- // });
+describe('Fragment.toJson()', () => {
+ runAlphabetKitTestSuite(runTests);
});
diff --git a/src/json-crdt-extensions/peritext/export/toJsonMl.ts b/src/json-crdt-extensions/peritext/export/toJsonMl.ts
new file mode 100644
index 0000000000..bfc5acd664
--- /dev/null
+++ b/src/json-crdt-extensions/peritext/export/toJsonMl.ts
@@ -0,0 +1,15 @@
+import {SliceTypeName} from "../slice";
+import type {JsonMlNode} from "../../../json-ml";
+import type {PeritextMlNode} from "../block/types";
+
+export const toJsonMl = (json: PeritextMlNode): JsonMlNode => {
+ if (typeof json === 'string') return json;
+ const [tag, attr, ...children] = json;
+ const namedTag = tag === '' ? tag : SliceTypeName[tag as any];
+ const htmlTag = namedTag ?? (attr?.inline ? 'span' : 'div');
+ const htmlAttr = attr && (attr.data !== void 0) ? {'data-attr': JSON.stringify(attr.data)} : null;
+ const htmlNode: JsonMlNode = [htmlTag, htmlAttr];
+ const length = children.length;
+ for (let i = 0; i < length; i++) htmlNode.push(toJsonMl(children[i]));
+ return htmlNode;
+};
diff --git a/src/json-crdt-extensions/peritext/slice/index.ts b/src/json-crdt-extensions/peritext/slice/index.ts
index 915c95da00..6a22d47d74 100644
--- a/src/json-crdt-extensions/peritext/slice/index.ts
+++ b/src/json-crdt-extensions/peritext/slice/index.ts
@@ -1,2 +1,2 @@
export type * from './types';
-export {CursorAnchor, SliceTypeName as CommonSliceType} from './constants';
+export {CursorAnchor, SliceTypeName, SliceTypeName as CommonSliceType} from './constants';