function _array_like_to_array(arr, len) {
    if (len == null || len > arr.length) len = arr.length;
    for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
    return arr2;
}
function _array_without_holes(arr) {
    if (Array.isArray(arr)) return _array_like_to_array(arr);
}
function _define_property(obj, key, value) {
    if (key in obj) {
        Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
        });
    } else {
        obj[key] = value;
    }
    return obj;
}
function _iterable_to_array(iter) {
    if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
}
function _non_iterable_spread() {
    throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _object_spread(target) {
    for(var i = 1; i < arguments.length; i++){
        var source = arguments[i] != null ? arguments[i] : {};
        var ownKeys = Object.keys(source);
        if (typeof Object.getOwnPropertySymbols === "function") {
            ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
                return Object.getOwnPropertyDescriptor(source, sym).enumerable;
            }));
        }
        ownKeys.forEach(function(key) {
            _define_property(target, key, source[key]);
        });
    }
    return target;
}
function ownKeys(object, enumerableOnly) {
    var keys = Object.keys(object);
    if (Object.getOwnPropertySymbols) {
        var symbols = Object.getOwnPropertySymbols(object);
        if (enumerableOnly) {
            symbols = symbols.filter(function(sym) {
                return Object.getOwnPropertyDescriptor(object, sym).enumerable;
            });
        }
        keys.push.apply(keys, symbols);
    }
    return keys;
}
function _object_spread_props(target, source) {
    source = source != null ? source : {};
    if (Object.getOwnPropertyDescriptors) {
        Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
    } else {
        ownKeys(Object(source)).forEach(function(key) {
            Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
        });
    }
    return target;
}
function _to_consumable_array(arr) {
    return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
}
function _unsupported_iterable_to_array(o, minLen) {
    if (!o) return;
    if (typeof o === "string") return _array_like_to_array(o, minLen);
    var n = Object.prototype.toString.call(o).slice(8, -1);
    if (n === "Object" && o.constructor) n = o.constructor.name;
    if (n === "Map" || n === "Set") return Array.from(n);
    if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
}
import { Editor, Node, Path, Point, Range, Transforms } from "slate";
import { decodeURIComponentUrl } from "../parser/parse/parseHtml";
import { EditorUtils } from "../utils/editorUtils";
export var insertAfter = function(editor, path) {
    var node = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {
        type: 'paragraph',
        children: [
            {
                text: ''
            }
        ]
    };
    var nextPath = Path.next(path);
    Transforms.insertNodes(editor, node, {
        select: true,
        at: nextPath
    });
};
var matchText = function(insert, matchString) {
    return function(ctx) {
        var sel = ctx.sel, editor = ctx.editor, match = ctx.match, startText = ctx.startText;
        var leaf = Node.leaf(editor, sel.anchor.path);
        if (EditorUtils.isDirtLeaf(leaf)) return false;
        if (matchString) {
            var preStr = Node.string(leaf) + matchString;
            var prev = preStr[match.index - 1];
            if (prev === matchString) return false;
        }
        Transforms.select(editor, {
            anchor: {
                path: sel.anchor.path,
                offset: match.index
            },
            focus: {
                path: sel.anchor.path,
                offset: match.index + startText.length - 1
            }
        });
        insert(ctx);
        var addSel = editor.selection;
        if (addSel) EditorUtils.moveAfterSpace(editor, addSel.focus.path);
        return true;
    };
};
export var MdElements = {
    table: {
        reg: /^\s*\|((?:[^|\n]+\|?)+)\|\s*$/,
        run: function(param) {
            var editor = param.editor, path = param.path, match = param.match;
            var columns = match[1].split('|');
            Transforms.delete(editor, {
                at: path
            });
            Transforms.insertNodes(editor, EditorUtils.wrapperCardNode({
                type: 'table',
                children: [
                    {
                        type: 'table-row',
                        children: columns.map(function(c) {
                            return {
                                type: 'table-cell',
                                title: true,
                                children: [
                                    {
                                        text: c
                                    }
                                ]
                            };
                        })
                    },
                    {
                        type: 'table-row',
                        children: columns.map(function() {
                            return {
                                type: 'table-cell',
                                children: [
                                    {
                                        text: ''
                                    }
                                ]
                            };
                        })
                    }
                ]
            }), {
                at: path
            });
            Transforms.select(editor, _to_consumable_array(path).concat([
                1,
                0,
                0
            ]));
        }
    },
    code: {
        reg: /^\s*(```|···)([\w#\-+*]{1,30})?\s*$/,
        run: function(param) {
            var editor = param.editor, path = param.path, match = param.match;
            var lang = match[2];
            Transforms.delete(editor, {
                at: path
            });
            Transforms.insertNodes(editor, {
                type: 'code',
                language: lang,
                value: ''
            }, {
                at: path,
                select: true
            });
            return true;
        }
    },
    head: {
        matchKey: ' ',
        checkAllow: function(ctx) {
            var _ctx_node_, _ctx_node;
            return EditorUtils.isTop(ctx.editor, ctx.node[1]) && [
                'paragraph',
                'head'
            ].includes((_ctx_node = ctx.node) === null || _ctx_node === void 0 ? void 0 : (_ctx_node_ = _ctx_node[0]) === null || _ctx_node_ === void 0 ? void 0 : _ctx_node_.type) && !Path.hasPrevious(ctx.sel.anchor.path);
        },
        reg: /^\s*(#{1,5})(\s+)([^\n]*)$/,
        run: function(param) {
            var editor = param.editor, path = param.path, match = param.match, sel = param.sel;
            var text = [
                {
                    text: ''
                }
            ];
            if (!Point.equals(sel.anchor, Editor.end(editor, path))) {
                text = EditorUtils.cutText(editor, sel.anchor);
            }
            Transforms.delete(editor, {
                at: path
            });
            Transforms.insertNodes(editor, {
                type: 'head',
                level: match[1].length,
                children: text
            }, {
                at: path
            });
            Transforms.select(editor, Editor.start(editor, path));
            return true;
        }
    },
    link: {
        reg: RegExp("(?<!!)\\[([^]+)]\\(([^)]+)\\)\\s*"),
        matchKey: ')',
        run: function(param) {
            var editor = param.editor, match = param.match, sel = param.sel, startText = param.startText;
            Transforms.select(editor, {
                anchor: {
                    path: sel.anchor.path,
                    offset: match.index
                },
                focus: {
                    path: sel.anchor.path,
                    offset: match.index + startText.length
                }
            });
            Transforms.insertNodes(editor, [
                {
                    text: match[1],
                    url: match[2]
                },
                {
                    text: ''
                }
            ]);
            return true;
        }
    },
    img: {
        reg: /!\[([^]*)]\(([^)]+)\)\s*/,
        matchKey: ')',
        run: function(param) {
            var editor = param.editor, match = param.match, sel = param.sel, startText = param.startText;
            Transforms.select(editor, {
                anchor: {
                    path: sel.anchor.path,
                    offset: match.index
                },
                focus: {
                    path: sel.anchor.path,
                    offset: match.index + startText.length
                }
            });
            Transforms.insertNodes(editor, [
                EditorUtils.createMediaNode(decodeURIComponentUrl(match[2] || ''), 'image', {
                    alt: match[1]
                })
            ]);
            return true;
        }
    },
    task: {
        reg: /^\s*\[(x|\s)]\s+/,
        matchKey: ' ',
        checkAllow: function(ctx) {
            var _ctx_node_, _ctx_node;
            if (((_ctx_node = ctx.node) === null || _ctx_node === void 0 ? void 0 : (_ctx_node_ = _ctx_node[0]) === null || _ctx_node_ === void 0 ? void 0 : _ctx_node_.type) === 'paragraph') {
                var list = Editor.parent(ctx.editor, ctx.node[1])[0].type === 'list-item';
                return !(list && !Path.hasPrevious(ctx.node[1]));
            }
            return false;
        },
        run: function(ctx) {
            Transforms.delete(ctx.editor, {
                at: ctx.path
            });
            Transforms.insertNodes(ctx.editor, {
                type: 'bulleted-list',
                task: true,
                children: [
                    {
                        type: 'list-item',
                        checked: ctx.match[1] === 'x',
                        children: [
                            EditorUtils.p
                        ]
                    }
                ]
            }, {
                at: ctx.path
            });
            Transforms.select(ctx.editor, Editor.start(ctx.editor, ctx.path).path);
            return true;
        }
    },
    list: {
        matchKey: ' ',
        reg: /^\s*(\d+\.|-|\*|\+)\s+?/,
        checkAllow: function(ctx) {
            var _ctx_node_, _ctx_node;
            if (Editor.parent(ctx.editor, ctx.node[1])[0].type === 'list-item') {
                return Path.hasPrevious(ctx.node[1]);
            }
            return [
                'paragraph'
            ].includes((_ctx_node = ctx.node) === null || _ctx_node === void 0 ? void 0 : (_ctx_node_ = _ctx_node[0]) === null || _ctx_node_ === void 0 ? void 0 : _ctx_node_.type) && !Path.hasPrevious(ctx.sel.anchor.path);
        },
        run: function(param) {
            var editor = param.editor, match = param.match, sel = param.sel, path = param.path;
            var _match__match;
            var removeLength = ((_match__match = match[0].match(/\s*(\d+\.|-|\*|\+)\s+/)) === null || _match__match === void 0 ? void 0 : _match__match[0].length) || 0;
            var texts = [
                {
                    text: ''
                }
            ];
            if (!Point.equals(sel.anchor, Editor.end(editor, path))) {
                texts = EditorUtils.cutText(editor, sel.anchor);
            }
            Transforms.delete(editor, {
                at: path
            });
            var start = match[1].match(/^\s*(\d+)\./);
            var listType = start ? 'numbered-list' : 'bulleted-list';
            Transforms.insertNodes(editor, _object_spread_props(_object_spread({
                type: listType
            }, start && {
                start: +start[1]
            }), {
                children: [
                    {
                        type: 'list-item',
                        children: [
                            {
                                type: 'paragraph',
                                children: texts
                            }
                        ]
                    }
                ]
            }), {
                at: path
            });
            Transforms.select(editor, {
                path: Editor.start(editor, path).path,
                offset: sel.anchor.offset - removeLength
            });
            return true;
        }
    },
    hr: {
        reg: /^\s*\*\*\*|___|---\s*/,
        checkAllow: function(ctx) {
            var _ctx_node_, _ctx_node;
            return ((_ctx_node = ctx.node) === null || _ctx_node === void 0 ? void 0 : (_ctx_node_ = _ctx_node[0]) === null || _ctx_node_ === void 0 ? void 0 : _ctx_node_.type) === 'paragraph' && ctx.node[1][0] !== 0;
        },
        run: function(param) {
            var editor = param.editor, path = param.path;
            Transforms.delete(editor, {
                at: path
            });
            Transforms.insertNodes(editor, {
                type: 'hr',
                children: [
                    {
                        text: ''
                    }
                ]
            }, {
                at: path
            });
            insertAfter(editor, path);
        }
    },
    frontmatter: {
        reg: /^\s*---\s*/,
        checkAllow: function(ctx) {
            var _ctx_node_, _ctx_node;
            return !Path.hasPrevious(ctx.node[1]) && ((_ctx_node = ctx.node) === null || _ctx_node === void 0 ? void 0 : (_ctx_node_ = _ctx_node[0]) === null || _ctx_node_ === void 0 ? void 0 : _ctx_node_.type) === 'paragraph' && EditorUtils.isTop(ctx.editor, ctx.node[1]);
        },
        run: function(param) {
            var editor = param.editor, path = param.path;
            Transforms.delete(editor, {
                at: path
            });
            Transforms.insertNodes(editor, {
                type: 'code',
                language: 'yaml',
                frontmatter: true,
                children: [
                    {
                        text: ''
                    }
                ]
            }, {
                select: true,
                at: path
            });
        }
    },
    blockquote: {
        matchKey: ' ',
        reg: /^\s*>\s+([^\n]+)?/,
        checkAllow: function(ctx) {
            var _ctx_node_, _ctx_node;
            return ((_ctx_node = ctx.node) === null || _ctx_node === void 0 ? void 0 : (_ctx_node_ = _ctx_node[0]) === null || _ctx_node_ === void 0 ? void 0 : _ctx_node_.type) === 'paragraph';
        },
        run: function(param) {
            var sel = param.sel, editor = param.editor, path = param.path;
            if (sel && Range.isCollapsed(sel)) {
                var text = EditorUtils.cutText(editor, {
                    path: sel.anchor.path,
                    offset: 1
                });
                Transforms.delete(editor, {
                    at: path
                });
                Transforms.insertNodes(editor, {
                    type: 'blockquote',
                    children: [
                        {
                            type: 'paragraph',
                            children: text
                        }
                    ]
                }, {
                    at: path
                });
                Transforms.select(editor, Editor.start(editor, path));
            }
            return true;
        }
    },
    bold: {
        reg: /[*]{2}([^*][^\n]*)[*]{2}/,
        matchKey: '*',
        run: matchText(function(param) {
            var editor = param.editor, match = param.match;
            Transforms.insertNodes(editor, [
                {
                    text: match[1],
                    bold: true
                }
            ], {
                select: true
            });
        }, '*')
    },
    italic: {
        reg: /[*]([^\n*]+)[*]/,
        matchKey: '*',
        run: matchText(function(param) {
            var editor = param.editor, match = param.match;
            Transforms.insertNodes(editor, [
                {
                    text: match[1],
                    italic: true
                }
            ], {
                select: true
            });
        }, '*')
    },
    inlineCode: {
        reg: /`([^\n`]+)`/,
        matchKey: '`',
        run: matchText(function(param) {
            var editor = param.editor, match = param.match;
            Transforms.insertNodes(editor, [
                {
                    text: match[1],
                    code: true
                }
            ]);
        })
    },
    boldAndItalic: {
        reg: /[*]{3}([^\n]+)[*]{3}/,
        matchKey: '*',
        run: matchText(function(param) {
            var editor = param.editor, match = param.match;
            Transforms.insertNodes(editor, [
                {
                    text: match[1],
                    italic: true,
                    bold: true
                }
            ], {
                select: true
            });
        })
    },
    strikethrough: {
        reg: /~~([^\n]+)~~/,
        matchKey: '~',
        run: matchText(function(param) {
            var editor = param.editor, match = param.match;
            Transforms.insertNodes(editor, [
                {
                    text: match[1],
                    strikethrough: true
                }
            ], {
                select: true
            });
        })
    }
};
export var BlockMathNodes = Object.entries(MdElements).filter(function(c) {
    return !c[1].matchKey;
}).map(function(c) {
    return Object.assign(c[1], {
        type: c[0]
    });
});
export var TextMatchNodes = Object.entries(MdElements).filter(function(c) {
    return !!c[1].matchKey;
}).map(function(c) {
    return Object.assign(c[1], {
        type: c[0]
    });
});
