"use strict"; var dom_toc = ebi('toc'), dom_wrap = ebi('mw'), dom_hbar = ebi('mh'), dom_nav = ebi('mn'), dom_pre = ebi('mp'), dom_src = ebi('mt'), dom_navtgl = ebi('navtoggle'), hash0 = location.hash; // chrome 49 needs this var chromedbg = function () { console.log(arguments); } // null-logger var dbg = function () { }; // replace dbg with the real deal here or in the console: // dbg = chromedbg // dbg = console.log // dodge browser issues (function () { var ua = navigator.userAgent; if (ua.indexOf(') Gecko/') !== -1 && /Linux| Mac /.exec(ua)) { // necessary on ff-68.7 at least var s = mknod('style'); s.innerHTML = '@page { margin: .5in .6in .8in .6in; }'; console.log(s.innerHTML); document.head.appendChild(s); } })(); // add navbar (function () { var parts = (get_evpath().slice(0, -1).split('?')[0] + '?v').split('/'), link = '', o; for (var a = 0, aa = parts.length - 1; a <= aa; a++) { link += parts[a] + (a < aa ? '/' : ''); o = mknod('a'); o.setAttribute('href', link); o.textContent = uricom_dec(parts[a].split('?')[0]) || 'top'; dom_nav.appendChild(o); } })(); // image load handler var img_load = (function () { var r = {}; r.callbacks = []; var fire = function () { for (var a = 0; a < r.callbacks.length; a++) r.callbacks[a](); } var timeout = null; r.done = function () { clearTimeout(timeout); timeout = setTimeout(fire, 500); }; return r; })(); // faster than replacing the entire html (chrome 1.8x, firefox 1.6x) function copydom(src, dst, lv) { var sc = src.childNodes, dc = dst.childNodes; if (sc.length !== dc.length) { dbg("replace L%d (%d/%d) |%d|", lv, sc.length, dc.length, src.innerHTML.length); dst.innerHTML = src.innerHTML; return; } var rpl = []; for (var a = sc.length - 1; a >= 0; a--) { var st = sc[a].tagName || sc[a].nodeType, dt = dc[a].tagName || dc[a].nodeType; if (st !== dt) { dbg("replace L%d (%d/%d) type %s/%s", lv, a, sc.length, st, dt); dst.innerHTML = src.innerHTML; return; } var sa = sc[a].attributes || [], da = dc[a].attributes || []; if (sa.length !== da.length) { dbg("replace L%d (%d/%d) attr# %d/%d", lv, a, sc.length, sa.length, da.length); rpl.push(a); continue; } var dirty = false; for (var b = sa.length - 1; b >= 0; b--) { var name = sa[b].name, sv = sa[b].value, dv = dc[a].getAttribute(name); if (name == "data-ln" && sv !== dv) { dc[a].setAttribute(name, sv); continue; } if (sv !== dv) { dbg("replace L%d (%d/%d) attr %s [%s] [%s]", lv, a, sc.length, name, sv, dv); dirty = true; break; } } if (dirty) rpl.push(a); } // TODO pure guessing if (rpl.length > sc.length / 3) { dbg("replace L%d fully, %s (%d/%d) |%d|", lv, rpl.length, sc.length, src.innerHTML.length); dst.innerHTML = src.innerHTML; return; } // repl is reversed; build top-down var nbytes = 0; for (var a = rpl.length - 1; a >= 0; a--) { var i = rpl[a], prop = sc[i].nodeType == 1 ? 'outerHTML' : 'nodeValue'; var html = sc[i][prop]; dc[i][prop] = html; nbytes += html.length; } if (nbytes > 0) dbg("replaced %d bytes L%d", nbytes, lv); for (var a = 0; a < sc.length; a++) copydom(sc[a], dc[a], lv + 1); if (src.innerHTML !== dst.innerHTML) { dbg("setting %d bytes L%d", src.innerHTML.length, lv); dst.innerHTML = src.innerHTML; } } md_plug_err = function (ex, js) { qsr('#md_errbox'); if (!ex) return; var msg = (ex + '').split('\n')[0]; var ln = ex.lineNumber; var o = null; if (ln) { msg = "Line " + ln + ", " + msg; var lns = js.split('\n'); if (ln < lns.length) { o = mknod('span'); o.style.cssText = "color:#ac2;font-size:.9em;font-family:'scp',monospace,monospace;display:block"; o.textContent = lns[ln - 1]; } } var errbox = mknod('div', 'md_errbox'); errbox.style.cssText = 'position:absolute;top:0;left:0;padding:1em .5em;background:#2b2b2b;color:#fc5' errbox.textContent = msg; errbox.onclick = function () { modal.alert('
' + esc(ex.stack) + '
'); }; if (o) { errbox.appendChild(o); errbox.style.padding = '.25em .5em'; } dom_nav.appendChild(errbox); try { console.trace(); } catch (ex2) { } } function convert_markdown(md_text, dest_dom) { md_text = md_text.replace(/\r/g, ''); md_plug_err(null); md_text = load_md_plug(md_text, 'pre'); md_text = load_md_plug(md_text, 'post'); var marked_opts = { //headerPrefix: 'h-', breaks: true, gfm: true }; var ext = md_plug.pre; if (ext) Object.assign(marked_opts, ext[0]); try { var md_html = marked.parse(md_text, marked_opts); if (!have_emp) md_html = DOMPurify.sanitize(md_html); } catch (ex) { if (IE) { dest_dom.innerHTML = 'IE cannot into markdown ;_;'; return; } if (ext) md_plug_err(ex, ext[1]); throw ex; } var md_dom = dest_dom; try { md_dom = new DOMParser().parseFromString(md_html, "text/html").body; } catch (ex) { md_dom.innerHTML = md_html; window.copydom = noop; } var nodes = md_dom.getElementsByTagName('a'); for (var a = nodes.length - 1; a >= 0; a--) { var href = nodes[a].getAttribute('href'); var txt = nodes[a].innerHTML; if (!txt) nodes[a].textContent = href; else if (href !== txt && !nodes[a].className) nodes[a].className = 'vis'; } // todo-lists (should probably be a marked extension) nodes = md_dom.getElementsByTagName('input'); for (var a = nodes.length - 1; a >= 0; a--) { var dom_box = nodes[a]; if (dom_box.getAttribute('type') !== 'checkbox') continue; var dom_li = dom_box.parentNode; var done = dom_box.getAttribute('checked'); done = done !== null; var clas = done ? 'done' : 'pend'; var char = done ? 'Y' : 'N'; dom_li.className = 'task-list-item'; dom_li.style.listStyleType = 'none'; var html = dom_li.innerHTML; dom_li.innerHTML = '' + char + '' + html.slice(html.indexOf('>') + 1); } // separate for each line in
    nodes = md_dom.getElementsByTagName('pre');
    for (var a = nodes.length - 1; a >= 0; a--) {
        var el = nodes[a];

        var is_precode =
            el.tagName == 'PRE' &&
            el.childNodes.length === 1 &&
            el.childNodes[0].tagName == 'CODE';

        if (!is_precode)
            continue;

        var nline = parseInt(el.getAttribute('data-ln')) + 1;
        var lines = el.innerHTML.replace(/\n<\/code>$/i, '').split(/\n/g);
        for (var b = 0; b < lines.length - 1; b++)
            lines[b] += '\n';

        el.innerHTML = lines.join('');
    }

    // self-link headers
    var id_seen = {},
        dyn = md_dom.getElementsByTagName('*');

    nodes = [];
    for (var a = 0, aa = dyn.length; a < aa; a++)
        if (/^[Hh]([1-6])/.exec(dyn[a].tagName) !== null)
            nodes.push(dyn[a]);

    for (var a = 0; a < nodes.length; a++) {
        el = nodes[a];
        var id = el.getAttribute('id'),
            orig_id = id;

        if (id_seen[id]) {
            for (var n = 1; n < 4096; n++) {
                id = orig_id + '-' + n;
                if (!id_seen[id])
                    break;
            }
            el.setAttribute('id', id);
        }
        id_seen[id] = 1;
        el.innerHTML = '' + el.innerHTML + '';
    }

    ext = md_plug.post;
    if (ext && ext[0].render)
        try {
            ext[0].render(md_dom);
        }
        catch (ex) {
            md_plug_err(ex, ext[1]);
        }

    copydom(md_dom, dest_dom, 0);

    var imgs = dest_dom.getElementsByTagName('img');
    for (var a = 0, aa = imgs.length; a < aa; a++)
        imgs[a].onload = img_load.done;

    if (ext && ext[0].render2)
        try {
            ext[0].render2(dest_dom);
        }
        catch (ex) {
            md_plug_err(ex, ext[1]);
        }

    if (hash0)
        setTimeout(function () {
            try {
                QS(hash0).scrollIntoView();
                hash0 = '';
            }
            catch (ex) { }
        }, 1);
}


function init_toc() {
    qsr('#ml');

    var anchors = [];  // list of toc entries, complex objects
    var anchor = null; // current toc node
    var html = [];     // generated toc html
    var lv = 0;        // current indentation level in the toc html
    var ctr = [0, 0, 0, 0, 0, 0];

    var manip_nodes_dyn = dom_pre.getElementsByTagName('*');
    var manip_nodes = [];
    for (var a = 0, aa = manip_nodes_dyn.length; a < aa; a++)
        manip_nodes.push(manip_nodes_dyn[a]);

    for (var a = 0, aa = manip_nodes.length; a < aa; a++) {
        var elm = manip_nodes[a];
        var m = /^[Hh]([1-6])/.exec(elm.tagName);
        var is_header = m !== null;
        if (is_header) {
            var nlv = m[1];
            while (lv < nlv) {
                html.push('');
                lv--;
            }
            ctr[lv - 1]++;
            for (var b = lv; b < 6; b++)
                ctr[b] = 0;

            elm.childNodes[0].setAttribute('ctr', ctr.slice(0, lv).join('.'));

            var elm2 = elm.cloneNode(true);
            elm2.childNodes[0].textContent = elm.textContent;
            while (elm2.childNodes.length > 1)
                elm2.removeChild(elm2.childNodes[1]);

            html.push('
  • ' + elm2.innerHTML + '
  • '); if (anchor != null) anchors.push(anchor); anchor = { elm: elm, kids: [], y: null }; } if (!is_header && anchor) anchor.kids.push(elm); } dom_toc.innerHTML = html.join('\n'); if (anchor != null) anchors.push(anchor); // copy toc links into the toc list var atoc = dom_toc.getElementsByTagName('a'); for (var a = 0, aa = anchors.length; a < aa; a++) anchors[a].lnk = atoc[a]; // collect vertical position of all toc items (headers in document) function freshen_offsets() { var top = yscroll(); for (var a = anchors.length - 1; a >= 0; a--) { var y = top + anchors[a].elm.getBoundingClientRect().top; y = Math.round(y * 10.0) / 10; if (anchors[a].y === y) break; anchors[a].y = y; } } // hilight the correct toc items + scroll into view function freshen_toclist() { if (anchors.length == 0) return; var ptop = yscroll(); var hit = anchors.length - 1; for (var a = 0; a < anchors.length; a++) { if (anchors[a].y >= ptop - 8) { //??? hit = a; break; } } var links = dom_toc.getElementsByTagName('a'); if (!anchors[hit].active) { for (var a = 0; a < anchors.length; a++) { if (anchors[a].active) { anchors[a].active = false; links[a].className = ''; } } anchors[hit].active = true; links[hit].className = 'act'; } var pane_height = parseInt(getComputedStyle(dom_toc).height); var link_bounds = links[hit].getBoundingClientRect(); var top = link_bounds.top - (pane_height / 6); var btm = link_bounds.bottom + (pane_height / 6); if (top < 0) dom_toc.scrollTop -= -top; else if (btm > pane_height) dom_toc.scrollTop += btm - pane_height; } function refresh() { freshen_offsets(); freshen_toclist(); } return { "refresh": refresh } } // "main" :p convert_markdown(dom_src.value, dom_pre); var toc = init_toc(); img_load.callbacks = [toc.refresh]; // scroll handler var redraw = (function () { var sbs = true; var onresize = function () { if (window.matchMedia) sbs = window.matchMedia('(min-width: 64em)').matches; var y = (dom_hbar.offsetTop + dom_hbar.offsetHeight) + 'px'; if (sbs) { dom_toc.style.top = y; dom_wrap.style.top = y; dom_toc.style.marginTop = '0'; } onscroll(); } var onscroll = function () { toc.refresh(); } window.onresize = onresize; window.onscroll = onscroll; dom_wrap.onscroll = onscroll; onresize(); return onresize; })(); dom_navtgl.onclick = function () { var hidden = dom_navtgl.innerHTML == 'hide nav'; dom_navtgl.innerHTML = hidden ? 'show nav' : 'hide nav'; dom_nav.style.display = hidden ? 'none' : 'block'; swrite('hidenav', hidden ? 1 : 0); redraw(); }; if (!HTTPS && location.hostname != '127.0.0.1') try { ebi('edit2').onclick = function (e) { toast.err(0, "the fancy editor is only available over https"); return ev(e); } } catch (ex) { } if (sread('hidenav') == 1) dom_navtgl.onclick(); if (window.tt && tt.init) tt.init();