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

63.15% Statements 12/19
40% Branches 2/5
50% Functions 2/4
66.66% Lines 12/18

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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 13562x 62x                 62x   62x               249x                                                             2250x                         2250x         2250x         2250x                                 2250x               2250x                                   2250x                                  
import {SliceStacking} from '../slice/constants';
import {formatType} from '../slice/util';
import type {PeritextMlElement} from '../block/types';
import type {NodeBuilder} from '../../../json-crdt-patch';
import type {FromHtmlConverter, ToHtmlConverter} from './types';
import type {JsonNodeView} from '../../../json-crdt/nodes';
import type {SchemaToJsonNode} from '../../../json-crdt/schema/types';
import type {Printable} from 'tree-dump';
import type {TypeTag} from '../slice';
 
const sliceCustomData = new WeakMap<SliceBehavior<any, any, any>, Record<string, unknown>>();
 
export class SliceBehavior<
  Stacking extends SliceStacking = SliceStacking,
  Tag extends TypeTag = TypeTag,
  Schema extends NodeBuilder = NodeBuilder,
  Data extends Record<string, unknown> = Record<string, unknown>,
> implements Printable
{
  public isInline(): boolean {
    return this.stacking !== SliceStacking.Marker;
  }
 
  /**
   * An opaque object which can be mutated in-place by the rendering layer
   * to store custom rendering-specific data. This is useful for storing, for
   * example, React component references, which is specific to the rendering
   * layer.
   *
   * Usage:
   *
   * ```ts
   * registry.get(SliceTypeCon.a)?.data().ReactConfig = ReactConfigCompForLink;
   * ```
   *
   * @returns The custom data of the slice.
   */
  public data(): Data {
    const data = sliceCustomData.get(this) as Data | undefined;
    Iif (data) return data;
    const newData = {} as Data;
    sliceCustomData.set(this, newData);
    return newData;
  }
 
  constructor(
    /**
     * Specifies whether the slice is an inline or block element. And if it is
     * an inline element, whether multiple instances of the same tag are allowed
     * to be applied to a range of tex - "Many", or only one instance - "One".
     */
    public readonly stacking: Stacking,
 
    /**
     * The tag name of this slice. The tag is one step in the type path of the
     * slice. For example, below is a type path composed of three steps:
     *
     * ```js
     * ['ul', 'li', 'p']
     * ```
     *
     * Tag types are normally numbers of type {@link SliceTypeCon}, however,
     * they can also be any arbitrary strings or numbers.
     */
    public readonly tag: Tag,
 
    /**
     * User friendly display name. Also used for translation purposes.
     */
    public readonly name: string,
 
    /**
     * Default expected schema of the slice data.
     */
    public readonly schema: Schema | undefined = void 0,
 
    /**
     * This property is relevant only for block split markers. It specifies
     * whether the block split marker is a container for other block elements.
     *
     * For example, a `blockquote` is a container for `paragraph` elements,
     * however, a `paragraph` is not a container (it can only contain inline
     * elements).
     *
     * If the marker slice is of the container sort, they tag can appear in the
     * path steps of the type:
     *
     * ```
     *
     * ```
     */
    public readonly container: boolean = false,
 
    /**
     * Converts a node of this type to HTML representation: returns the HTML tag
     * and attributes. The method receives {@link PeritextMlElement} as an
     * argument, which is a tuple of internal HTML-like representation of the
     * node.
     */
    public readonly toHtml:
      | ToHtmlConverter<
          PeritextMlElement<
            Tag,
            JsonNodeView<SchemaToJsonNode<Schema>>,
            Stacking extends SliceStacking.Marker ? false : true
          >
        >
      | undefined = void 0,
 
    /**
     * Specifies a mapping of converters from HTML {@link JsonMlElement} to
     * {@link PeritextMlElement}. This way a slice type can specify multiple
     * HTML tags that are converted to the same slice type.
     *
     * For example, both, `<b>` and `<strong>` tags can be converted to the
     * {@link SliceTypeCon.b} slice type.
     */
    public readonly fromHtml?: {
      [htmlTag: string]: FromHtmlConverter<
        PeritextMlElement<
          Tag,
          JsonNodeView<SchemaToJsonNode<Schema>>,
          Stacking extends SliceStacking.Marker ? false : true
        >
      >;
    },
  ) {}
 
  /** ----------------------------------------------------- {@link Printable} */
 
  public toString(tab: string = ''): string {
    return `${formatType(this.tag)} (${this.stacking}) ${JSON.stringify(Object.keys(this.data))}`;
  }
}