UNPKG

json-joy

Version:

Collection of libraries for building collaborative editing apps.

131 lines (130 loc) 4.56 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SliceRegistry = exports.SliceRegistryEntry = void 0; const constants_1 = require("../slice/constants"); const slice_1 = require("../slice"); class SliceRegistryEntry { isInline() { return this.behavior !== constants_1.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". */ 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. */ tag, /** * Default expected schema of the slice data. */ 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: * * ``` * * ``` */ container = 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. */ toHtml = 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. */ fromHtml) { this.behavior = behavior; this.tag = tag; this.schema = schema; this.container = container; this.toHtml = toHtml; this.fromHtml = fromHtml; } } exports.SliceRegistryEntry = SliceRegistryEntry; /** * 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. */ class SliceRegistry { constructor() { this.map = new Map(); this._fromHtml = new Map(); } add(entry) { 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 = slice_1.CommonSliceType[tag]; if (tagStr && typeof tagStr === 'string') _fromHtml.set(tagStr, [[entry, () => [tag, null]]]); } isContainer(tag) { const entry = this.map.get(tag); return entry?.container ?? false; } toHtml(el) { const entry = this.map.get(el[0]); return entry?.toHtml ? entry?.toHtml(el) : void 0; } fromHtml(el) { 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 ? constants_1.SliceBehavior.Marker : (entry.behavior ?? constants_1.SliceBehavior.Many); } return result; } } } return; } } exports.SliceRegistry = SliceRegistry;