Skip to content

Commit acfe769

Browse files
committed
feat(json-crdt-extensions): 🎸 improve slice registry typing
1 parent 7248c8c commit acfe769

File tree

4 files changed

+38
-26
lines changed

4 files changed

+38
-26
lines changed

src/json-crdt-extensions/peritext/registry/SliceRegistry.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import {PeritextMlElement} from '../block/types';
22
import {NodeBuilder} from '../../../json-crdt-patch';
3-
import type {JsonMlNode} from 'very-small-parser/lib/html/json-ml/types';
3+
import type {JsonMlElement} from 'very-small-parser/lib/html/json-ml/types';
44
import type {FromHtmlConverter, SliceTypeDefinition, ToHtmlConverter} from './types';
55

66
export class SliceRegistry {
7-
private map: Map<string | number, SliceTypeDefinition> = new Map();
8-
private toHtmlMap: Map<string | number, ToHtmlConverter> = new Map();
7+
private map: Map<string | number, SliceTypeDefinition<any, any, any>> = new Map();
8+
private toHtmlMap: Map<string | number, ToHtmlConverter<any>> = new Map();
99
private fromHtmlMap: Map<string, FromHtmlConverter[]> = new Map();
1010

11-
public add<Type extends number | string, Schema extends NodeBuilder>(def: SliceTypeDefinition<Type, Schema>): void {
11+
public add<Type extends number | string, Schema extends NodeBuilder, Inline extends boolean = true>(def: SliceTypeDefinition<Type, Schema, Inline>): void {
1212
const {type, toHtml, fromHtml} = def;
1313
this.map.set(type, def);
1414
if (toHtml) this.toHtmlMap.set(type, toHtml);
@@ -21,17 +21,19 @@ export class SliceRegistry {
2121
}
2222
}
2323

24-
public toHtml(el: PeritextMlElement): JsonMlNode | undefined {
24+
public toHtml(el: PeritextMlElement): ReturnType<ToHtmlConverter<any>> | undefined {
2525
const converter = this.toHtmlMap.get(el[0]);
2626
return converter ? converter(el) : undefined;
2727
}
2828

29-
public fromHtml(el: JsonMlNode): PeritextMlElement | undefined {
29+
public fromHtml(el: JsonMlElement): ReturnType<FromHtmlConverter<any, any>> | undefined {
3030
const tag = el[0] + '';
3131
const converters = this.fromHtmlMap.get(tag);
32-
for (const converter of converters ?? []) {
33-
const result = converter(el);
34-
if (result) return result;
32+
if (converters) {
33+
for (const converter of converters) {
34+
const result = converter(el);
35+
if (result) return result;
36+
}
3537
}
3638
return;
3739
}
Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {s} from "../../../json-crdt-patch";
22
import {JsonNodeView} from "../../../json-crdt/nodes";
3-
import {PeritextMlElement} from "../block/types";
3+
import {SchemaToJsonNode} from "../../../json-crdt/schema/types";
44
import {CommonSliceType} from "../slice";
55
import {SliceRegistry} from "./SliceRegistry";
66

@@ -9,13 +9,23 @@ import {SliceRegistry} from "./SliceRegistry";
99
*/
1010
export const registry = new SliceRegistry();
1111

12+
const aSchema = s.obj({
13+
href: s.str<string>(''),
14+
title: s.str<string>(''),
15+
});
16+
1217
registry.add({
1318
type: CommonSliceType.a,
14-
schema: s.obj({
15-
href: s.str(''),
16-
title: s.str(''),
17-
}),
18-
toHtml: (el) => {
19-
throw new Error('Not implemented');
19+
schema: aSchema,
20+
// toHtml: (el) => ['a', {...el[1]?.data}],
21+
fromHtml: {
22+
a: (jsonml) => {
23+
const attr = jsonml[1] || {};
24+
const data: JsonNodeView<SchemaToJsonNode<typeof aSchema>> = {
25+
href: attr.href ?? '',
26+
title: attr.title ?? '',
27+
};
28+
return [CommonSliceType.a, data];
29+
}
2030
},
2131
});
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
import type {NodeBuilder} from '../../../json-crdt-patch';
22
import type {JsonNodeView} from '../../../json-crdt/nodes';
3-
import {SchemaToJsonNode} from '../../../json-crdt/schema/types';
3+
import type {SchemaToJsonNode} from '../../../json-crdt/schema/types';
44
import type {PeritextMlElement} from '../block/types';
5-
import type {JsonMlNode} from 'very-small-parser/lib/html/json-ml/types';
5+
import type {JsonMlElement} from 'very-small-parser/lib/html/json-ml/types';
66

7-
export interface SliceTypeDefinition<Type extends number | string, Schema extends NodeBuilder> {
7+
export interface SliceTypeDefinition<Type extends number | string = number | string, Schema extends NodeBuilder = NodeBuilder, Inline extends boolean = true> {
88
type: Type;
99
schema: Schema;
10-
toHtml?: ToHtmlConverter<PeritextMlElement<Type, JsonNodeView<SchemaToJsonNode<Schema>>, true>>;
10+
toHtml?: ToHtmlConverter<PeritextMlElement<Type, JsonNodeView<SchemaToJsonNode<Schema>>, Inline>>;
1111
fromHtml?: {
12-
[htmlTag: string]: FromHtmlConverter<PeritextMlElement<Type, JsonNodeView<SchemaToJsonNode<Schema>>, true>>;
12+
[htmlTag: string]: FromHtmlConverter<Type, JsonNodeView<SchemaToJsonNode<Schema>>>;
1313
};
1414
}
1515

16-
export type ToHtmlConverter<El extends PeritextMlElement<any, any, any>> =
17-
(element: El) => JsonMlNode;
16+
export type ToHtmlConverter<El extends PeritextMlElement<any, any, any> = PeritextMlElement<string | number, unknown, boolean>> =
17+
(element: El) => [tag: string, attr: Record<string, string> | null];
1818

19-
export type FromHtmlConverter<El extends PeritextMlElement<any, any, any>> =
20-
(jsonml: JsonMlNode) => El | undefined;
19+
export type FromHtmlConverter<Type extends number | string = string | number, Data = unknown> =
20+
(jsonml: JsonMlElement) => [type: Type, data: Data];

src/json-crdt-patch/builder/schema.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ export namespace nodes {
152152
* s.obj({
153153
* href: s.str('https://example.com'),
154154
* })
155-
* .optional<nodes.obj({
155+
* .optional<nodes.obj({
156156
* title: nodes.str,
157157
* })>()
158158
* ```

0 commit comments

Comments
 (0)