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 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | 62x 62x 62x 120x 102960x 102960x 102960x 102960x 102960x 102960x 62x 3432x 3432x 102960x 102960x 102960x 102960x 13728x 24024x 24024x 24024x 24024x 102960x 102960x 192x 192x 131x 131x 131x 91x 91x 91x 91x 29x 29x 29x 91x 40x | import {SliceBehavior, type SliceTypeCon} from '../slice/constants'; import {CommonSliceType} from '../slice'; import type {PeritextMlElement} from '../block/types'; import type {NodeBuilder} from '../../../json-crdt-patch'; import type {JsonMlElement} from 'very-small-parser/lib/html/json-ml/types'; import type {FromHtmlConverter, ToHtmlConverter} from './types'; import type {JsonNodeView} from '../../../json-crdt/nodes'; import type {SchemaToJsonNode} from '../../../json-crdt/schema/types'; export type TagType = SliceTypeCon | number | string; export class SliceRegistryEntry< Behavior extends SliceBehavior = SliceBehavior, Tag extends TagType = TagType, Schema extends NodeBuilder = NodeBuilder, > { public isInline(): boolean { return this.behavior !== SliceBehavior.Marker; } 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 behavior: Behavior, /** * 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, /** * Default expected schema of the slice data. */ public readonly schema: Schema, /** * 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>>, Behavior extends SliceBehavior.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>>, Behavior extends SliceBehavior.Marker ? false : true > >; }, ) {} } /** * Slice registry contains a record of possible inline an block formatting * annotations. Each entry in the registry is a {@link SliceRegistryEntry} that * specifies the behavior, tag, and other properties of the slice. * * @todo Consider moving the registry under the `/transfer` directory. Or maybe * `/slices` directory. */ export class SliceRegistry { private map: Map<TagType, SliceRegistryEntry> = new Map(); private _fromHtml: Map<string, [entry: SliceRegistryEntry, converter: FromHtmlConverter][]> = new Map(); public add(entry: SliceRegistryEntry<any, any, any>): void { const {tag, fromHtml} = entry; this.map.set(tag, entry); const _fromHtml = this._fromHtml; if (fromHtml) { for (const htmlTag in fromHtml) { const converter = fromHtml[htmlTag]; const converters = _fromHtml.get(htmlTag) ?? []; converters.push([entry, converter]); _fromHtml.set(htmlTag, converters); } } const tagStr = CommonSliceType[tag as SliceTypeCon]; if (tagStr && typeof tagStr === 'string') _fromHtml.set(tagStr, [[entry, () => [tag, null]]]); } public isContainer(tag: TagType): boolean { const entry = this.map.get(tag); return entry?.container ?? false; } public toHtml(el: PeritextMlElement): ReturnType<ToHtmlConverter<any>> | undefined { const entry = this.map.get(el[0]); return entry?.toHtml ? entry?.toHtml(el) : void 0; } public fromHtml(el: JsonMlElement): PeritextMlElement | undefined { const tag = el[0] + ''; const converters = this._fromHtml.get(tag); if (converters) { for (const [entry, converter] of converters) { const result = converter(el); if (result) { if (entry.isInline()) { const attr = result[1] ?? (result[1] = {}); attr.inline = entry.isInline(); attr.behavior = !attr.inline ? SliceBehavior.Marker : (entry.behavior ?? SliceBehavior.Many); } return result; } } } return; } } |