"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) {
        if (!range)
            range = this.txt.rangeAll();
        if (!range)
            return '';
        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 view = this.htmlI().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;
//# sourceMappingURL=PeritextDataTransfer.js.map