"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MarkdownReactParser = void 0;
const tslib_1 = require("tslib");
const marked_1 = require("marked");
const react_1 = tslib_1.__importDefault(require("react"));
/**
 * 这里通过重新实现 marked.Renderer 的所有方法，实现一个能直接渲染 React 的 Markdown 渲染器
 */
class MarkdownReactParser extends marked_1.marked.Renderer {
    constructor(options) {
        super();
        this.unescapeInfo = new Map([
            ['&quot;', '"'],
            ['&nbsp;', ' '],
            ['&amp;', '&'],
            ['&#39;', "'"],
            ['&lt;', '<'],
            ['&gt;', '>'],
        ]);
        this.renderer = options.renderer;
    }
    parse(tokens) {
        return tokens.map((token, index) => {
            const element = (() => {
                switch (token.type) {
                    case 'html': {
                        return this.renderer.html(token.text);
                    }
                    case 'space': {
                        return null;
                    }
                    case 'heading': {
                        const level = token.depth;
                        return this.renderer.heading(this.parseInline(token.tokens), level);
                    }
                    case 'paragraph': {
                        return this.renderer.paragraph(this.parseInline(token.tokens));
                    }
                    case 'text': {
                        const textToken = token;
                        return textToken.tokens ? this.parseInline(textToken.tokens) : token.text;
                    }
                    case 'blockquote': {
                        const blockquoteToken = token;
                        const quote = this.parse(blockquoteToken.tokens);
                        return this.renderer.blockquote(quote);
                    }
                    case 'list': {
                        const listToken = token;
                        const children = listToken.items.map((item, itemIndex) => {
                            var _a;
                            const listItemChildren = [];
                            if (item.task) {
                                listItemChildren.push(this.renderer.checkbox((_a = item.checked) !== null && _a !== void 0 ? _a : false));
                            }
                            listItemChildren.push(this.parse(item.tokens));
                            return react_1.default.cloneElement(this.renderer.listItem(listItemChildren), {
                                key: `list-item-${itemIndex}`,
                            });
                        });
                        return this.renderer.list(children, token.ordered);
                    }
                    case 'code': {
                        return this.renderer.code(token.text, token.lang);
                    }
                    case 'table': {
                        const tableToken = token;
                        const headerCells = tableToken.header.map((cell, cellIndex) => react_1.default.cloneElement(this.renderer.tableCell(this.parseInline(cell.tokens), {
                            header: true,
                            align: token.align[cellIndex],
                        }), { key: `header-cell-${cellIndex}` }));
                        const headerRow = react_1.default.cloneElement(this.renderer.tableRow(headerCells), {
                            key: 'header-row',
                        });
                        const header = this.renderer.tableHeader(headerRow);
                        const bodyChilren = tableToken.rows.map((row, rowIndex) => {
                            const rowChildren = row.map((cell, cellIndex) => react_1.default.cloneElement(this.renderer.tableCell(this.parseInline(cell.tokens), {
                                header: false,
                                align: token.align[cellIndex],
                            }), { key: `body-cell-${rowIndex}-${cellIndex}` }));
                            return react_1.default.cloneElement(this.renderer.tableRow(rowChildren), {
                                key: `body-row-${rowIndex}`,
                            });
                        });
                        const body = this.renderer.tableBody(bodyChilren);
                        return this.renderer.table([header, body]);
                    }
                    case 'hr': {
                        return this.renderer.hr();
                    }
                    default: {
                        // eslint-disable-next-line no-console
                        console.warn(`Token with "${token.type}" type was not found`);
                        return null;
                    }
                }
            })();
            if (react_1.default.isValidElement(element)) {
                return react_1.default.cloneElement(element, { key: `token-${index}` });
            }
            return element;
        });
    }
    parseInline(tokens = []) {
        return tokens.map((token) => {
            switch (token.type) {
                case 'text': {
                    const text = token.text.replace(/&(#\d+|[a-zA-Z]+);/g, (m) => { var _a; return (_a = this.unescapeInfo.get(m)) !== null && _a !== void 0 ? _a : m; });
                    return this.renderer.text(text);
                }
                case 'strong': {
                    return this.renderer.strong(this.parseInline(token.tokens));
                }
                case 'em': {
                    return this.renderer.em(this.parseInline(token.tokens));
                }
                case 'del': {
                    return this.renderer.del(this.parseInline(token.tokens));
                }
                case 'codespan': {
                    return this.renderer.codespan(unescape(token.text));
                }
                case 'link': {
                    return this.renderer.link(token.href, this.parseInline(token.tokens));
                }
                case 'image': {
                    return this.renderer.image(token.href, token.text, token.title);
                }
                case 'html': {
                    return this.renderer.html(token.text);
                }
                case 'br': {
                    return this.renderer.br();
                }
                case 'escape': {
                    return this.renderer.text(token.text);
                }
                default: {
                    // eslint-disable-next-line no-console
                    console.warn(`Token with "${token.type}" type was not found`);
                    return null;
                }
            }
        });
    }
}
exports.MarkdownReactParser = MarkdownReactParser;
//# sourceMappingURL=parse.js.map