json-joy
Version:
Collection of libraries for building collaborative editing apps.
131 lines (130 loc) • 4.56 kB
JavaScript
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;
;