json-joy
Version:
Collection of libraries for building collaborative editing apps.
167 lines (166 loc) • 5.26 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PeritextDataTransfer = void 0;
/**
* This class provides methods for transferring data between Peritext and other
* formats, such as JSON, HTML, Markdown, etc. A Peritext {@link Fragment} can
* be converted to a JSON object, which can be converted to HTML, Markdown, etc.
* The reverse is also possible.
*/
class PeritextDataTransfer {
constructor(txt, opts) {
this.txt = txt;
this.opts = opts;
}
// ------------------------------------------------------------------ exports
toView(range) {
return this.txt.editor.export(range);
}
toFragment(range) {
const fragment = this.txt.fragment(range);
fragment.refresh();
return fragment;
}
toJson(range) {
const fragment = this.toFragment(range);
return fragment.toJson();
}
htmlE() {
const tools = this.opts.htmlExport;
if (!tools)
throw new Error('NO_HTML_EXPORT_TOOLS');
return tools;
}
toJsonMl(range) {
const tools = this.htmlE();
const json = this.toJson(range);
return tools.toJsonMl(json);
}
toHast(range) {
const tools = this.htmlE();
const json = this.toJson(range);
return tools.toHast(json);
}
toHtml(range, tab, indent) {
const tools = this.htmlE();
const json = this.toJson(range);
return tools.toHtml(json, tab, indent);
}
mdE() {
const tools = this.opts.mdExport;
if (!tools)
throw new Error('NO_MD_EXPORT_TOOLS');
return tools;
}
toMdast(range) {
const tools = this.mdE();
const json = this.toJson(range);
return tools.toMdast(json);
}
toMarkdown(range) {
const tools = this.mdE();
const json = this.toJson(range);
return tools.toMarkdown(json);
}
toClipboard(range) {
const view = this.txt.editor.export(range);
const node = this.toJson(range);
const html = this.htmlE().exportHtml(view, node);
return {
'text/plain': range.text(),
'text/html': html,
};
}
toFormat(range) {
const json = this.txt.editor.exportStyle(range);
const html = this.htmlE().exportStyle(json);
return { 'text/html': html };
}
// ------------------------------------------------------------------ imports
fromView(pos, view) {
return this.txt.editor.import(pos, view);
}
fromJson(pos, json) {
const tools = this.htmlI();
const view = tools.toViewRange(json);
return this.fromView(pos, view);
}
_imp(pos, data, transform) {
const registry = this.txt.editor.getRegistry();
const json = transform(data, registry);
return this.fromJson(pos, json);
}
htmlI() {
const tools = this.opts.htmlImport;
if (!tools)
throw new Error('NO_HTML_IMPORT_TOOLS');
return tools;
}
fromJsonMl(pos, jsonml) {
return this._imp(pos, jsonml, this.htmlI().fromJsonMl);
}
fromHast(pos, hast) {
return this._imp(pos, hast, this.htmlI().fromHast);
}
fromHtml(pos, html) {
return this._imp(pos, html, this.htmlI().fromHtml);
}
mdI() {
const tools = this.opts.mdImport;
if (!tools)
throw new Error('NO_MD_IMPORT_TOOLS');
return tools;
}
fromMdast(pos, mdast) {
return this._imp(pos, mdast, this.mdI().fromMdast);
}
fromMarkdown(pos, markdown) {
return this._imp(pos, markdown, this.mdI().fromMarkdown);
}
textFromHtml(html) {
return this.htmlI().textFromHtml(html);
}
/**
* Inserts data from the clipboard at a given position. Returns the number
* of characters inserted, this can be used by the caller to move the cursor
* to the end of the inserted data.
*
* @param pos View position to insert the data at.
* @param data Clipboard data to attempt to insert.
* @returns The number of characters inserted.
*/
fromClipboard(range, data) {
const txt = this.txt;
const html = data.html;
const collapseRange = () => {
if (!range.isCollapsed())
txt.editor.delRange(range);
range.collapseToStart();
return range.start.viewPos();
};
if (html) {
const [view, style] = this.htmlI().importHtml(html, txt.editor.getRegistry());
if (style) {
txt.editor.importStyle(range, style);
return 0;
}
else if (view) {
const pos = collapseRange();
return this.fromView(pos, view);
}
}
const text = data.text;
if (!text)
return 0;
const pos = collapseRange();
this.txt.insAt(pos, text);
return text.length;
}
fromStyle(range, html) {
const style = this.htmlI().importStyle(html);
if (!style)
return;
this.txt.editor.importStyle(range, style);
}
}
exports.PeritextDataTransfer = PeritextDataTransfer;