Skip to content

Commit

Permalink
feat(json-crdt-extensions): 🎸 improve to JSON-ML export
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Dec 1, 2024
1 parent 8b47358 commit b3e7e5c
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 27 deletions.
4 changes: 3 additions & 1 deletion src/json-crdt-extensions/peritext/block/Fragment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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) => {
Expand All @@ -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('<div><p>efghij</p><p>klm</p></div>');
});
};

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);
});
15 changes: 15 additions & 0 deletions src/json-crdt-extensions/peritext/export/toJsonMl.ts
Original file line number Diff line number Diff line change
@@ -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;
};
2 changes: 1 addition & 1 deletion src/json-crdt-extensions/peritext/slice/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export type * from './types';
export {CursorAnchor, SliceTypeName as CommonSliceType} from './constants';
export {CursorAnchor, SliceTypeName, SliceTypeName as CommonSliceType} from './constants';

0 comments on commit b3e7e5c

Please sign in to comment.