All files / json-crdt-extensions/peritext/registry SliceRegistry.ts

90% Statements 27/30
64.7% Branches 11/17
80% Functions 4/5
93.1% Lines 27/29

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62    2x       2x 2x 2x 2x           26x 26x 26x 26x 8x 8x 14x 14x 14x 14x                       26x                 22x 22x 22x 3x 3x 3x 3x 3x 3x 3x       19x      
import type {PeritextMlElement} from '../block/types';
import type {NodeBuilder} from '../../../json-crdt-patch';
import {SliceBehavior} from '../slice/constants';
import type {JsonMlElement} from 'very-small-parser/lib/html/json-ml/types';
import type {FromHtmlConverter, SliceTypeDefinition, ToHtmlConverter} from './types';
 
export class SliceRegistry {
  private map: Map<string | number, SliceTypeDefinition<any, any, any>> = new Map();
  private toHtmlMap: Map<string | number, ToHtmlConverter<any>> = new Map();
  private fromHtmlMap: Map<string, [def: SliceTypeDefinition<any, any, any>, converter: FromHtmlConverter][]> =
    new Map();
 
  public add<Type extends number | string, Schema extends NodeBuilder, Inline extends boolean = true>(
    def: SliceTypeDefinition<Type, Schema, Inline>,
  ): void {
    const {type, toHtml, fromHtml} = def;
    this.map.set(type, def);
    Iif (toHtml) this.toHtmlMap.set(type, toHtml);
    if (fromHtml) {
      const fromHtmlMap = this.fromHtmlMap;
      for (const htmlTag in fromHtml) {
        const converter = fromHtml[htmlTag];
        const converters = fromHtmlMap.get(htmlTag) ?? [];
        converters.push([def, converter]);
        fromHtmlMap.set(htmlTag, converters);
      }
    }
  }
 
  public def<Type extends number | string, Schema extends NodeBuilder, Inline extends boolean = true>(
    type: Type,
    schema: Schema,
    behavior: SliceBehavior,
    inline: boolean,
    rest: Omit<SliceTypeDefinition<Type, Schema, Inline>, 'type' | 'schema' | 'behavior' | 'inline'> = {},
  ): void {
    this.add({type, schema, behavior, inline, ...rest});
  }
 
  public toHtml(el: PeritextMlElement): ReturnType<ToHtmlConverter<any>> | undefined {
    const converter = this.toHtmlMap.get(el[0]);
    return converter ? converter(el) : undefined;
  }
 
  public fromHtml(el: JsonMlElement): PeritextMlElement | undefined {
    const tag = el[0] + '';
    const converters = this.fromHtmlMap.get(tag);
    if (converters) {
      for (const [def, converter] of converters) {
        const result = converter(el);
        if (result) {
          const attr = result[1] ?? (result[1] = {});
          attr.inline = def.inline ?? def.type < 0;
          attr.behavior = !attr.inline ? SliceBehavior.Marker : (def.behavior ?? SliceBehavior.Many);
          return result;
        }
      }
    }
    return;
  }
}