UNPKG

json-joy

Version:

Collection of libraries for building collaborative editing apps.

185 lines (184 loc) 7.17 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SliceRegistry = void 0; const json_crdt_patch_1 = require("../../../json-crdt-patch"); const constants_1 = require("../slice/constants"); const slice_1 = require("../slice"); const SliceBehavior_1 = require("./SliceBehavior"); const printTree_1 = require("tree-dump/lib/printTree"); /** * Slice registry contains a record of possible inline an block formatting * annotations. Each entry in the registry is a {@link SliceBehavior} 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(); } clear() { this.map.clear(); this._fromHtml.clear(); } 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 || !(tagStr in fromHtml))) _fromHtml.set(tagStr, [[entry, () => [tag, null]]]); } get(tag) { return this.map.get(tag); } 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.stacking = !attr.inline ? constants_1.SliceStacking.Marker : (entry.stacking ?? constants_1.SliceStacking.Many); } return result; } } } return; } /** ----------------------------------------------------- {@link Printable} */ toString(tab = '') { return ('SliceRegistry' + (0, printTree_1.printTree)(tab, [...this.map.values()].map((entry) => (tab) => entry.toString(tab)))); } } exports.SliceRegistry = SliceRegistry; /** * Creates a new slice registry with common tag registered. */ SliceRegistry.withCommon = () => { const undefSchema = json_crdt_patch_1.s.con(undefined); const registry = new SliceRegistry(); //------------------------------ Inline elements with "One" stacking behavior const i0 = (tag, name, fromHtml) => { registry.add(new SliceBehavior_1.SliceBehavior(constants_1.SliceStacking.One, tag, name, void 0, false, void 0, fromHtml)); }; const i1 = (tag, name, htmlTags) => { const fromHtml = {}; for (const htmlTag of htmlTags) fromHtml[htmlTag] = () => [tag, null]; i0(tag, name, fromHtml); }; i1(-4 /* TAG.i */, 'Italic', ['i', 'em']); i1(-3 /* TAG.b */, 'Bold', ['b', 'strong']); i1(-6 /* TAG.s */, 'Strikethrough', ['s', 'strike']); i0(-5 /* TAG.u */, 'Underline'); i0(-7 /* TAG.code */, 'Code'); i0(-8 /* TAG.mark */, 'Highlight'); i0(-19 /* TAG.kbd */, 'Keyboard'); i0(-11 /* TAG.del */, 'Delete'); i0(-12 /* TAG.ins */, 'Insert'); i0(-13 /* TAG.sup */, 'Superscript'); i0(-14 /* TAG.sub */, 'Subscript'); i0(-15 /* TAG.math */, 'Math'); // --------------------------- Inline elements with "Many" stacking behavior const aSchema = json_crdt_patch_1.s.obj({}, { href: json_crdt_patch_1.s.str(''), title: json_crdt_patch_1.s.str(''), }); registry.add(new SliceBehavior_1.SliceBehavior(constants_1.SliceStacking.Many, -9 /* TAG.a */, 'Link', aSchema, false, void 0, { a: (jsonml) => { const attr = jsonml[1] || {}; const data = { href: attr.href ?? '', title: attr.title ?? '', }; return [-9 /* TAG.a */, { data, inline: true }]; }, })); const colSchema = json_crdt_patch_1.s.obj({}, { color: json_crdt_patch_1.s.str(''), }); registry.add(new SliceBehavior_1.SliceBehavior(constants_1.SliceStacking.Many, -17 /* TAG.col */, 'Color', colSchema, false, void 0, { col: (jsonml) => { const attr = jsonml[1] || {}; const data = { color: attr.color ?? '', }; return [-17 /* TAG.col */, { data, inline: true }]; }, })); // TODO: add more default annotations with "Many" stacking behavior // comment = SliceTypeCon.comment, // font = SliceTypeCon.font, // col = SliceTypeCon.col, // bg = SliceTypeCon.bg, // hidden = SliceTypeCon.hidden, // footnote = SliceTypeCon.footnote, // ref = SliceTypeCon.ref, // iaside = SliceTypeCon.iaside, // iembed = SliceTypeCon.iembed, // bookmark = SliceTypeCon.bookmark, // -------------------------- Block elements with "Marker" stacking behavior const commonBlockSchema = json_crdt_patch_1.s.obj({}, { indent: json_crdt_patch_1.s.con(0), align: json_crdt_patch_1.s.str('left'), }); const b0 = (tag, name, container) => { registry.add(new SliceBehavior_1.SliceBehavior(constants_1.SliceStacking.Marker, tag, name, commonBlockSchema, container)); }; b0(0 /* TAG.p */, 'Paragraph', false); b0(1 /* TAG.blockquote */, 'Blockquote', true); b0(2 /* TAG.codeblock */, 'Code block', false); b0(3 /* TAG.pre */, 'Pre-formatted', false); b0(4 /* TAG.ul */, 'Unordered list', true); b0(5 /* TAG.ol */, 'Ordered list', true); b0(6 /* TAG.tl */, 'Task list', true); b0(7 /* TAG.li */, 'List item', true); b0(8 /* TAG.h1 */, 'Heading 1', false); b0(9 /* TAG.h2 */, 'Heading 2', false); b0(10 /* TAG.h3 */, 'Heading 3', false); b0(11 /* TAG.h4 */, 'Heading 4', false); b0(12 /* TAG.h5 */, 'Heading 5', false); b0(13 /* TAG.h6 */, 'Heading 6', false); b0(14 /* TAG.title */, 'Title', false); b0(15 /* TAG.subtitle */, 'Subtitle', false); // b0(TAG.br, false); // b0(TAG.nl, false); // b0(TAG.hr, false); // b0(TAG.page, false); // b0(TAG.aside, true); // b0(TAG.embed, false); // b0(TAG.column, true); // b0(TAG.contents, true); // b0(TAG.table, true); // b0(TAG.row, true); // b0(TAG.cell, true); // b0(TAG.collapselist, true); // b0(TAG.collapse, true); // b0(TAG.note, true); // b0(TAG.mathblock, false); return registry; };