"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
var path_1 = require("path");
var querystring_1 = require("querystring");
var events_1 = require("events");
var electron_1 = require("electron");
var marked = require("marked");
var katex = require("katex");
var highlight_js_1 = require("highlight.js");
var he = require("he");
var marked_sanitizer_github_1 = require("marked-sanitizer-github");
var element_env = null;
var emoji_replacer = new Emoji.Replacer(path_1.dirname(__dirname) + '/images');
var mermaid = undefined;
marked.setOptions({
    langPrefix: 'hljs ',
    highlight: function (code, lang) {
        if (lang === undefined) {
            return code;
        }
        if (lang === 'mermaid') {
            if (mermaid === undefined) {
                mermaid = require('mermaid');
                mermaid.init(undefined, 'div.mermaid');
            }
            return '<div class="mermaid">' + he.encode(code) + '</div>';
        }
        if (lang === 'katex') {
            return '<div class="katex">' + katex.renderToString(code, { displayMode: true }) + '</div>';
        }
        try {
            return highlight_js_1.highlight(lang, code).value;
        }
        catch (e) {
            console.log('Error on highlight: ' + e.message);
            return code;
        }
    },
    emoji: function (name) {
        return emoji_replacer.replaceOne(name);
    },
    sanitize: 1,
});
var REGEX_CHECKED_LISTITEM = /^\[x]\s+/;
var REGEX_UNCHECKED_LISTITEM = /^\[ ]\s+/;
var MarkdownRenderer = (function (_super) {
    __extends(MarkdownRenderer, _super);
    function MarkdownRenderer(markdown_exts) {
        var _this = _super.call(this) || this;
        _this.markdown_exts = markdown_exts;
        _this.renderer = new marked.Renderer();
        var self = _this;
        _this.renderer.listitem = function (text) {
            var matched = text.match(REGEX_CHECKED_LISTITEM);
            if (matched && matched[0]) {
                return "\n                  <li class=\"task-list-item\">\n                    <input type=\"checkbox\" class=\"task-list-item-checkbox\" checked=\"checked\" disabled=\"disabled\">\n                    " + text.slice(matched[0].length) + "\n                  </li>\n                ";
            }
            matched = text.match(REGEX_UNCHECKED_LISTITEM);
            if (matched && matched[0]) {
                return "\n                  <li class=\"task-list-item\">\n                    <input type=\"checkbox\" class=\"task-list-item-checkbox\" disabled=\"disabled\">\n                    " + text.slice(matched[0].length) + "\n                  </li>\n                ";
            }
            return marked.Renderer.prototype.listitem.call(this, text);
        };
        var re_ext = new RegExp("\\.(:?" + _this.markdown_exts.join('|') + ")(:?$|#)");
        _this.renderer.link = function (href, title, text) {
            if (!href) {
                return marked.Renderer.prototype.link.call(this, href, title, text);
            }
            if (this.options.sanitize) {
                try {
                    var prot = decodeURIComponent(querystring_1.unescape(href))
                        .replace(/[^\w:]/g, '')
                        .toLowerCase();
                    if (prot.startsWith('javascript:') || prot.startsWith('vbscript:')) {
                        return '';
                    }
                }
                catch (e) {
                    return '';
                }
            }
            var onclick = 'cancelClick(event)';
            if (href.startsWith('http://') || href.startsWith('https://')) {
                onclick = "openLinkWithExternalBrowser(event, this.id)";
            }
            else if (re_ext.test(href)) {
                onclick = 'openMarkdownLink(event)';
            }
            else if (href.indexOf('#') !== -1) {
                onclick = 'openHashLink(event)';
            }
            self.link_id += 1;
            var id = "md-link-" + self.link_id;
            self.tooltips += "<paper-tooltip for=\"" + id + "\" offset=\"0\">" + he.encode(href) + "</paper-tooltip>";
            return title !== null
                ? "<a id=\"" + id + "\" href=\"" + href + "\" onclick=\"" + onclick + "\" title=" + title + ">" + text + "</a>"
                : "<a id=\"" + id + "\" href=\"" + href + "\" onclick=\"" + onclick + "\">" + text + "</a>";
        };
        _this.renderer.heading = function (text, level, raw) {
            var hash = this.options.headerPrefix + raw.toLowerCase().replace(/[^\w]+/g, '-');
            self.outline.push({
                title: raw,
                hash: hash,
                level: level,
                html: text,
            });
            return marked.Renderer.prototype.heading.call(this, text, level, raw);
        };
        _this.sanitizeState = new marked_sanitizer_github_1.default();
        _this.sanitizeState.onDetectedBroken = function (reason, tag) {
            _this.emit('sanitization-error', "HTML is broken around '" + tag + "' tag", reason);
        };
        _this.sanitizer = _this.sanitizeState.getSanitizer();
        return _this;
    }
    MarkdownRenderer.prototype.render = function (markdown) {
        this.link_id = 0;
        this.tooltips = '';
        this.outline = [];
        this.sanitizeState.reset();
        return (marked(markdown, {
            renderer: this.renderer,
            sanitizer: this.sanitizer,
        }) + this.tooltips);
    };
    return MarkdownRenderer;
}(events_1.EventEmitter));
function openMarkdownLink(event) {
    event.preventDefault();
    var target = event.target;
    while (target !== null) {
        if (target.href) {
            break;
        }
        target = target.parentElement;
    }
    if (target === null) {
        console.log('openMarkdownLink(): No target <a> was found', event);
        return;
    }
    var path = querystring_1.unescape(target.href);
    if (path.startsWith('file://')) {
        path = path.slice(7);
    }
    var hash_idx = path.indexOf('#');
    if (hash_idx !== -1) {
        path = path.slice(0, hash_idx);
    }
    if (process.platform === 'win32' && path[0] === '/') {
        path = path.slice(1);
    }
    if (element_env.openMarkdownDoc) {
        element_env.openMarkdownDoc(path, event.ctrlKey || event.metaKey);
    }
    else {
        console.log('openMarkdownDoc() is not defined!! Link ignored: ' + path);
    }
}
function openHashLink(event) {
    event.preventDefault();
    var target = event.target;
    var hash_name = target.href.split('#')[1];
    location.hash = hash_name;
}
function openLinkWithExternalBrowser(event, id) {
    event.preventDefault();
    var e = document.getElementById(id);
    electron_1.shell.openExternal(e.href);
}
function cancelClick(event) {
    event.preventDefault();
}
Polymer({
    is: 'markdown-preview',
    properties: {
        document: {
            type: String,
            observer: '_documentUpdated',
        },
        exts: {
            type: Array,
            value: function () {
                return [];
            },
        },
        currentOutline: {
            type: Array,
            value: function () {
                return [];
            },
        },
        isGithubStyle: {
            type: Boolean,
            value: true,
        },
        openMarkdownDoc: Object,
        fontSize: String,
        onDocumentUpdated: Object,
        onSanitizationError: Object,
    },
    ready: function () {
        element_env = this;
    },
    attached: function () {
        var _this = this;
        this.renderer = new MarkdownRenderer(this.exts);
        this.renderer.on('sanitization-error', function (message, reason) {
            if (_this.onSanitizationError) {
                _this.onSanitizationError(message, reason);
            }
        });
        var body = document.getElementById('shiba-markdown-component');
        if (this.fontSize) {
            body.style.fontSize = this.fontSize;
        }
        if (!this.isGithubStyle) {
            body.classList.remove('markdown-body');
        }
    },
    _documentUpdated: function (updated_doc) {
        var body = document.getElementById('shiba-markdown-component');
        body.innerHTML = this.renderer.render(updated_doc);
        this.currentOutline = this.renderer.outline;
        var mermaid_blocks = document.querySelectorAll('div.mermaid');
        if (mermaid_blocks.length > 0 && typeof mermaid !== 'undefined') {
            mermaid.init(undefined, mermaid_blocks);
        }
        if (this.onDocumentUpdated) {
            this.onDocumentUpdated();
        }
    },
    scrollToHeading: function (scroller, h) {
        var elem = document.getElementById(h.hash);
        if (elem) {
            scroller.scrollTop = elem.offsetTop;
        }
    },
});
//# sourceMappingURL=markdown-preview.js.map