Ver código fonte

增加markdown&html互转工具

zxlie 7 anos atrás
pai
commit
bf480a4088

+ 1 - 0
README.md

@@ -31,6 +31,7 @@ https://chrome.google.com/webstore/detail/pkgccpejnmalmdinmhkkfafefagiiiad?hl=zh
 - 代码压缩工具(HTML/CSS/JS)
 - 二维码生成器(支持当前页面、图片、链接、选中的文字生成QrCode)
 - 二维码解码器(支持网页二维码`右键`解码)
+- Markdown转换(支持Markdown与HTML的互转)
 - 页面取色工具(滑动鼠标随意取色)
 - Js正则表达式(正则测试、常用正则列表)
 - 时间(戳)转换(Unix戳与本地时间的互转)

+ 1 - 1
apps/en-decode/index.js

@@ -58,7 +58,7 @@ new Vue({
             });
         },
 
-        clear: () => {
+        clear: function() {
             this.sourceContent = '';
             this.resultContent = '';
         },

+ 39 - 0
apps/html2markdown/index.css

@@ -0,0 +1,39 @@
+@import url("../static/css/bootstrap.min.css");
+
+#srcText {
+    height: 150px;
+}
+#rstCode {
+    height: 330px;
+    width: 100%;
+    border:none;
+    padding: 5px;
+    resize:vertical;
+    background:#000;
+    color:#fff;
+}
+
+#rstCode::selection {
+    background: #faf2cc ;
+}
+
+.ui-ml-05 {
+    margin-left: 5px;
+}
+.x-preview {
+    height: auto;
+}
+.x-xdemo,.x-switch {
+    margin-left: 30px;
+    font-size: 12px;
+    color: blue;
+    cursor: pointer;
+    text-decoration: underline;
+}
+.x-xdemo:hover,.x-switch:hover {
+    color: #cc8841;
+}
+.x-switch {
+    color:#f00;
+    border-bottom: 1px solid #f00;
+}

+ 72 - 0
apps/html2markdown/index.html

@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<html lang="zh-CN">
+<head>
+    <title>HTML转Markdown工具</title>
+    <meta charset="UTF-8">
+    <link rel="stylesheet" href="index.css" />
+    <script type="text/javascript" src="../static/vendor/vue/vue.js"></script>
+    <script src="../static/vendor/require/require.js"></script>
+</head>
+<body>
+
+<div class="wrapper" id="pageContainer">
+    <div class="panel panel-default" style="margin-bottom: 0px;">
+        <div class="panel-heading">
+            <h3 class="panel-title">
+                <a href="http://www.baidufe.com/fehelper/feedback.html" target="_blank" class="x-a-high">
+                    <img src="../static/img/fe-16.png" alt="fehelper"/> FeHelper</a>:{{toolName[codeType]}}工具
+                <span class="x-xdemo" ref="demoLink1" @click="setDemo">示例:{{codeType}}片段</span>
+
+                <span class="x-switch ui-fl-r" ref="btnSwitch" @click="trans">切换为{{toolName[nextCodeType]}}&gt;&gt;</span>
+            </h3>
+        </div>
+    </div>
+    <div class="panel-body mod-endecode">
+
+        <div class="row">
+            <textarea class="form-control mod-textarea ui-mb-10" id="srcText" ref="srcText" v-model="sourceContent" @input="convert"
+                      placeholder="粘贴或输入需要进行转换的内容"></textarea>
+        </div>
+
+        <div id="rst" class="row ui-mt-10" v-show="resultContent.length > 0">
+            <a href="#" @click="preview" v-html="previewText"></a><hr>
+            <textarea class="mod-textarea" id="rstCode" ref="rstCode" v-model="resultContent" @click="getResult" v-show="!showPreview"></textarea>
+            <div class="x-preview" v-show="showPreview" v-html="previewHTML"></div>
+        </div>
+    </div>
+
+    <div class="html-demo hide" ref="htmlDemo">
+        <h2 class="fe-function-title">FE助手</h2>
+        <ul class="fe-function-list">
+            <li class="-x-endecode" >
+                <span>字符串编解码</span></li>
+            <li class="-x-jsonformat">
+                <span><code>Json</code>串格式化</span></li>
+            <li class="-x-codebeautify">
+                <span>代码美化工具</span></li>
+            <li class="-x-codecompress">
+                <span>代码压缩工具</span></li>
+            <li class="-x-qrcode">
+                <span>二维码生成器</span></li>
+            <li class="-x-colorpicker">
+                <span>页面取色工具</span></li>
+            <li class="-x-regexp">
+                <span>Js正则表达式</span></li>
+            <li class="-x-timestamp">
+                <span>时间(戳)转换</span></li>
+            <li class="-x-base64">
+                <span>图片Base64</span></li>
+            <li class="-x-fcp">
+                <span>编码规范检测</span></li>
+            <li class="-x-loadtime">
+                <span>页面性能检测</span></li>
+            <li class="-x-markdown">
+                <span>Html转<code>Markdown</code></span></li>
+            <li class="-x-ajax-debugger">
+                <span>Ajax调试:<strong>关</strong></span></li>
+        </ul>
+    </div>
+</div>
+<script type="text/javascript" src="index.js"></script>
+</body>
+</html>

+ 83 - 0
apps/html2markdown/index.js

@@ -0,0 +1,83 @@
+/**
+ * FeHelper HTML转Markdown
+ */
+new Vue({
+    el: '#pageContainer',
+    data: {
+        sourceContent: '',
+        resultContent: '',
+        previewHTML: '',
+        showPreview: false,
+        previewText: '效果预览',
+        codeType: 'HTML',
+        nextCodeType: 'Markdown',
+        toolName: {
+            HTML: 'HTML转Markdown',
+            Markdown: 'Markdown转HTML'
+        }
+    },
+
+    mounted: function () {
+        this.$refs.srcText.focus();
+    },
+    methods: {
+        convert: function () {
+            let h2m = Tarp.require('../static/vendor/h2m/h2m');
+            let markdown = Tarp.require('../static/vendor/h2m/markdown');
+            if (this.codeType === 'HTML') {
+                this.resultContent = h2m(this.sourceContent, {
+                    converter: 'CommonMark' // CommonMark | MarkdownExtra
+                });
+                this.previewHTML = markdown.toHTML(this.resultContent);
+            } else {
+                this.resultContent = this.previewHTML = markdown.toHTML(this.sourceContent);
+            }
+        },
+
+        preview: function (event) {
+            event && event.preventDefault();
+            this.showPreview = !this.showPreview;
+            this.previewText = this.showPreview ? '查看源码' : '效果预览';
+        },
+
+        trans: function () {
+            this.codeType = {HTML: 'Markdown', Markdown: 'HTML'}[this.codeType];
+            this.nextCodeType = {HTML: 'Markdown', Markdown: 'HTML'}[this.nextCodeType];
+            this.preview();
+            this.clear();
+        },
+
+        clear: function () {
+            this.sourceContent = '';
+            this.resultContent = '';
+            this.resultContent = false;
+        },
+
+        getResult: function () {
+            this.$refs.rstCode.select();
+        },
+
+        setDemo: function () {
+            if (this.codeType === 'HTML') {
+                this.sourceContent = this.$refs.htmlDemo.innerHTML;
+            } else {
+                this.sourceContent = '## FE助手\n' +
+                    '\n' +
+                    '- 字符串编解码\n' +
+                    '- `Json`串格式化\n' +
+                    '- 代码美化工具\n' +
+                    '- 代码压缩工具\n' +
+                    '- 二维码生成器\n' +
+                    '- 页面取色工具\n' +
+                    '- Js正则表达式\n' +
+                    '- 时间(戳)转换\n' +
+                    '- 图片Base64\n' +
+                    '- 编码规范检测\n' +
+                    '- 页面性能检测\n' +
+                    '- Html转`Markdown`\n' +
+                    '- Ajax调试:**关**';
+            }
+            this.convert();
+        }
+    }
+});

+ 2 - 2
apps/manifest.json

@@ -1,9 +1,9 @@
 {
   "name": "WEB前端助手(FeHelper)",
-  "version": "2018.04.2519",
+  "version": "2018.04.2611",
   "manifest_version": 2,
   "default_locale": "zh_CN",
-  "description": "FE助手:包括JSON格式化、二维码生成与解码、信息编解码、代码压缩、美化、页面取色、正则表达式、时间转换工具、编码规范检测、页面性能检测、Ajax接口调试",
+  "description": "FE助手:包括JSON格式化、二维码生成与解码、信息编解码、代码压缩、美化、页面取色、Markdown与HTML互转、正则表达式、时间转换工具、编码规范检测、页面性能检测、Ajax接口调试",
   "icons": {
     "16": "static/img/fe-16.png",
     "48": "static/img/fe-48.png",

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
apps/options/index.html


+ 2 - 1
apps/options/settings.js

@@ -22,7 +22,8 @@ module.exports = (() => {
         'FCP_HELPER_DETECT',
         'SHOW_PAGE_LOAD_TIME',
         'AJAX_DEBUGGER',
-        'JS_CSS_PAGE_BEAUTIFY'
+        'JS_CSS_PAGE_BEAUTIFY',
+        'HTML_TO_MARKDOWN'
     ];
 
     /**

+ 4 - 0
apps/popup/index.css

@@ -87,6 +87,10 @@ ul.fe-function-list li.-x-colorpicker b {
 ul.fe-function-list li.-x-ajax-debugger b {
     background-position:-81px -129px;
 }
+ul.fe-function-list li.-x-markdown b {
+	background-position:-83px -222px;
+}
+
 ul.fe-function-list li i {
     color: #aaa;
     font-weight: 700;

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
apps/popup/index.html


+ 2 - 0
apps/static/js/msg_type.js

@@ -83,6 +83,8 @@ const MSG_TYPE = {
     AJAX_DEBUGGER_CONSOLE: "ajax-debugger-console",
     AJAX_DEBUGGER_SWITCH: "ajax-debugger-switch",
 
+    HTML_TO_MARKDOWN: "html2markdown",
+
     // dev tools页面
     DEV_TOOLS: 'dev-tools',
 

+ 10650 - 0
apps/static/vendor/h2m/h2m.js

@@ -0,0 +1,10650 @@
+(function e(t, n, r) {
+    function s(o, u) {
+        if (!n[o]) {
+            if (!t[o]) {
+                var a = typeof require == "function" && require;
+                if (!u && a) return a(o, !0);
+                if (i) return i(o, !0);
+                var f = new Error("Cannot find module '" + o + "'");
+                throw f.code = "MODULE_NOT_FOUND", f
+            }
+            var l = n[o] = {exports: {}};
+            t[o][0].call(l.exports, function (e) {
+                var n = t[o][1][e];
+                return s(n ? n : e)
+            }, l, l.exports, e, t, n, r)
+        }
+        return n[o].exports
+    }
+
+    var i = typeof require == "function" && require;
+    for (var o = 0; o < r.length; o++) s(r[o]);
+    return s
+})({
+    1: [function (require, module, exports) {
+        window.h2m = require('./index')
+
+    }, {"./index": 5}],
+    2: [function (require, module, exports) {
+        /**
+         * http://commonmark.org/help/
+         */
+
+        var LI_HEADER = 'H2M_LI_HEADER'
+
+        module.exports = {
+            em: function (node) {
+                if (node.md) {
+                    return `*${node.md}*`
+                }
+            },
+            strong: function (node) {
+                if (node.md) {
+                    return `**${node.md}**`
+                }
+            },
+            h1: function (node) {
+                if (node.md) {
+                    return `\n# ${node.md}\n`
+                }
+            },
+            h2: function (node) {
+                if (node.md) {
+                    return `\n## ${node.md}\n`
+                }
+            },
+            h3: function (node) {
+                if (node.md) {
+                    return `\n### ${node.md}\n`
+                }
+            },
+            h4: function (node) {
+                if (node.md) {
+                    return `\n#### ${node.md}\n`
+                }
+            },
+            h5: function (node) {
+                if (node.md) {
+                    return `\n##### ${node.md}\n`
+                }
+            },
+            h6: function (node) {
+                if (node.md) {
+                    return `\n###### ${node.md}\n`
+                }
+            },
+            a: function (node) {
+                var text = node.md || node.attrs.href
+                var href = node.attrs.href || text
+                if (text) {
+                    return `[${text}](${href})`
+                }
+            },
+            img: function (node) {
+                var src = node.attrs.src
+                if (src) {
+                    return `![${(node.attrs.title || node.attrs.alt || '').trim()}](${src})`
+                }
+            },
+            blockquote: function (node) {
+                var md = node.md
+                if (md) {
+                    md = md.replace(/(^\n+|\n+$)/g, '')
+                    md = md.split('\n').map(function (line) {
+                        return `> ${line}\n`
+                    }).join('')
+                    return `\n${md}\n`
+                }
+            },
+            ul: function (node) {
+                if (node.md) {
+                    return `\n${node.md.replace(new RegExp(LI_HEADER, 'ig'), '-')}\n`
+                }
+            },
+            ol: function (node) {
+                var index = 1
+                if (node.md) {
+                    return `\n${node.md.replace(new RegExp(LI_HEADER, 'ig'), function () {
+                        return `${index++}.`
+                    })}\n`
+                }
+            },
+            li: function (node) {
+                if (node.md) {
+                    return `${LI_HEADER} ${node.md}\n`
+                }
+            },
+            hr: function () {
+                return '\n---\n'
+            },
+            code: function (node) {
+                if (node.md) {
+                    if (node.isInPreNode) {
+                        return node.md
+                    }
+                    return `\`${node.md}\``
+                }
+            },
+            br: function () {
+                return '\n'
+            },
+            pre: function (node) {
+                var md = node.md
+                if (md) {
+                    md = md.split('\n').map(function (line) {
+                        return `    ${line}\n`
+                    }).join('')
+                    return `\n${md}\n`
+                }
+            },
+            p: function (node) {
+                var md = node.md
+                if (md) {
+                    return `\n${md}\n`
+                }
+            },
+            div: function (node) {
+                var md = node.md
+                if (md) {
+                    return `\n${md}\n`
+                }
+            },
+            'default': function (node) {
+                return node.md
+            },
+            cleanup: function (result) {
+                // remove leading or tailing break
+                // convert \n\n\n... to \n\n
+                return result.replace(/(^\n+|\n+$)/g, '')
+                    .replace(/\n{3,}/g, '\n\n')
+            }
+        }
+
+    }, {}],
+    3: [function (require, module, exports) {
+        module.exports = {
+            'CommonMark': require('./commonmark'),
+            'MarkdownExtra': require('./markdown-extra')
+        }
+
+    }, {"./commonmark": 2, "./markdown-extra": 4}],
+    4: [function (require, module, exports) {
+        /**
+         * implement based on https://michelf.ca/projects/php-markdown/extra/
+         */
+
+        var CommonMark = require('./commonmark')
+
+        var ignoreAttributes = ['id', 'class', 'href', 'src', 'alt']
+
+        function getSpecialAttributes(node) {
+            var specialAttributes = []
+            var value = node.attrs['id']
+            if (value) {
+                specialAttributes.push(`#${value}`)
+            }
+            value = node.attrs['class']
+            if (value) {
+                specialAttributes.push(value.split(/\s+/).map(function (klass) {
+                    return `.${klass}`
+                }).join(' '))
+            }
+            Object.keys(node.attrs).forEach(function (key) {
+                if (ignoreAttributes.indexOf(key) == -1) {
+                    specialAttributes.push(`${key}=${value}`)
+                }
+            })
+            specialAttributes = specialAttributes.join(' ')
+
+            if (specialAttributes.length <= 0) {
+                return ''
+            } else {
+                return ` (${specialAttributes})`
+            }
+        }
+
+        var Extra = Object.create(CommonMark)
+
+// Special Attributes
+// headers
+        var hx
+        for (var i = 0; i < 6; i++) {
+            (function (j) {
+                hx = `h${j}`
+                Extra[hx] = function (node) {
+                    var hashes = '#'.repeat(j)
+                    return `\n${hashes} ${node.md} ${hashes}${getSpecialAttributes(node)}\n`
+                }
+            })(i + 1)
+
+        }
+// links
+        Extra['a'] = function (node) {
+            return `${CommonMark['a'](node)}${getSpecialAttributes(node)}`
+        }
+// images
+        Extra['img'] = function (node) {
+            return `${CommonMark['img'](node)}${getSpecialAttributes(node)}`
+        }
+
+
+// Fenced Code Blocks
+        Extra['pre'] = function (node) {
+            return `\n\`\`\`\n${node.md}\n\`\`\`\n`
+        }
+
+// Abbreviations
+        var abbrs = []
+
+        Extra['abbr'] = function (node) {
+            if (node.attrs.title != '') {
+                abbrs.push({
+                    word: node.md,
+                    title: node.attrs.title
+                })
+            }
+            return node.md
+        }
+
+        var isHandleTheadChar = false;
+        var isTh = false;
+        var trCount = 0;
+        var thCount = 0;
+
+// Tables
+        Extra['table'] = function (node) {
+            var theadChar = '';
+            if (!isHandleTheadChar) {
+                theadChar = getTeadChar() + '\n';
+            }
+            if (!isTh) {
+                resetTable();
+                return '';
+            }
+            resetTable();
+            return `\n${node.md}\n${theadChar}`;
+        }
+
+        Extra['tr'] = function (node) {
+            var trStr = '';
+            trCount++;
+
+            trStr = `\n|${node.md}`;
+
+            if (!isHandleTheadChar && trCount == 2) {
+                var theadChar = getTeadChar();
+                isHandleTheadChar = true;
+                return `\n${theadChar}${trStr}`;
+            } else {
+
+                return `${trStr}`;
+            }
+
+        }
+        Extra['th'] = function (node) {
+            isTh = true;
+            thCount++;
+            return `${node.md}|`;
+        }
+        Extra['td'] = function (node) {
+            isTh = true;
+            if (trCount == 0) {
+                thCount++;
+            }
+            var md = replaceBr(node.md);
+            return `${md}|`;
+        }
+
+// Definition Lists
+        Extra['dl'] = function (node) {
+            var md = node.md
+            if (md) {
+                return `\n${md}\n`
+            }
+        }
+        Extra['dt'] = function (node) {
+            // console.log(node)
+            var md = node.md
+            if (md) {
+                return `${md}\n`
+            }
+        }
+        Extra['dd'] = function (node) {
+            var md = node.md
+            if (md) {
+                return `:   ${md}\n\n`
+            }
+        }
+
+        function resetTable() {
+            isTr = false;
+            isTh = false;
+            thCount = 0;
+            trCount = 0;
+            isHandleTheadChar = false;
+        }
+
+        function getTeadChar() {
+            var theadChar = '|';
+            for (var i = thCount; i > 0; i--) {
+                theadChar += '--------|';
+            }
+            return theadChar;
+        }
+
+        function replaceBr(content) {
+            return content.replace(/(<br>)|(<br\/>)|(\n)|(\r\n)/g, '');
+        }
+
+        function generateAbbreviations() {
+            var results = abbrs.map(function (abbr) {
+                return `*[${abbr.word}]: ${abbr.title}`
+            }).join('\n')
+            // clean up
+            abbrs = []
+            return results
+        }
+
+        Extra.cleanup = function (result) {
+            // append abbreviations to tail of markdown
+            return CommonMark.cleanup(`${result}\n\n${generateAbbreviations()}`)
+        }
+
+        module.exports = Extra
+    }, {"./commonmark": 2}],
+    5: [function (require, module, exports) {
+        var htmlparser = require("htmlparser2")
+        var converters = require('./converters/')
+
+        var escapeMap = {
+            "&amp;": "&",
+            "&lt;": "<",
+            "&gt;": ">",
+            "&quot;": "\"",
+            "&#x27;": "'",
+            "&#x60;": "`",
+            "&nbsp;": " ",
+            "&#8202;": " "
+        }
+
+        var unescape = (function () {
+            var source = `(?:${Object.keys(escapeMap).join('|')})`
+            var testRegexp = RegExp(source)
+            var replaceRegexp = RegExp(source, 'g')
+            var escaper = function (match) {
+                return escapeMap[match]
+            }
+            return function (string) {
+                string = string || ''
+                return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string
+            }
+        })()
+
+        /**
+         * @param html {String} the html to be onverted
+         * @param options {Object}
+         *   {
+ *      converter {String} which converter you choose
+ *      overides {Object<String, Function>} override converter behavior, for example:
+ *          {
+ *              br: function (node) {
+ *                  return `\n\n` // let br tag break twice
+ *              }
+ *          }
+ *   }
+         */
+        module.exports = function (html, options) {
+            options = Object.assign({
+                converter: 'CommonMark'
+            }, options)
+
+            var converter = Object.assign(
+                Object.create(converters[options.converter]),
+                options.overides || {}
+            )
+
+            var nodeBuffer = []
+            var results = []
+            var isInPreNode = false
+
+            function convert(node) {
+                node.md = (node.md && node.md.join('')) || ''
+                return (converter[node.name] || converter['default'])(node) || ''
+            }
+
+            var parser = new htmlparser.Parser({
+                onopentag: function (name, attributes) {
+                    var node = {
+                        name: name,
+                        attrs: attributes,
+                        isInPreNode: isInPreNode
+                    }
+                    if (name === 'pre') {
+                        isInPreNode = true
+                    }
+                    nodeBuffer.push(node)
+                },
+                ontext: function (text) {
+                    if (/^\s+$/.test(text)) {
+                        return
+                    }
+                    text = unescape(text)
+                    var last = nodeBuffer[nodeBuffer.length - 1]
+                    if (last) {
+                        last.md = last.md || []
+                        last.md.push(text)
+                    } else {
+                        results.push(text)
+                    }
+                },
+                onclosetag: function (name) {
+                    var last = nodeBuffer.pop()
+                    var md = convert(last)
+
+                    if (name === 'pre') {
+                        isInPreNode = false
+                    }
+
+                    if (nodeBuffer.length === 0) {
+                        return results.push(md)
+                    }
+
+                    var tail = nodeBuffer[nodeBuffer.length - 1]
+                    tail.md = tail.md || []
+                    tail.md.push(md)
+                }
+            }, {decodeEntities: false})
+            parser.write(html)
+            parser.end()
+            // remove the \n on head or tail
+            return typeof converter.cleanup == 'function'
+                ? converter.cleanup(results.join(''))
+                : results.join('')
+        }
+
+    }, {"./converters/": 3, "htmlparser2": 13}],
+    6: [function (require, module, exports) {
+        module.exports = CollectingHandler;
+
+        function CollectingHandler(cbs) {
+            this._cbs = cbs || {};
+            this.events = [];
+        }
+
+        var EVENTS = require("./").EVENTS;
+        Object.keys(EVENTS).forEach(function (name) {
+            if (EVENTS[name] === 0) {
+                name = "on" + name;
+                CollectingHandler.prototype[name] = function () {
+                    this.events.push([name]);
+                    if (this._cbs[name]) this._cbs[name]();
+                };
+            } else if (EVENTS[name] === 1) {
+                name = "on" + name;
+                CollectingHandler.prototype[name] = function (a) {
+                    this.events.push([name, a]);
+                    if (this._cbs[name]) this._cbs[name](a);
+                };
+            } else if (EVENTS[name] === 2) {
+                name = "on" + name;
+                CollectingHandler.prototype[name] = function (a, b) {
+                    this.events.push([name, a, b]);
+                    if (this._cbs[name]) this._cbs[name](a, b);
+                };
+            } else {
+                throw Error("wrong number of arguments");
+            }
+        });
+
+        CollectingHandler.prototype.onreset = function () {
+            this.events = [];
+            if (this._cbs.onreset) this._cbs.onreset();
+        };
+
+        CollectingHandler.prototype.restart = function () {
+            if (this._cbs.onreset) this._cbs.onreset();
+
+            for (var i = 0, len = this.events.length; i < len; i++) {
+                if (this._cbs[this.events[i][0]]) {
+
+                    var num = this.events[i].length;
+
+                    if (num === 1) {
+                        this._cbs[this.events[i][0]]();
+                    } else if (num === 2) {
+                        this._cbs[this.events[i][0]](this.events[i][1]);
+                    } else {
+                        this._cbs[this.events[i][0]](this.events[i][1], this.events[i][2]);
+                    }
+                }
+            }
+        };
+
+    }, {"./": 13}],
+    7: [function (require, module, exports) {
+        var index = require("./index.js"),
+            DomHandler = index.DomHandler,
+            DomUtils = index.DomUtils;
+
+//TODO: make this a streamable handler
+        function FeedHandler(callback, options) {
+            this.init(callback, options);
+        }
+
+        require("util").inherits(FeedHandler, DomHandler);
+
+        FeedHandler.prototype.init = DomHandler;
+
+        function getElements(what, where) {
+            return DomUtils.getElementsByTagName(what, where, true);
+        }
+
+        function getOneElement(what, where) {
+            return DomUtils.getElementsByTagName(what, where, true, 1)[0];
+        }
+
+        function fetch(what, where, recurse) {
+            return DomUtils.getText(
+                DomUtils.getElementsByTagName(what, where, recurse, 1)
+            ).trim();
+        }
+
+        function addConditionally(obj, prop, what, where, recurse) {
+            var tmp = fetch(what, where, recurse);
+            if (tmp) obj[prop] = tmp;
+        }
+
+        var isValidFeed = function (value) {
+            return value === "rss" || value === "feed" || value === "rdf:RDF";
+        };
+
+        FeedHandler.prototype.onend = function () {
+            var feed = {},
+                feedRoot = getOneElement(isValidFeed, this.dom),
+                tmp, childs;
+
+            if (feedRoot) {
+                if (feedRoot.name === "feed") {
+                    childs = feedRoot.children;
+
+                    feed.type = "atom";
+                    addConditionally(feed, "id", "id", childs);
+                    addConditionally(feed, "title", "title", childs);
+                    if ((tmp = getOneElement("link", childs)) && (tmp = tmp.attribs) && (tmp = tmp.href)) feed.link = tmp;
+                    addConditionally(feed, "description", "subtitle", childs);
+                    if ((tmp = fetch("updated", childs))) feed.updated = new Date(tmp);
+                    addConditionally(feed, "author", "email", childs, true);
+
+                    feed.items = getElements("entry", childs).map(function (item) {
+                        var entry = {}, tmp;
+
+                        item = item.children;
+
+                        addConditionally(entry, "id", "id", item);
+                        addConditionally(entry, "title", "title", item);
+                        if ((tmp = getOneElement("link", item)) && (tmp = tmp.attribs) && (tmp = tmp.href)) entry.link = tmp;
+                        if ((tmp = fetch("summary", item) || fetch("content", item))) entry.description = tmp;
+                        if ((tmp = fetch("updated", item))) entry.pubDate = new Date(tmp);
+                        return entry;
+                    });
+                } else {
+                    childs = getOneElement("channel", feedRoot.children).children;
+
+                    feed.type = feedRoot.name.substr(0, 3);
+                    feed.id = "";
+                    addConditionally(feed, "title", "title", childs);
+                    addConditionally(feed, "link", "link", childs);
+                    addConditionally(feed, "description", "description", childs);
+                    if ((tmp = fetch("lastBuildDate", childs))) feed.updated = new Date(tmp);
+                    addConditionally(feed, "author", "managingEditor", childs, true);
+
+                    feed.items = getElements("item", feedRoot.children).map(function (item) {
+                        var entry = {}, tmp;
+
+                        item = item.children;
+
+                        addConditionally(entry, "id", "guid", item);
+                        addConditionally(entry, "title", "title", item);
+                        addConditionally(entry, "link", "link", item);
+                        addConditionally(entry, "description", "description", item);
+                        if ((tmp = fetch("pubDate", item))) entry.pubDate = new Date(tmp);
+                        return entry;
+                    });
+                }
+            }
+            this.dom = feed;
+            DomHandler.prototype._handleCallback.call(
+                this, feedRoot ? null : Error("couldn't find root of feed")
+            );
+        };
+
+        module.exports = FeedHandler;
+
+    }, {"./index.js": 13, "util": 61}],
+    8: [function (require, module, exports) {
+        var Tokenizer = require("./Tokenizer.js");
+
+        /*
+	Options:
+
+	xmlMode: Disables the special behavior for script/style tags (false by default)
+	lowerCaseAttributeNames: call .toLowerCase for each attribute name (true if xmlMode is `false`)
+	lowerCaseTags: call .toLowerCase for each tag name (true if xmlMode is `false`)
+*/
+
+        /*
+	Callbacks:
+
+	oncdataend,
+	oncdatastart,
+	onclosetag,
+	oncomment,
+	oncommentend,
+	onerror,
+	onopentag,
+	onprocessinginstruction,
+	onreset,
+	ontext
+*/
+
+        var formTags = {
+            input: true,
+            option: true,
+            optgroup: true,
+            select: true,
+            button: true,
+            datalist: true,
+            textarea: true
+        };
+
+        var openImpliesClose = {
+            tr: {tr: true, th: true, td: true},
+            th: {th: true},
+            td: {thead: true, th: true, td: true},
+            body: {head: true, link: true, script: true},
+            li: {li: true},
+            p: {p: true},
+            h1: {p: true},
+            h2: {p: true},
+            h3: {p: true},
+            h4: {p: true},
+            h5: {p: true},
+            h6: {p: true},
+            select: formTags,
+            input: formTags,
+            output: formTags,
+            button: formTags,
+            datalist: formTags,
+            textarea: formTags,
+            option: {option: true},
+            optgroup: {optgroup: true}
+        };
+
+        var voidElements = {
+            __proto__: null,
+            area: true,
+            base: true,
+            basefont: true,
+            br: true,
+            col: true,
+            command: true,
+            embed: true,
+            frame: true,
+            hr: true,
+            img: true,
+            input: true,
+            isindex: true,
+            keygen: true,
+            link: true,
+            meta: true,
+            param: true,
+            source: true,
+            track: true,
+            wbr: true,
+
+            //common self closing svg elements
+            path: true,
+            circle: true,
+            ellipse: true,
+            line: true,
+            rect: true,
+            use: true,
+            stop: true,
+            polyline: true,
+            polygon: true
+        };
+
+        var re_nameEnd = /\s|\//;
+
+        function Parser(cbs, options) {
+            this._options = options || {};
+            this._cbs = cbs || {};
+
+            this._tagname = "";
+            this._attribname = "";
+            this._attribvalue = "";
+            this._attribs = null;
+            this._stack = [];
+
+            this.startIndex = 0;
+            this.endIndex = null;
+
+            this._lowerCaseTagNames = "lowerCaseTags" in this._options ?
+                !!this._options.lowerCaseTags :
+                !this._options.xmlMode;
+            this._lowerCaseAttributeNames = "lowerCaseAttributeNames" in this._options ?
+                !!this._options.lowerCaseAttributeNames :
+                !this._options.xmlMode;
+            if (!!this._options.Tokenizer) {
+                Tokenizer = this._options.Tokenizer;
+            }
+            this._tokenizer = new Tokenizer(this._options, this);
+
+            if (this._cbs.onparserinit) this._cbs.onparserinit(this);
+        }
+
+        require("util").inherits(Parser, require("events").EventEmitter);
+
+        Parser.prototype._updatePosition = function (initialOffset) {
+            if (this.endIndex === null) {
+                if (this._tokenizer._sectionStart <= initialOffset) {
+                    this.startIndex = 0;
+                } else {
+                    this.startIndex = this._tokenizer._sectionStart - initialOffset;
+                }
+            }
+            else this.startIndex = this.endIndex + 1;
+            this.endIndex = this._tokenizer.getAbsoluteIndex();
+        };
+
+//Tokenizer event handlers
+        Parser.prototype.ontext = function (data) {
+            this._updatePosition(1);
+            this.endIndex--;
+
+            if (this._cbs.ontext) this._cbs.ontext(data);
+        };
+
+        Parser.prototype.onopentagname = function (name) {
+            if (this._lowerCaseTagNames) {
+                name = name.toLowerCase();
+            }
+
+            this._tagname = name;
+
+            if (!this._options.xmlMode && name in openImpliesClose) {
+                for (
+                    var el;
+                    (el = this._stack[this._stack.length - 1]) in openImpliesClose[name];
+                    this.onclosetag(el)
+                ) ;
+            }
+
+            if (this._options.xmlMode || !(name in voidElements)) {
+                this._stack.push(name);
+            }
+
+            if (this._cbs.onopentagname) this._cbs.onopentagname(name);
+            if (this._cbs.onopentag) this._attribs = {};
+        };
+
+        Parser.prototype.onopentagend = function () {
+            this._updatePosition(1);
+
+            if (this._attribs) {
+                if (this._cbs.onopentag) this._cbs.onopentag(this._tagname, this._attribs);
+                this._attribs = null;
+            }
+
+            if (!this._options.xmlMode && this._cbs.onclosetag && this._tagname in voidElements) {
+                this._cbs.onclosetag(this._tagname);
+            }
+
+            this._tagname = "";
+        };
+
+        Parser.prototype.onclosetag = function (name) {
+            this._updatePosition(1);
+
+            if (this._lowerCaseTagNames) {
+                name = name.toLowerCase();
+            }
+
+            if (this._stack.length && (!(name in voidElements) || this._options.xmlMode)) {
+                var pos = this._stack.lastIndexOf(name);
+                if (pos !== -1) {
+                    if (this._cbs.onclosetag) {
+                        pos = this._stack.length - pos;
+                        while (pos--) this._cbs.onclosetag(this._stack.pop());
+                    }
+                    else this._stack.length = pos;
+                } else if (name === "p" && !this._options.xmlMode) {
+                    this.onopentagname(name);
+                    this._closeCurrentTag();
+                }
+            } else if (!this._options.xmlMode && (name === "br" || name === "p")) {
+                this.onopentagname(name);
+                this._closeCurrentTag();
+            }
+        };
+
+        Parser.prototype.onselfclosingtag = function () {
+            if (this._options.xmlMode || this._options.recognizeSelfClosing) {
+                this._closeCurrentTag();
+            } else {
+                this.onopentagend();
+            }
+        };
+
+        Parser.prototype._closeCurrentTag = function () {
+            var name = this._tagname;
+
+            this.onopentagend();
+
+            //self-closing tags will be on the top of the stack
+            //(cheaper check than in onclosetag)
+            if (this._stack[this._stack.length - 1] === name) {
+                if (this._cbs.onclosetag) {
+                    this._cbs.onclosetag(name);
+                }
+                this._stack.pop();
+            }
+        };
+
+        Parser.prototype.onattribname = function (name) {
+            if (this._lowerCaseAttributeNames) {
+                name = name.toLowerCase();
+            }
+            this._attribname = name;
+        };
+
+        Parser.prototype.onattribdata = function (value) {
+            this._attribvalue += value;
+        };
+
+        Parser.prototype.onattribend = function () {
+            if (this._cbs.onattribute) this._cbs.onattribute(this._attribname, this._attribvalue);
+            if (
+                this._attribs &&
+                !Object.prototype.hasOwnProperty.call(this._attribs, this._attribname)
+            ) {
+                this._attribs[this._attribname] = this._attribvalue;
+            }
+            this._attribname = "";
+            this._attribvalue = "";
+        };
+
+        Parser.prototype._getInstructionName = function (value) {
+            var idx = value.search(re_nameEnd),
+                name = idx < 0 ? value : value.substr(0, idx);
+
+            if (this._lowerCaseTagNames) {
+                name = name.toLowerCase();
+            }
+
+            return name;
+        };
+
+        Parser.prototype.ondeclaration = function (value) {
+            if (this._cbs.onprocessinginstruction) {
+                var name = this._getInstructionName(value);
+                this._cbs.onprocessinginstruction("!" + name, "!" + value);
+            }
+        };
+
+        Parser.prototype.onprocessinginstruction = function (value) {
+            if (this._cbs.onprocessinginstruction) {
+                var name = this._getInstructionName(value);
+                this._cbs.onprocessinginstruction("?" + name, "?" + value);
+            }
+        };
+
+        Parser.prototype.oncomment = function (value) {
+            this._updatePosition(4);
+
+            if (this._cbs.oncomment) this._cbs.oncomment(value);
+            if (this._cbs.oncommentend) this._cbs.oncommentend();
+        };
+
+        Parser.prototype.oncdata = function (value) {
+            this._updatePosition(1);
+
+            if (this._options.xmlMode || this._options.recognizeCDATA) {
+                if (this._cbs.oncdatastart) this._cbs.oncdatastart();
+                if (this._cbs.ontext) this._cbs.ontext(value);
+                if (this._cbs.oncdataend) this._cbs.oncdataend();
+            } else {
+                this.oncomment("[CDATA[" + value + "]]");
+            }
+        };
+
+        Parser.prototype.onerror = function (err) {
+            if (this._cbs.onerror) this._cbs.onerror(err);
+        };
+
+        Parser.prototype.onend = function () {
+            if (this._cbs.onclosetag) {
+                for (
+                    var i = this._stack.length;
+                    i > 0;
+                    this._cbs.onclosetag(this._stack[--i])
+                ) ;
+            }
+            if (this._cbs.onend) this._cbs.onend();
+        };
+
+
+//Resets the parser to a blank state, ready to parse a new HTML document
+        Parser.prototype.reset = function () {
+            if (this._cbs.onreset) this._cbs.onreset();
+            this._tokenizer.reset();
+
+            this._tagname = "";
+            this._attribname = "";
+            this._attribs = null;
+            this._stack = [];
+
+            if (this._cbs.onparserinit) this._cbs.onparserinit(this);
+        };
+
+//Parses a complete HTML document and pushes it to the handler
+        Parser.prototype.parseComplete = function (data) {
+            this.reset();
+            this.end(data);
+        };
+
+        Parser.prototype.write = function (chunk) {
+            this._tokenizer.write(chunk);
+        };
+
+        Parser.prototype.end = function (chunk) {
+            this._tokenizer.end(chunk);
+        };
+
+        Parser.prototype.pause = function () {
+            this._tokenizer.pause();
+        };
+
+        Parser.prototype.resume = function () {
+            this._tokenizer.resume();
+        };
+
+//alias for backwards compat
+        Parser.prototype.parseChunk = Parser.prototype.write;
+        Parser.prototype.done = Parser.prototype.end;
+
+        module.exports = Parser;
+
+    }, {"./Tokenizer.js": 11, "events": 40, "util": 61}],
+    9: [function (require, module, exports) {
+        module.exports = ProxyHandler;
+
+        function ProxyHandler(cbs) {
+            this._cbs = cbs || {};
+        }
+
+        var EVENTS = require("./").EVENTS;
+        Object.keys(EVENTS).forEach(function (name) {
+            if (EVENTS[name] === 0) {
+                name = "on" + name;
+                ProxyHandler.prototype[name] = function () {
+                    if (this._cbs[name]) this._cbs[name]();
+                };
+            } else if (EVENTS[name] === 1) {
+                name = "on" + name;
+                ProxyHandler.prototype[name] = function (a) {
+                    if (this._cbs[name]) this._cbs[name](a);
+                };
+            } else if (EVENTS[name] === 2) {
+                name = "on" + name;
+                ProxyHandler.prototype[name] = function (a, b) {
+                    if (this._cbs[name]) this._cbs[name](a, b);
+                };
+            } else {
+                throw Error("wrong number of arguments");
+            }
+        });
+    }, {"./": 13}],
+    10: [function (require, module, exports) {
+        module.exports = Stream;
+
+        var Parser = require("./WritableStream.js");
+
+        function Stream(options) {
+            Parser.call(this, new Cbs(this), options);
+        }
+
+        require("util").inherits(Stream, Parser);
+
+        Stream.prototype.readable = true;
+
+        function Cbs(scope) {
+            this.scope = scope;
+        }
+
+        var EVENTS = require("../").EVENTS;
+
+        Object.keys(EVENTS).forEach(function (name) {
+            if (EVENTS[name] === 0) {
+                Cbs.prototype["on" + name] = function () {
+                    this.scope.emit(name);
+                };
+            } else if (EVENTS[name] === 1) {
+                Cbs.prototype["on" + name] = function (a) {
+                    this.scope.emit(name, a);
+                };
+            } else if (EVENTS[name] === 2) {
+                Cbs.prototype["on" + name] = function (a, b) {
+                    this.scope.emit(name, a, b);
+                };
+            } else {
+                throw Error("wrong number of arguments!");
+            }
+        });
+    }, {"../": 13, "./WritableStream.js": 12, "util": 61}],
+    11: [function (require, module, exports) {
+        module.exports = Tokenizer;
+
+        var decodeCodePoint = require("entities/lib/decode_codepoint.js"),
+            entityMap = require("entities/maps/entities.json"),
+            legacyMap = require("entities/maps/legacy.json"),
+            xmlMap = require("entities/maps/xml.json"),
+
+            i = 0,
+
+            TEXT = i++,
+            BEFORE_TAG_NAME = i++, //after <
+            IN_TAG_NAME = i++,
+            IN_SELF_CLOSING_TAG = i++,
+            BEFORE_CLOSING_TAG_NAME = i++,
+            IN_CLOSING_TAG_NAME = i++,
+            AFTER_CLOSING_TAG_NAME = i++,
+
+            //attributes
+            BEFORE_ATTRIBUTE_NAME = i++,
+            IN_ATTRIBUTE_NAME = i++,
+            AFTER_ATTRIBUTE_NAME = i++,
+            BEFORE_ATTRIBUTE_VALUE = i++,
+            IN_ATTRIBUTE_VALUE_DQ = i++, // "
+            IN_ATTRIBUTE_VALUE_SQ = i++, // '
+            IN_ATTRIBUTE_VALUE_NQ = i++,
+
+            //declarations
+            BEFORE_DECLARATION = i++, // !
+            IN_DECLARATION = i++,
+
+            //processing instructions
+            IN_PROCESSING_INSTRUCTION = i++, // ?
+
+            //comments
+            BEFORE_COMMENT = i++,
+            IN_COMMENT = i++,
+            AFTER_COMMENT_1 = i++,
+            AFTER_COMMENT_2 = i++,
+
+            //cdata
+            BEFORE_CDATA_1 = i++, // [
+            BEFORE_CDATA_2 = i++, // C
+            BEFORE_CDATA_3 = i++, // D
+            BEFORE_CDATA_4 = i++, // A
+            BEFORE_CDATA_5 = i++, // T
+            BEFORE_CDATA_6 = i++, // A
+            IN_CDATA = i++, // [
+            AFTER_CDATA_1 = i++, // ]
+            AFTER_CDATA_2 = i++, // ]
+
+            //special tags
+            BEFORE_SPECIAL = i++, //S
+            BEFORE_SPECIAL_END = i++,   //S
+
+            BEFORE_SCRIPT_1 = i++, //C
+            BEFORE_SCRIPT_2 = i++, //R
+            BEFORE_SCRIPT_3 = i++, //I
+            BEFORE_SCRIPT_4 = i++, //P
+            BEFORE_SCRIPT_5 = i++, //T
+            AFTER_SCRIPT_1 = i++, //C
+            AFTER_SCRIPT_2 = i++, //R
+            AFTER_SCRIPT_3 = i++, //I
+            AFTER_SCRIPT_4 = i++, //P
+            AFTER_SCRIPT_5 = i++, //T
+
+            BEFORE_STYLE_1 = i++, //T
+            BEFORE_STYLE_2 = i++, //Y
+            BEFORE_STYLE_3 = i++, //L
+            BEFORE_STYLE_4 = i++, //E
+            AFTER_STYLE_1 = i++, //T
+            AFTER_STYLE_2 = i++, //Y
+            AFTER_STYLE_3 = i++, //L
+            AFTER_STYLE_4 = i++, //E
+
+            BEFORE_ENTITY = i++, //&
+            BEFORE_NUMERIC_ENTITY = i++, //#
+            IN_NAMED_ENTITY = i++,
+            IN_NUMERIC_ENTITY = i++,
+            IN_HEX_ENTITY = i++, //X
+
+            j = 0,
+
+            SPECIAL_NONE = j++,
+            SPECIAL_SCRIPT = j++,
+            SPECIAL_STYLE = j++;
+
+        function whitespace(c) {
+            return c === " " || c === "\n" || c === "\t" || c === "\f" || c === "\r";
+        }
+
+        function characterState(char, SUCCESS) {
+            return function (c) {
+                if (c === char) this._state = SUCCESS;
+            };
+        }
+
+        function ifElseState(upper, SUCCESS, FAILURE) {
+            var lower = upper.toLowerCase();
+
+            if (upper === lower) {
+                return function (c) {
+                    if (c === lower) {
+                        this._state = SUCCESS;
+                    } else {
+                        this._state = FAILURE;
+                        this._index--;
+                    }
+                };
+            } else {
+                return function (c) {
+                    if (c === lower || c === upper) {
+                        this._state = SUCCESS;
+                    } else {
+                        this._state = FAILURE;
+                        this._index--;
+                    }
+                };
+            }
+        }
+
+        function consumeSpecialNameChar(upper, NEXT_STATE) {
+            var lower = upper.toLowerCase();
+
+            return function (c) {
+                if (c === lower || c === upper) {
+                    this._state = NEXT_STATE;
+                } else {
+                    this._state = IN_TAG_NAME;
+                    this._index--; //consume the token again
+                }
+            };
+        }
+
+        function Tokenizer(options, cbs) {
+            this._state = TEXT;
+            this._buffer = "";
+            this._sectionStart = 0;
+            this._index = 0;
+            this._bufferOffset = 0; //chars removed from _buffer
+            this._baseState = TEXT;
+            this._special = SPECIAL_NONE;
+            this._cbs = cbs;
+            this._running = true;
+            this._ended = false;
+            this._xmlMode = !!(options && options.xmlMode);
+            this._decodeEntities = !!(options && options.decodeEntities);
+        }
+
+        Tokenizer.prototype._stateText = function (c) {
+            if (c === "<") {
+                if (this._index > this._sectionStart) {
+                    this._cbs.ontext(this._getSection());
+                }
+                this._state = BEFORE_TAG_NAME;
+                this._sectionStart = this._index;
+            } else if (this._decodeEntities && this._special === SPECIAL_NONE && c === "&") {
+                if (this._index > this._sectionStart) {
+                    this._cbs.ontext(this._getSection());
+                }
+                this._baseState = TEXT;
+                this._state = BEFORE_ENTITY;
+                this._sectionStart = this._index;
+            }
+        };
+
+        Tokenizer.prototype._stateBeforeTagName = function (c) {
+            if (c === "/") {
+                this._state = BEFORE_CLOSING_TAG_NAME;
+            } else if (c === ">" || this._special !== SPECIAL_NONE || whitespace(c)) {
+                this._state = TEXT;
+            } else if (c === "!") {
+                this._state = BEFORE_DECLARATION;
+                this._sectionStart = this._index + 1;
+            } else if (c === "?") {
+                this._state = IN_PROCESSING_INSTRUCTION;
+                this._sectionStart = this._index + 1;
+            } else if (c === "<") {
+                this._cbs.ontext(this._getSection());
+                this._sectionStart = this._index;
+            } else {
+                this._state = (!this._xmlMode && (c === "s" || c === "S")) ?
+                    BEFORE_SPECIAL : IN_TAG_NAME;
+                this._sectionStart = this._index;
+            }
+        };
+
+        Tokenizer.prototype._stateInTagName = function (c) {
+            if (c === "/" || c === ">" || whitespace(c)) {
+                this._emitToken("onopentagname");
+                this._state = BEFORE_ATTRIBUTE_NAME;
+                this._index--;
+            }
+        };
+
+        Tokenizer.prototype._stateBeforeCloseingTagName = function (c) {
+            if (whitespace(c)) ;
+            else if (c === ">") {
+                this._state = TEXT;
+            } else if (this._special !== SPECIAL_NONE) {
+                if (c === "s" || c === "S") {
+                    this._state = BEFORE_SPECIAL_END;
+                } else {
+                    this._state = TEXT;
+                    this._index--;
+                }
+            } else {
+                this._state = IN_CLOSING_TAG_NAME;
+                this._sectionStart = this._index;
+            }
+        };
+
+        Tokenizer.prototype._stateInCloseingTagName = function (c) {
+            if (c === ">" || whitespace(c)) {
+                this._emitToken("onclosetag");
+                this._state = AFTER_CLOSING_TAG_NAME;
+                this._index--;
+            }
+        };
+
+        Tokenizer.prototype._stateAfterCloseingTagName = function (c) {
+            //skip everything until ">"
+            if (c === ">") {
+                this._state = TEXT;
+                this._sectionStart = this._index + 1;
+            }
+        };
+
+        Tokenizer.prototype._stateBeforeAttributeName = function (c) {
+            if (c === ">") {
+                this._cbs.onopentagend();
+                this._state = TEXT;
+                this._sectionStart = this._index + 1;
+            } else if (c === "/") {
+                this._state = IN_SELF_CLOSING_TAG;
+            } else if (!whitespace(c)) {
+                this._state = IN_ATTRIBUTE_NAME;
+                this._sectionStart = this._index;
+            }
+        };
+
+        Tokenizer.prototype._stateInSelfClosingTag = function (c) {
+            if (c === ">") {
+                this._cbs.onselfclosingtag();
+                this._state = TEXT;
+                this._sectionStart = this._index + 1;
+            } else if (!whitespace(c)) {
+                this._state = BEFORE_ATTRIBUTE_NAME;
+                this._index--;
+            }
+        };
+
+        Tokenizer.prototype._stateInAttributeName = function (c) {
+            if (c === "=" || c === "/" || c === ">" || whitespace(c)) {
+                this._cbs.onattribname(this._getSection());
+                this._sectionStart = -1;
+                this._state = AFTER_ATTRIBUTE_NAME;
+                this._index--;
+            }
+        };
+
+        Tokenizer.prototype._stateAfterAttributeName = function (c) {
+            if (c === "=") {
+                this._state = BEFORE_ATTRIBUTE_VALUE;
+            } else if (c === "/" || c === ">") {
+                this._cbs.onattribend();
+                this._state = BEFORE_ATTRIBUTE_NAME;
+                this._index--;
+            } else if (!whitespace(c)) {
+                this._cbs.onattribend();
+                this._state = IN_ATTRIBUTE_NAME;
+                this._sectionStart = this._index;
+            }
+        };
+
+        Tokenizer.prototype._stateBeforeAttributeValue = function (c) {
+            if (c === "\"") {
+                this._state = IN_ATTRIBUTE_VALUE_DQ;
+                this._sectionStart = this._index + 1;
+            } else if (c === "'") {
+                this._state = IN_ATTRIBUTE_VALUE_SQ;
+                this._sectionStart = this._index + 1;
+            } else if (!whitespace(c)) {
+                this._state = IN_ATTRIBUTE_VALUE_NQ;
+                this._sectionStart = this._index;
+                this._index--; //reconsume token
+            }
+        };
+
+        Tokenizer.prototype._stateInAttributeValueDoubleQuotes = function (c) {
+            if (c === "\"") {
+                this._emitToken("onattribdata");
+                this._cbs.onattribend();
+                this._state = BEFORE_ATTRIBUTE_NAME;
+            } else if (this._decodeEntities && c === "&") {
+                this._emitToken("onattribdata");
+                this._baseState = this._state;
+                this._state = BEFORE_ENTITY;
+                this._sectionStart = this._index;
+            }
+        };
+
+        Tokenizer.prototype._stateInAttributeValueSingleQuotes = function (c) {
+            if (c === "'") {
+                this._emitToken("onattribdata");
+                this._cbs.onattribend();
+                this._state = BEFORE_ATTRIBUTE_NAME;
+            } else if (this._decodeEntities && c === "&") {
+                this._emitToken("onattribdata");
+                this._baseState = this._state;
+                this._state = BEFORE_ENTITY;
+                this._sectionStart = this._index;
+            }
+        };
+
+        Tokenizer.prototype._stateInAttributeValueNoQuotes = function (c) {
+            if (whitespace(c) || c === ">") {
+                this._emitToken("onattribdata");
+                this._cbs.onattribend();
+                this._state = BEFORE_ATTRIBUTE_NAME;
+                this._index--;
+            } else if (this._decodeEntities && c === "&") {
+                this._emitToken("onattribdata");
+                this._baseState = this._state;
+                this._state = BEFORE_ENTITY;
+                this._sectionStart = this._index;
+            }
+        };
+
+        Tokenizer.prototype._stateBeforeDeclaration = function (c) {
+            this._state = c === "[" ? BEFORE_CDATA_1 :
+                c === "-" ? BEFORE_COMMENT :
+                    IN_DECLARATION;
+        };
+
+        Tokenizer.prototype._stateInDeclaration = function (c) {
+            if (c === ">") {
+                this._cbs.ondeclaration(this._getSection());
+                this._state = TEXT;
+                this._sectionStart = this._index + 1;
+            }
+        };
+
+        Tokenizer.prototype._stateInProcessingInstruction = function (c) {
+            if (c === ">") {
+                this._cbs.onprocessinginstruction(this._getSection());
+                this._state = TEXT;
+                this._sectionStart = this._index + 1;
+            }
+        };
+
+        Tokenizer.prototype._stateBeforeComment = function (c) {
+            if (c === "-") {
+                this._state = IN_COMMENT;
+                this._sectionStart = this._index + 1;
+            } else {
+                this._state = IN_DECLARATION;
+            }
+        };
+
+        Tokenizer.prototype._stateInComment = function (c) {
+            if (c === "-") this._state = AFTER_COMMENT_1;
+        };
+
+        Tokenizer.prototype._stateAfterComment1 = function (c) {
+            if (c === "-") {
+                this._state = AFTER_COMMENT_2;
+            } else {
+                this._state = IN_COMMENT;
+            }
+        };
+
+        Tokenizer.prototype._stateAfterComment2 = function (c) {
+            if (c === ">") {
+                //remove 2 trailing chars
+                this._cbs.oncomment(this._buffer.substring(this._sectionStart, this._index - 2));
+                this._state = TEXT;
+                this._sectionStart = this._index + 1;
+            } else if (c !== "-") {
+                this._state = IN_COMMENT;
+            }
+            // else: stay in AFTER_COMMENT_2 (`--->`)
+        };
+
+        Tokenizer.prototype._stateBeforeCdata1 = ifElseState("C", BEFORE_CDATA_2, IN_DECLARATION);
+        Tokenizer.prototype._stateBeforeCdata2 = ifElseState("D", BEFORE_CDATA_3, IN_DECLARATION);
+        Tokenizer.prototype._stateBeforeCdata3 = ifElseState("A", BEFORE_CDATA_4, IN_DECLARATION);
+        Tokenizer.prototype._stateBeforeCdata4 = ifElseState("T", BEFORE_CDATA_5, IN_DECLARATION);
+        Tokenizer.prototype._stateBeforeCdata5 = ifElseState("A", BEFORE_CDATA_6, IN_DECLARATION);
+
+        Tokenizer.prototype._stateBeforeCdata6 = function (c) {
+            if (c === "[") {
+                this._state = IN_CDATA;
+                this._sectionStart = this._index + 1;
+            } else {
+                this._state = IN_DECLARATION;
+                this._index--;
+            }
+        };
+
+        Tokenizer.prototype._stateInCdata = function (c) {
+            if (c === "]") this._state = AFTER_CDATA_1;
+        };
+
+        Tokenizer.prototype._stateAfterCdata1 = characterState("]", AFTER_CDATA_2);
+
+        Tokenizer.prototype._stateAfterCdata2 = function (c) {
+            if (c === ">") {
+                //remove 2 trailing chars
+                this._cbs.oncdata(this._buffer.substring(this._sectionStart, this._index - 2));
+                this._state = TEXT;
+                this._sectionStart = this._index + 1;
+            } else if (c !== "]") {
+                this._state = IN_CDATA;
+            }
+            //else: stay in AFTER_CDATA_2 (`]]]>`)
+        };
+
+        Tokenizer.prototype._stateBeforeSpecial = function (c) {
+            if (c === "c" || c === "C") {
+                this._state = BEFORE_SCRIPT_1;
+            } else if (c === "t" || c === "T") {
+                this._state = BEFORE_STYLE_1;
+            } else {
+                this._state = IN_TAG_NAME;
+                this._index--; //consume the token again
+            }
+        };
+
+        Tokenizer.prototype._stateBeforeSpecialEnd = function (c) {
+            if (this._special === SPECIAL_SCRIPT && (c === "c" || c === "C")) {
+                this._state = AFTER_SCRIPT_1;
+            } else if (this._special === SPECIAL_STYLE && (c === "t" || c === "T")) {
+                this._state = AFTER_STYLE_1;
+            }
+            else this._state = TEXT;
+        };
+
+        Tokenizer.prototype._stateBeforeScript1 = consumeSpecialNameChar("R", BEFORE_SCRIPT_2);
+        Tokenizer.prototype._stateBeforeScript2 = consumeSpecialNameChar("I", BEFORE_SCRIPT_3);
+        Tokenizer.prototype._stateBeforeScript3 = consumeSpecialNameChar("P", BEFORE_SCRIPT_4);
+        Tokenizer.prototype._stateBeforeScript4 = consumeSpecialNameChar("T", BEFORE_SCRIPT_5);
+
+        Tokenizer.prototype._stateBeforeScript5 = function (c) {
+            if (c === "/" || c === ">" || whitespace(c)) {
+                this._special = SPECIAL_SCRIPT;
+            }
+            this._state = IN_TAG_NAME;
+            this._index--; //consume the token again
+        };
+
+        Tokenizer.prototype._stateAfterScript1 = ifElseState("R", AFTER_SCRIPT_2, TEXT);
+        Tokenizer.prototype._stateAfterScript2 = ifElseState("I", AFTER_SCRIPT_3, TEXT);
+        Tokenizer.prototype._stateAfterScript3 = ifElseState("P", AFTER_SCRIPT_4, TEXT);
+        Tokenizer.prototype._stateAfterScript4 = ifElseState("T", AFTER_SCRIPT_5, TEXT);
+
+        Tokenizer.prototype._stateAfterScript5 = function (c) {
+            if (c === ">" || whitespace(c)) {
+                this._special = SPECIAL_NONE;
+                this._state = IN_CLOSING_TAG_NAME;
+                this._sectionStart = this._index - 6;
+                this._index--; //reconsume the token
+            }
+            else this._state = TEXT;
+        };
+
+        Tokenizer.prototype._stateBeforeStyle1 = consumeSpecialNameChar("Y", BEFORE_STYLE_2);
+        Tokenizer.prototype._stateBeforeStyle2 = consumeSpecialNameChar("L", BEFORE_STYLE_3);
+        Tokenizer.prototype._stateBeforeStyle3 = consumeSpecialNameChar("E", BEFORE_STYLE_4);
+
+        Tokenizer.prototype._stateBeforeStyle4 = function (c) {
+            if (c === "/" || c === ">" || whitespace(c)) {
+                this._special = SPECIAL_STYLE;
+            }
+            this._state = IN_TAG_NAME;
+            this._index--; //consume the token again
+        };
+
+        Tokenizer.prototype._stateAfterStyle1 = ifElseState("Y", AFTER_STYLE_2, TEXT);
+        Tokenizer.prototype._stateAfterStyle2 = ifElseState("L", AFTER_STYLE_3, TEXT);
+        Tokenizer.prototype._stateAfterStyle3 = ifElseState("E", AFTER_STYLE_4, TEXT);
+
+        Tokenizer.prototype._stateAfterStyle4 = function (c) {
+            if (c === ">" || whitespace(c)) {
+                this._special = SPECIAL_NONE;
+                this._state = IN_CLOSING_TAG_NAME;
+                this._sectionStart = this._index - 5;
+                this._index--; //reconsume the token
+            }
+            else this._state = TEXT;
+        };
+
+        Tokenizer.prototype._stateBeforeEntity = ifElseState("#", BEFORE_NUMERIC_ENTITY, IN_NAMED_ENTITY);
+        Tokenizer.prototype._stateBeforeNumericEntity = ifElseState("X", IN_HEX_ENTITY, IN_NUMERIC_ENTITY);
+
+//for entities terminated with a semicolon
+        Tokenizer.prototype._parseNamedEntityStrict = function () {
+            //offset = 1
+            if (this._sectionStart + 1 < this._index) {
+                var entity = this._buffer.substring(this._sectionStart + 1, this._index),
+                    map = this._xmlMode ? xmlMap : entityMap;
+
+                if (map.hasOwnProperty(entity)) {
+                    this._emitPartial(map[entity]);
+                    this._sectionStart = this._index + 1;
+                }
+            }
+        };
+
+
+//parses legacy entities (without trailing semicolon)
+        Tokenizer.prototype._parseLegacyEntity = function () {
+            var start = this._sectionStart + 1,
+                limit = this._index - start;
+
+            if (limit > 6) limit = 6; //the max length of legacy entities is 6
+
+            while (limit >= 2) { //the min length of legacy entities is 2
+                var entity = this._buffer.substr(start, limit);
+
+                if (legacyMap.hasOwnProperty(entity)) {
+                    this._emitPartial(legacyMap[entity]);
+                    this._sectionStart += limit + 1;
+                    return;
+                } else {
+                    limit--;
+                }
+            }
+        };
+
+        Tokenizer.prototype._stateInNamedEntity = function (c) {
+            if (c === ";") {
+                this._parseNamedEntityStrict();
+                if (this._sectionStart + 1 < this._index && !this._xmlMode) {
+                    this._parseLegacyEntity();
+                }
+                this._state = this._baseState;
+            } else if ((c < "a" || c > "z") && (c < "A" || c > "Z") && (c < "0" || c > "9")) {
+                if (this._xmlMode) ;
+                else if (this._sectionStart + 1 === this._index) ;
+                else if (this._baseState !== TEXT) {
+                    if (c !== "=") {
+                        this._parseNamedEntityStrict();
+                    }
+                } else {
+                    this._parseLegacyEntity();
+                }
+
+                this._state = this._baseState;
+                this._index--;
+            }
+        };
+
+        Tokenizer.prototype._decodeNumericEntity = function (offset, base) {
+            var sectionStart = this._sectionStart + offset;
+
+            if (sectionStart !== this._index) {
+                //parse entity
+                var entity = this._buffer.substring(sectionStart, this._index);
+                var parsed = parseInt(entity, base);
+
+                this._emitPartial(decodeCodePoint(parsed));
+                this._sectionStart = this._index;
+            } else {
+                this._sectionStart--;
+            }
+
+            this._state = this._baseState;
+        };
+
+        Tokenizer.prototype._stateInNumericEntity = function (c) {
+            if (c === ";") {
+                this._decodeNumericEntity(2, 10);
+                this._sectionStart++;
+            } else if (c < "0" || c > "9") {
+                if (!this._xmlMode) {
+                    this._decodeNumericEntity(2, 10);
+                } else {
+                    this._state = this._baseState;
+                }
+                this._index--;
+            }
+        };
+
+        Tokenizer.prototype._stateInHexEntity = function (c) {
+            if (c === ";") {
+                this._decodeNumericEntity(3, 16);
+                this._sectionStart++;
+            } else if ((c < "a" || c > "f") && (c < "A" || c > "F") && (c < "0" || c > "9")) {
+                if (!this._xmlMode) {
+                    this._decodeNumericEntity(3, 16);
+                } else {
+                    this._state = this._baseState;
+                }
+                this._index--;
+            }
+        };
+
+        Tokenizer.prototype._cleanup = function () {
+            if (this._sectionStart < 0) {
+                this._buffer = "";
+                this._index = 0;
+                this._bufferOffset += this._index;
+            } else if (this._running) {
+                if (this._state === TEXT) {
+                    if (this._sectionStart !== this._index) {
+                        this._cbs.ontext(this._buffer.substr(this._sectionStart));
+                    }
+                    this._buffer = "";
+                    this._index = 0;
+                    this._bufferOffset += this._index;
+                } else if (this._sectionStart === this._index) {
+                    //the section just started
+                    this._buffer = "";
+                    this._index = 0;
+                    this._bufferOffset += this._index;
+                } else {
+                    //remove everything unnecessary
+                    this._buffer = this._buffer.substr(this._sectionStart);
+                    this._index -= this._sectionStart;
+                    this._bufferOffset += this._sectionStart;
+                }
+
+                this._sectionStart = 0;
+            }
+        };
+
+//TODO make events conditional
+        Tokenizer.prototype.write = function (chunk) {
+            if (this._ended) this._cbs.onerror(Error(".write() after done!"));
+
+            this._buffer += chunk;
+            this._parse();
+        };
+
+        Tokenizer.prototype._parse = function () {
+            while (this._index < this._buffer.length && this._running) {
+                var c = this._buffer.charAt(this._index);
+                if (this._state === TEXT) {
+                    this._stateText(c);
+                } else if (this._state === BEFORE_TAG_NAME) {
+                    this._stateBeforeTagName(c);
+                } else if (this._state === IN_TAG_NAME) {
+                    this._stateInTagName(c);
+                } else if (this._state === BEFORE_CLOSING_TAG_NAME) {
+                    this._stateBeforeCloseingTagName(c);
+                } else if (this._state === IN_CLOSING_TAG_NAME) {
+                    this._stateInCloseingTagName(c);
+                } else if (this._state === AFTER_CLOSING_TAG_NAME) {
+                    this._stateAfterCloseingTagName(c);
+                } else if (this._state === IN_SELF_CLOSING_TAG) {
+                    this._stateInSelfClosingTag(c);
+                }
+
+                /*
+		*	attributes
+		*/
+                else if (this._state === BEFORE_ATTRIBUTE_NAME) {
+                    this._stateBeforeAttributeName(c);
+                } else if (this._state === IN_ATTRIBUTE_NAME) {
+                    this._stateInAttributeName(c);
+                } else if (this._state === AFTER_ATTRIBUTE_NAME) {
+                    this._stateAfterAttributeName(c);
+                } else if (this._state === BEFORE_ATTRIBUTE_VALUE) {
+                    this._stateBeforeAttributeValue(c);
+                } else if (this._state === IN_ATTRIBUTE_VALUE_DQ) {
+                    this._stateInAttributeValueDoubleQuotes(c);
+                } else if (this._state === IN_ATTRIBUTE_VALUE_SQ) {
+                    this._stateInAttributeValueSingleQuotes(c);
+                } else if (this._state === IN_ATTRIBUTE_VALUE_NQ) {
+                    this._stateInAttributeValueNoQuotes(c);
+                }
+
+                /*
+		*	declarations
+		*/
+                else if (this._state === BEFORE_DECLARATION) {
+                    this._stateBeforeDeclaration(c);
+                } else if (this._state === IN_DECLARATION) {
+                    this._stateInDeclaration(c);
+                }
+
+                /*
+		*	processing instructions
+		*/
+                else if (this._state === IN_PROCESSING_INSTRUCTION) {
+                    this._stateInProcessingInstruction(c);
+                }
+
+                /*
+		*	comments
+		*/
+                else if (this._state === BEFORE_COMMENT) {
+                    this._stateBeforeComment(c);
+                } else if (this._state === IN_COMMENT) {
+                    this._stateInComment(c);
+                } else if (this._state === AFTER_COMMENT_1) {
+                    this._stateAfterComment1(c);
+                } else if (this._state === AFTER_COMMENT_2) {
+                    this._stateAfterComment2(c);
+                }
+
+                /*
+		*	cdata
+		*/
+                else if (this._state === BEFORE_CDATA_1) {
+                    this._stateBeforeCdata1(c);
+                } else if (this._state === BEFORE_CDATA_2) {
+                    this._stateBeforeCdata2(c);
+                } else if (this._state === BEFORE_CDATA_3) {
+                    this._stateBeforeCdata3(c);
+                } else if (this._state === BEFORE_CDATA_4) {
+                    this._stateBeforeCdata4(c);
+                } else if (this._state === BEFORE_CDATA_5) {
+                    this._stateBeforeCdata5(c);
+                } else if (this._state === BEFORE_CDATA_6) {
+                    this._stateBeforeCdata6(c);
+                } else if (this._state === IN_CDATA) {
+                    this._stateInCdata(c);
+                } else if (this._state === AFTER_CDATA_1) {
+                    this._stateAfterCdata1(c);
+                } else if (this._state === AFTER_CDATA_2) {
+                    this._stateAfterCdata2(c);
+                }
+
+                /*
+		* special tags
+		*/
+                else if (this._state === BEFORE_SPECIAL) {
+                    this._stateBeforeSpecial(c);
+                } else if (this._state === BEFORE_SPECIAL_END) {
+                    this._stateBeforeSpecialEnd(c);
+                }
+
+                /*
+		* script
+		*/
+                else if (this._state === BEFORE_SCRIPT_1) {
+                    this._stateBeforeScript1(c);
+                } else if (this._state === BEFORE_SCRIPT_2) {
+                    this._stateBeforeScript2(c);
+                } else if (this._state === BEFORE_SCRIPT_3) {
+                    this._stateBeforeScript3(c);
+                } else if (this._state === BEFORE_SCRIPT_4) {
+                    this._stateBeforeScript4(c);
+                } else if (this._state === BEFORE_SCRIPT_5) {
+                    this._stateBeforeScript5(c);
+                }
+
+                else if (this._state === AFTER_SCRIPT_1) {
+                    this._stateAfterScript1(c);
+                } else if (this._state === AFTER_SCRIPT_2) {
+                    this._stateAfterScript2(c);
+                } else if (this._state === AFTER_SCRIPT_3) {
+                    this._stateAfterScript3(c);
+                } else if (this._state === AFTER_SCRIPT_4) {
+                    this._stateAfterScript4(c);
+                } else if (this._state === AFTER_SCRIPT_5) {
+                    this._stateAfterScript5(c);
+                }
+
+                /*
+		* style
+		*/
+                else if (this._state === BEFORE_STYLE_1) {
+                    this._stateBeforeStyle1(c);
+                } else if (this._state === BEFORE_STYLE_2) {
+                    this._stateBeforeStyle2(c);
+                } else if (this._state === BEFORE_STYLE_3) {
+                    this._stateBeforeStyle3(c);
+                } else if (this._state === BEFORE_STYLE_4) {
+                    this._stateBeforeStyle4(c);
+                }
+
+                else if (this._state === AFTER_STYLE_1) {
+                    this._stateAfterStyle1(c);
+                } else if (this._state === AFTER_STYLE_2) {
+                    this._stateAfterStyle2(c);
+                } else if (this._state === AFTER_STYLE_3) {
+                    this._stateAfterStyle3(c);
+                } else if (this._state === AFTER_STYLE_4) {
+                    this._stateAfterStyle4(c);
+                }
+
+                /*
+		* entities
+		*/
+                else if (this._state === BEFORE_ENTITY) {
+                    this._stateBeforeEntity(c);
+                } else if (this._state === BEFORE_NUMERIC_ENTITY) {
+                    this._stateBeforeNumericEntity(c);
+                } else if (this._state === IN_NAMED_ENTITY) {
+                    this._stateInNamedEntity(c);
+                } else if (this._state === IN_NUMERIC_ENTITY) {
+                    this._stateInNumericEntity(c);
+                } else if (this._state === IN_HEX_ENTITY) {
+                    this._stateInHexEntity(c);
+                }
+
+                else {
+                    this._cbs.onerror(Error("unknown _state"), this._state);
+                }
+
+                this._index++;
+            }
+
+            this._cleanup();
+        };
+
+        Tokenizer.prototype.pause = function () {
+            this._running = false;
+        };
+        Tokenizer.prototype.resume = function () {
+            this._running = true;
+
+            if (this._index < this._buffer.length) {
+                this._parse();
+            }
+            if (this._ended) {
+                this._finish();
+            }
+        };
+
+        Tokenizer.prototype.end = function (chunk) {
+            if (this._ended) this._cbs.onerror(Error(".end() after done!"));
+            if (chunk) this.write(chunk);
+
+            this._ended = true;
+
+            if (this._running) this._finish();
+        };
+
+        Tokenizer.prototype._finish = function () {
+            //if there is remaining data, emit it in a reasonable way
+            if (this._sectionStart < this._index) {
+                this._handleTrailingData();
+            }
+
+            this._cbs.onend();
+        };
+
+        Tokenizer.prototype._handleTrailingData = function () {
+            var data = this._buffer.substr(this._sectionStart);
+
+            if (this._state === IN_CDATA || this._state === AFTER_CDATA_1 || this._state === AFTER_CDATA_2) {
+                this._cbs.oncdata(data);
+            } else if (this._state === IN_COMMENT || this._state === AFTER_COMMENT_1 || this._state === AFTER_COMMENT_2) {
+                this._cbs.oncomment(data);
+            } else if (this._state === IN_NAMED_ENTITY && !this._xmlMode) {
+                this._parseLegacyEntity();
+                if (this._sectionStart < this._index) {
+                    this._state = this._baseState;
+                    this._handleTrailingData();
+                }
+            } else if (this._state === IN_NUMERIC_ENTITY && !this._xmlMode) {
+                this._decodeNumericEntity(2, 10);
+                if (this._sectionStart < this._index) {
+                    this._state = this._baseState;
+                    this._handleTrailingData();
+                }
+            } else if (this._state === IN_HEX_ENTITY && !this._xmlMode) {
+                this._decodeNumericEntity(3, 16);
+                if (this._sectionStart < this._index) {
+                    this._state = this._baseState;
+                    this._handleTrailingData();
+                }
+            } else if (
+                this._state !== IN_TAG_NAME &&
+                this._state !== BEFORE_ATTRIBUTE_NAME &&
+                this._state !== BEFORE_ATTRIBUTE_VALUE &&
+                this._state !== AFTER_ATTRIBUTE_NAME &&
+                this._state !== IN_ATTRIBUTE_NAME &&
+                this._state !== IN_ATTRIBUTE_VALUE_SQ &&
+                this._state !== IN_ATTRIBUTE_VALUE_DQ &&
+                this._state !== IN_ATTRIBUTE_VALUE_NQ &&
+                this._state !== IN_CLOSING_TAG_NAME
+            ) {
+                this._cbs.ontext(data);
+            }
+            //else, ignore remaining data
+            //TODO add a way to remove current tag
+        };
+
+        Tokenizer.prototype.reset = function () {
+            Tokenizer.call(this, {xmlMode: this._xmlMode, decodeEntities: this._decodeEntities}, this._cbs);
+        };
+
+        Tokenizer.prototype.getAbsoluteIndex = function () {
+            return this._bufferOffset + this._index;
+        };
+
+        Tokenizer.prototype._getSection = function () {
+            return this._buffer.substring(this._sectionStart, this._index);
+        };
+
+        Tokenizer.prototype._emitToken = function (name) {
+            this._cbs[name](this._getSection());
+            this._sectionStart = -1;
+        };
+
+        Tokenizer.prototype._emitPartial = function (value) {
+            if (this._baseState !== TEXT) {
+                this._cbs.onattribdata(value); //TODO implement the new event
+            } else {
+                this._cbs.ontext(value);
+            }
+        };
+
+    }, {
+        "entities/lib/decode_codepoint.js": 29,
+        "entities/maps/entities.json": 32,
+        "entities/maps/legacy.json": 33,
+        "entities/maps/xml.json": 34
+    }],
+    12: [function (require, module, exports) {
+        module.exports = Stream;
+
+        var Parser = require("./Parser.js"),
+            WritableStream = require("stream").Writable || require("readable-stream").Writable;
+
+        function Stream(cbs, options) {
+            var parser = this._parser = new Parser(cbs, options);
+
+            WritableStream.call(this, {decodeStrings: false});
+
+            this.once("finish", function () {
+                parser.end();
+            });
+        }
+
+        require("util").inherits(Stream, WritableStream);
+
+        WritableStream.prototype._write = function (chunk, encoding, cb) {
+            this._parser.write(chunk);
+            cb();
+        };
+    }, {"./Parser.js": 8, "readable-stream": 35, "stream": 58, "util": 61}],
+    13: [function (require, module, exports) {
+        var Parser = require("./Parser.js"),
+            DomHandler = require("domhandler");
+
+        function defineProp(name, value) {
+            delete module.exports[name];
+            module.exports[name] = value;
+            return value;
+        }
+
+        module.exports = {
+            Parser: Parser,
+            Tokenizer: require("./Tokenizer.js"),
+            ElementType: require("domelementtype"),
+            DomHandler: DomHandler,
+            get FeedHandler() {
+                return defineProp("FeedHandler", require("./FeedHandler.js"));
+            },
+            get Stream() {
+                return defineProp("Stream", require("./Stream.js"));
+            },
+            get WritableStream() {
+                return defineProp("WritableStream", require("./WritableStream.js"));
+            },
+            get ProxyHandler() {
+                return defineProp("ProxyHandler", require("./ProxyHandler.js"));
+            },
+            get DomUtils() {
+                return defineProp("DomUtils", require("domutils"));
+            },
+            get CollectingHandler() {
+                return defineProp("CollectingHandler", require("./CollectingHandler.js"));
+            },
+            // For legacy support
+            DefaultHandler: DomHandler,
+            get RssHandler() {
+                return defineProp("RssHandler", this.FeedHandler);
+            },
+            //helper methods
+            parseDOM: function (data, options) {
+                var handler = new DomHandler(options);
+                new Parser(handler, options).end(data);
+                return handler.dom;
+            },
+            parseFeed: function (feed, options) {
+                var handler = new module.exports.FeedHandler(options);
+                new Parser(handler, options).end(feed);
+                return handler.dom;
+            },
+            createDomStream: function (cb, options, elementCb) {
+                var handler = new DomHandler(cb, options, elementCb);
+                return new Parser(handler, options);
+            },
+            // List of all events that the parser emits
+            EVENTS: {
+                /* Format: eventname: number of arguments */
+                attribute: 2,
+                cdatastart: 0,
+                cdataend: 0,
+                text: 1,
+                processinginstruction: 2,
+                comment: 1,
+                commentend: 0,
+                closetag: 1,
+                opentag: 2,
+                opentagname: 1,
+                error: 1,
+                end: 0
+            }
+        };
+
+    }, {
+        "./CollectingHandler.js": 6,
+        "./FeedHandler.js": 7,
+        "./Parser.js": 8,
+        "./ProxyHandler.js": 9,
+        "./Stream.js": 10,
+        "./Tokenizer.js": 11,
+        "./WritableStream.js": 12,
+        "domelementtype": 14,
+        "domhandler": 15,
+        "domutils": 18
+    }],
+    14: [function (require, module, exports) {
+//Types of elements found in the DOM
+        module.exports = {
+            Text: "text", //Text
+            Directive: "directive", //<? ... ?>
+            Comment: "comment", //<!-- ... -->
+            Script: "script", //<script> tags
+            Style: "style", //<style> tags
+            Tag: "tag", //Any tag
+            CDATA: "cdata", //<![CDATA[ ... ]]>
+            Doctype: "doctype",
+
+            isTag: function (elem) {
+                return elem.type === "tag" || elem.type === "script" || elem.type === "style";
+            }
+        };
+
+    }, {}],
+    15: [function (require, module, exports) {
+        var ElementType = require("domelementtype");
+
+        var re_whitespace = /\s+/g;
+        var NodePrototype = require("./lib/node");
+        var ElementPrototype = require("./lib/element");
+
+        function DomHandler(callback, options, elementCB) {
+            if (typeof callback === "object") {
+                elementCB = options;
+                options = callback;
+                callback = null;
+            } else if (typeof options === "function") {
+                elementCB = options;
+                options = defaultOpts;
+            }
+            this._callback = callback;
+            this._options = options || defaultOpts;
+            this._elementCB = elementCB;
+            this.dom = [];
+            this._done = false;
+            this._tagStack = [];
+            this._parser = this._parser || null;
+        }
+
+//default options
+        var defaultOpts = {
+            normalizeWhitespace: false, //Replace all whitespace with single spaces
+            withStartIndices: false, //Add startIndex properties to nodes
+        };
+
+        DomHandler.prototype.onparserinit = function (parser) {
+            this._parser = parser;
+        };
+
+//Resets the handler back to starting state
+        DomHandler.prototype.onreset = function () {
+            DomHandler.call(this, this._callback, this._options, this._elementCB);
+        };
+
+//Signals the handler that parsing is done
+        DomHandler.prototype.onend = function () {
+            if (this._done) return;
+            this._done = true;
+            this._parser = null;
+            this._handleCallback(null);
+        };
+
+        DomHandler.prototype._handleCallback =
+            DomHandler.prototype.onerror = function (error) {
+                if (typeof this._callback === "function") {
+                    this._callback(error, this.dom);
+                } else {
+                    if (error) throw error;
+                }
+            };
+
+        DomHandler.prototype.onclosetag = function () {
+            //if(this._tagStack.pop().name !== name) this._handleCallback(Error("Tagname didn't match!"));
+            var elem = this._tagStack.pop();
+            if (this._elementCB) this._elementCB(elem);
+        };
+
+        DomHandler.prototype._addDomElement = function (element) {
+            var parent = this._tagStack[this._tagStack.length - 1];
+            var siblings = parent ? parent.children : this.dom;
+            var previousSibling = siblings[siblings.length - 1];
+
+            element.next = null;
+
+            if (this._options.withStartIndices) {
+                element.startIndex = this._parser.startIndex;
+            }
+
+            if (this._options.withDomLvl1) {
+                element.__proto__ = element.type === "tag" ? ElementPrototype : NodePrototype;
+            }
+
+            if (previousSibling) {
+                element.prev = previousSibling;
+                previousSibling.next = element;
+            } else {
+                element.prev = null;
+            }
+
+            siblings.push(element);
+            element.parent = parent || null;
+        };
+
+        DomHandler.prototype.onopentag = function (name, attribs) {
+            var element = {
+                type: name === "script" ? ElementType.Script : name === "style" ? ElementType.Style : ElementType.Tag,
+                name: name,
+                attribs: attribs,
+                children: []
+            };
+
+            this._addDomElement(element);
+
+            this._tagStack.push(element);
+        };
+
+        DomHandler.prototype.ontext = function (data) {
+            //the ignoreWhitespace is officially dropped, but for now,
+            //it's an alias for normalizeWhitespace
+            var normalize = this._options.normalizeWhitespace || this._options.ignoreWhitespace;
+
+            var lastTag;
+
+            if (!this._tagStack.length && this.dom.length && (lastTag = this.dom[this.dom.length - 1]).type === ElementType.Text) {
+                if (normalize) {
+                    lastTag.data = (lastTag.data + data).replace(re_whitespace, " ");
+                } else {
+                    lastTag.data += data;
+                }
+            } else {
+                if (
+                    this._tagStack.length &&
+                    (lastTag = this._tagStack[this._tagStack.length - 1]) &&
+                    (lastTag = lastTag.children[lastTag.children.length - 1]) &&
+                    lastTag.type === ElementType.Text
+                ) {
+                    if (normalize) {
+                        lastTag.data = (lastTag.data + data).replace(re_whitespace, " ");
+                    } else {
+                        lastTag.data += data;
+                    }
+                } else {
+                    if (normalize) {
+                        data = data.replace(re_whitespace, " ");
+                    }
+
+                    this._addDomElement({
+                        data: data,
+                        type: ElementType.Text
+                    });
+                }
+            }
+        };
+
+        DomHandler.prototype.oncomment = function (data) {
+            var lastTag = this._tagStack[this._tagStack.length - 1];
+
+            if (lastTag && lastTag.type === ElementType.Comment) {
+                lastTag.data += data;
+                return;
+            }
+
+            var element = {
+                data: data,
+                type: ElementType.Comment
+            };
+
+            this._addDomElement(element);
+            this._tagStack.push(element);
+        };
+
+        DomHandler.prototype.oncdatastart = function () {
+            var element = {
+                children: [{
+                    data: "",
+                    type: ElementType.Text
+                }],
+                type: ElementType.CDATA
+            };
+
+            this._addDomElement(element);
+            this._tagStack.push(element);
+        };
+
+        DomHandler.prototype.oncommentend = DomHandler.prototype.oncdataend = function () {
+            this._tagStack.pop();
+        };
+
+        DomHandler.prototype.onprocessinginstruction = function (name, data) {
+            this._addDomElement({
+                name: name,
+                data: data,
+                type: ElementType.Directive
+            });
+        };
+
+        module.exports = DomHandler;
+
+    }, {"./lib/element": 16, "./lib/node": 17, "domelementtype": 14}],
+    16: [function (require, module, exports) {
+// DOM-Level-1-compliant structure
+        var NodePrototype = require('./node');
+        var ElementPrototype = module.exports = Object.create(NodePrototype);
+
+        var domLvl1 = {
+            tagName: "name"
+        };
+
+        Object.keys(domLvl1).forEach(function (key) {
+            var shorthand = domLvl1[key];
+            Object.defineProperty(ElementPrototype, key, {
+                get: function () {
+                    return this[shorthand] || null;
+                },
+                set: function (val) {
+                    this[shorthand] = val;
+                    return val;
+                }
+            });
+        });
+
+    }, {"./node": 17}],
+    17: [function (require, module, exports) {
+// This object will be used as the prototype for Nodes when creating a
+// DOM-Level-1-compliant structure.
+        var NodePrototype = module.exports = {
+            get firstChild() {
+                var children = this.children;
+                return children && children[0] || null;
+            },
+            get lastChild() {
+                var children = this.children;
+                return children && children[children.length - 1] || null;
+            },
+            get nodeType() {
+                return nodeTypes[this.type] || nodeTypes.element;
+            }
+        };
+
+        var domLvl1 = {
+            tagName: "name",
+            childNodes: "children",
+            parentNode: "parent",
+            previousSibling: "prev",
+            nextSibling: "next",
+            nodeValue: "data"
+        };
+
+        var nodeTypes = {
+            element: 1,
+            text: 3,
+            cdata: 4,
+            comment: 8
+        };
+
+        Object.keys(domLvl1).forEach(function (key) {
+            var shorthand = domLvl1[key];
+            Object.defineProperty(NodePrototype, key, {
+                get: function () {
+                    return this[shorthand] || null;
+                },
+                set: function (val) {
+                    this[shorthand] = val;
+                    return val;
+                }
+            });
+        });
+
+    }, {}],
+    18: [function (require, module, exports) {
+        var DomUtils = module.exports;
+
+        [
+            require("./lib/stringify"),
+            require("./lib/traversal"),
+            require("./lib/manipulation"),
+            require("./lib/querying"),
+            require("./lib/legacy"),
+            require("./lib/helpers")
+        ].forEach(function (ext) {
+            Object.keys(ext).forEach(function (key) {
+                DomUtils[key] = ext[key].bind(DomUtils);
+            });
+        });
+
+    }, {
+        "./lib/helpers": 19,
+        "./lib/legacy": 20,
+        "./lib/manipulation": 21,
+        "./lib/querying": 22,
+        "./lib/stringify": 23,
+        "./lib/traversal": 24
+    }],
+    19: [function (require, module, exports) {
+// removeSubsets
+// Given an array of nodes, remove any member that is contained by another.
+        exports.removeSubsets = function (nodes) {
+            var idx = nodes.length, node, ancestor, replace;
+
+            // Check if each node (or one of its ancestors) is already contained in the
+            // array.
+            while (--idx > -1) {
+                node = ancestor = nodes[idx];
+
+                // Temporarily remove the node under consideration
+                nodes[idx] = null;
+                replace = true;
+
+                while (ancestor) {
+                    if (nodes.indexOf(ancestor) > -1) {
+                        replace = false;
+                        nodes.splice(idx, 1);
+                        break;
+                    }
+                    ancestor = ancestor.parent;
+                }
+
+                // If the node has been found to be unique, re-insert it.
+                if (replace) {
+                    nodes[idx] = node;
+                }
+            }
+
+            return nodes;
+        };
+
+// Source: http://dom.spec.whatwg.org/#dom-node-comparedocumentposition
+        var POSITION = {
+            DISCONNECTED: 1,
+            PRECEDING: 2,
+            FOLLOWING: 4,
+            CONTAINS: 8,
+            CONTAINED_BY: 16
+        };
+
+// Compare the position of one node against another node in any other document.
+// The return value is a bitmask with the following values:
+//
+// document order:
+// > There is an ordering, document order, defined on all the nodes in the
+// > document corresponding to the order in which the first character of the
+// > XML representation of each node occurs in the XML representation of the
+// > document after expansion of general entities. Thus, the document element
+// > node will be the first node. Element nodes occur before their children.
+// > Thus, document order orders element nodes in order of the occurrence of
+// > their start-tag in the XML (after expansion of entities). The attribute
+// > nodes of an element occur after the element and before its children. The
+// > relative order of attribute nodes is implementation-dependent./
+// Source:
+// http://www.w3.org/TR/DOM-Level-3-Core/glossary.html#dt-document-order
+//
+// @argument {Node} nodaA The first node to use in the comparison
+// @argument {Node} nodeB The second node to use in the comparison
+//
+// @return {Number} A bitmask describing the input nodes' relative position.
+//         See http://dom.spec.whatwg.org/#dom-node-comparedocumentposition for
+//         a description of these values.
+        var comparePos = exports.compareDocumentPosition = function (nodeA, nodeB) {
+            var aParents = [];
+            var bParents = [];
+            var current, sharedParent, siblings, aSibling, bSibling, idx;
+
+            if (nodeA === nodeB) {
+                return 0;
+            }
+
+            current = nodeA;
+            while (current) {
+                aParents.unshift(current);
+                current = current.parent;
+            }
+            current = nodeB;
+            while (current) {
+                bParents.unshift(current);
+                current = current.parent;
+            }
+
+            idx = 0;
+            while (aParents[idx] === bParents[idx]) {
+                idx++;
+            }
+
+            if (idx === 0) {
+                return POSITION.DISCONNECTED;
+            }
+
+            sharedParent = aParents[idx - 1];
+            siblings = sharedParent.children;
+            aSibling = aParents[idx];
+            bSibling = bParents[idx];
+
+            if (siblings.indexOf(aSibling) > siblings.indexOf(bSibling)) {
+                if (sharedParent === nodeB) {
+                    return POSITION.FOLLOWING | POSITION.CONTAINED_BY;
+                }
+                return POSITION.FOLLOWING;
+            } else {
+                if (sharedParent === nodeA) {
+                    return POSITION.PRECEDING | POSITION.CONTAINS;
+                }
+                return POSITION.PRECEDING;
+            }
+        };
+
+// Sort an array of nodes based on their relative position in the document and
+// remove any duplicate nodes. If the array contains nodes that do not belong
+// to the same document, sort order is unspecified.
+//
+// @argument {Array} nodes Array of DOM nodes
+//
+// @returns {Array} collection of unique nodes, sorted in document order
+        exports.uniqueSort = function (nodes) {
+            var idx = nodes.length, node, position;
+
+            nodes = nodes.slice();
+
+            while (--idx > -1) {
+                node = nodes[idx];
+                position = nodes.indexOf(node);
+                if (position > -1 && position < idx) {
+                    nodes.splice(idx, 1);
+                }
+            }
+            nodes.sort(function (a, b) {
+                var relative = comparePos(a, b);
+                if (relative & POSITION.PRECEDING) {
+                    return -1;
+                } else if (relative & POSITION.FOLLOWING) {
+                    return 1;
+                }
+                return 0;
+            });
+
+            return nodes;
+        };
+
+    }, {}],
+    20: [function (require, module, exports) {
+        var ElementType = require("domelementtype");
+        var isTag = exports.isTag = ElementType.isTag;
+
+        exports.testElement = function (options, element) {
+            for (var key in options) {
+                if (!options.hasOwnProperty(key)) ;
+                else if (key === "tag_name") {
+                    if (!isTag(element) || !options.tag_name(element.name)) {
+                        return false;
+                    }
+                } else if (key === "tag_type") {
+                    if (!options.tag_type(element.type)) return false;
+                } else if (key === "tag_contains") {
+                    if (isTag(element) || !options.tag_contains(element.data)) {
+                        return false;
+                    }
+                } else if (!element.attribs || !options[key](element.attribs[key])) {
+                    return false;
+                }
+            }
+            return true;
+        };
+
+        var Checks = {
+            tag_name: function (name) {
+                if (typeof name === "function") {
+                    return function (elem) {
+                        return isTag(elem) && name(elem.name);
+                    };
+                } else if (name === "*") {
+                    return isTag;
+                } else {
+                    return function (elem) {
+                        return isTag(elem) && elem.name === name;
+                    };
+                }
+            },
+            tag_type: function (type) {
+                if (typeof type === "function") {
+                    return function (elem) {
+                        return type(elem.type);
+                    };
+                } else {
+                    return function (elem) {
+                        return elem.type === type;
+                    };
+                }
+            },
+            tag_contains: function (data) {
+                if (typeof data === "function") {
+                    return function (elem) {
+                        return !isTag(elem) && data(elem.data);
+                    };
+                } else {
+                    return function (elem) {
+                        return !isTag(elem) && elem.data === data;
+                    };
+                }
+            }
+        };
+
+        function getAttribCheck(attrib, value) {
+            if (typeof value === "function") {
+                return function (elem) {
+                    return elem.attribs && value(elem.attribs[attrib]);
+                };
+            } else {
+                return function (elem) {
+                    return elem.attribs && elem.attribs[attrib] === value;
+                };
+            }
+        }
+
+        function combineFuncs(a, b) {
+            return function (elem) {
+                return a(elem) || b(elem);
+            };
+        }
+
+        exports.getElements = function (options, element, recurse, limit) {
+            var funcs = Object.keys(options).map(function (key) {
+                var value = options[key];
+                return key in Checks ? Checks[key](value) : getAttribCheck(key, value);
+            });
+
+            return funcs.length === 0 ? [] : this.filter(
+                funcs.reduce(combineFuncs),
+                element, recurse, limit
+            );
+        };
+
+        exports.getElementById = function (id, element, recurse) {
+            if (!Array.isArray(element)) element = [element];
+            return this.findOne(getAttribCheck("id", id), element, recurse !== false);
+        };
+
+        exports.getElementsByTagName = function (name, element, recurse, limit) {
+            return this.filter(Checks.tag_name(name), element, recurse, limit);
+        };
+
+        exports.getElementsByTagType = function (type, element, recurse, limit) {
+            return this.filter(Checks.tag_type(type), element, recurse, limit);
+        };
+
+    }, {"domelementtype": 14}],
+    21: [function (require, module, exports) {
+        exports.removeElement = function (elem) {
+            if (elem.prev) elem.prev.next = elem.next;
+            if (elem.next) elem.next.prev = elem.prev;
+
+            if (elem.parent) {
+                var childs = elem.parent.children;
+                childs.splice(childs.lastIndexOf(elem), 1);
+            }
+        };
+
+        exports.replaceElement = function (elem, replacement) {
+            var prev = replacement.prev = elem.prev;
+            if (prev) {
+                prev.next = replacement;
+            }
+
+            var next = replacement.next = elem.next;
+            if (next) {
+                next.prev = replacement;
+            }
+
+            var parent = replacement.parent = elem.parent;
+            if (parent) {
+                var childs = parent.children;
+                childs[childs.lastIndexOf(elem)] = replacement;
+            }
+        };
+
+        exports.appendChild = function (elem, child) {
+            child.parent = elem;
+
+            if (elem.children.push(child) !== 1) {
+                var sibling = elem.children[elem.children.length - 2];
+                sibling.next = child;
+                child.prev = sibling;
+                child.next = null;
+            }
+        };
+
+        exports.append = function (elem, next) {
+            var parent = elem.parent,
+                currNext = elem.next;
+
+            next.next = currNext;
+            next.prev = elem;
+            elem.next = next;
+            next.parent = parent;
+
+            if (currNext) {
+                currNext.prev = next;
+                if (parent) {
+                    var childs = parent.children;
+                    childs.splice(childs.lastIndexOf(currNext), 0, next);
+                }
+            } else if (parent) {
+                parent.children.push(next);
+            }
+        };
+
+        exports.prepend = function (elem, prev) {
+            var parent = elem.parent;
+            if (parent) {
+                var childs = parent.children;
+                childs.splice(childs.lastIndexOf(elem), 0, prev);
+            }
+
+            if (elem.prev) {
+                elem.prev.next = prev;
+            }
+
+            prev.parent = parent;
+            prev.prev = elem.prev;
+            prev.next = elem;
+            elem.prev = prev;
+        };
+
+
+    }, {}],
+    22: [function (require, module, exports) {
+        var isTag = require("domelementtype").isTag;
+
+        module.exports = {
+            filter: filter,
+            find: find,
+            findOneChild: findOneChild,
+            findOne: findOne,
+            existsOne: existsOne,
+            findAll: findAll
+        };
+
+        function filter(test, element, recurse, limit) {
+            if (!Array.isArray(element)) element = [element];
+
+            if (typeof limit !== "number" || !isFinite(limit)) {
+                limit = Infinity;
+            }
+            return find(test, element, recurse !== false, limit);
+        }
+
+        function find(test, elems, recurse, limit) {
+            var result = [], childs;
+
+            for (var i = 0, j = elems.length; i < j; i++) {
+                if (test(elems[i])) {
+                    result.push(elems[i]);
+                    if (--limit <= 0) break;
+                }
+
+                childs = elems[i].children;
+                if (recurse && childs && childs.length > 0) {
+                    childs = find(test, childs, recurse, limit);
+                    result = result.concat(childs);
+                    limit -= childs.length;
+                    if (limit <= 0) break;
+                }
+            }
+
+            return result;
+        }
+
+        function findOneChild(test, elems) {
+            for (var i = 0, l = elems.length; i < l; i++) {
+                if (test(elems[i])) return elems[i];
+            }
+
+            return null;
+        }
+
+        function findOne(test, elems) {
+            var elem = null;
+
+            for (var i = 0, l = elems.length; i < l && !elem; i++) {
+                if (!isTag(elems[i])) {
+                    continue;
+                } else if (test(elems[i])) {
+                    elem = elems[i];
+                } else if (elems[i].children.length > 0) {
+                    elem = findOne(test, elems[i].children);
+                }
+            }
+
+            return elem;
+        }
+
+        function existsOne(test, elems) {
+            for (var i = 0, l = elems.length; i < l; i++) {
+                if (
+                    isTag(elems[i]) && (
+                        test(elems[i]) || (
+                            elems[i].children.length > 0 &&
+                            existsOne(test, elems[i].children)
+                        )
+                    )
+                ) {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        function findAll(test, elems) {
+            var result = [];
+            for (var i = 0, j = elems.length; i < j; i++) {
+                if (!isTag(elems[i])) continue;
+                if (test(elems[i])) result.push(elems[i]);
+
+                if (elems[i].children.length > 0) {
+                    result = result.concat(findAll(test, elems[i].children));
+                }
+            }
+            return result;
+        }
+
+    }, {"domelementtype": 14}],
+    23: [function (require, module, exports) {
+        var ElementType = require("domelementtype"),
+            getOuterHTML = require("dom-serializer"),
+            isTag = ElementType.isTag;
+
+        module.exports = {
+            getInnerHTML: getInnerHTML,
+            getOuterHTML: getOuterHTML,
+            getText: getText
+        };
+
+        function getInnerHTML(elem, opts) {
+            return elem.children ? elem.children.map(function (elem) {
+                return getOuterHTML(elem, opts);
+            }).join("") : "";
+        }
+
+        function getText(elem) {
+            if (Array.isArray(elem)) return elem.map(getText).join("");
+            if (isTag(elem) || elem.type === ElementType.CDATA) return getText(elem.children);
+            if (elem.type === ElementType.Text) return elem.data;
+            return "";
+        }
+
+    }, {"dom-serializer": 25, "domelementtype": 14}],
+    24: [function (require, module, exports) {
+        var getChildren = exports.getChildren = function (elem) {
+            return elem.children;
+        };
+
+        var getParent = exports.getParent = function (elem) {
+            return elem.parent;
+        };
+
+        exports.getSiblings = function (elem) {
+            var parent = getParent(elem);
+            return parent ? getChildren(parent) : [elem];
+        };
+
+        exports.getAttributeValue = function (elem, name) {
+            return elem.attribs && elem.attribs[name];
+        };
+
+        exports.hasAttrib = function (elem, name) {
+            return !!elem.attribs && hasOwnProperty.call(elem.attribs, name);
+        };
+
+        exports.getName = function (elem) {
+            return elem.name;
+        };
+
+    }, {}],
+    25: [function (require, module, exports) {
+        /*
+  Module dependencies
+*/
+        var ElementType = require('domelementtype');
+        var entities = require('entities');
+
+        /*
+  Boolean Attributes
+*/
+        var booleanAttributes = {
+            __proto__: null,
+            allowfullscreen: true,
+            async: true,
+            autofocus: true,
+            autoplay: true,
+            checked: true,
+            controls: true,
+            default: true,
+            defer: true,
+            disabled: true,
+            hidden: true,
+            ismap: true,
+            loop: true,
+            multiple: true,
+            muted: true,
+            open: true,
+            readonly: true,
+            required: true,
+            reversed: true,
+            scoped: true,
+            seamless: true,
+            selected: true,
+            typemustmatch: true
+        };
+
+        var unencodedElements = {
+            __proto__: null,
+            style: true,
+            script: true,
+            xmp: true,
+            iframe: true,
+            noembed: true,
+            noframes: true,
+            plaintext: true,
+            noscript: true
+        };
+
+        /*
+  Format attributes
+*/
+        function formatAttrs(attributes, opts) {
+            if (!attributes) return;
+
+            var output = '',
+                value;
+
+            // Loop through the attributes
+            for (var key in attributes) {
+                value = attributes[key];
+                if (output) {
+                    output += ' ';
+                }
+
+                if (!value && booleanAttributes[key]) {
+                    output += key;
+                } else {
+                    output += key + '="' + (opts.decodeEntities ? entities.encodeXML(value) : value) + '"';
+                }
+            }
+
+            return output;
+        }
+
+        /*
+  Self-enclosing tags (stolen from node-htmlparser)
+*/
+        var singleTag = {
+            __proto__: null,
+            area: true,
+            base: true,
+            basefont: true,
+            br: true,
+            col: true,
+            command: true,
+            embed: true,
+            frame: true,
+            hr: true,
+            img: true,
+            input: true,
+            isindex: true,
+            keygen: true,
+            link: true,
+            meta: true,
+            param: true,
+            source: true,
+            track: true,
+            wbr: true,
+        };
+
+
+        var render = module.exports = function (dom, opts) {
+            if (!Array.isArray(dom) && !dom.cheerio) dom = [dom];
+            opts = opts || {};
+
+            var output = '';
+
+            for (var i = 0; i < dom.length; i++) {
+                var elem = dom[i];
+
+                if (elem.type === 'root')
+                    output += render(elem.children, opts);
+                else if (ElementType.isTag(elem))
+                    output += renderTag(elem, opts);
+                else if (elem.type === ElementType.Directive)
+                    output += renderDirective(elem);
+                else if (elem.type === ElementType.Comment)
+                    output += renderComment(elem);
+                else if (elem.type === ElementType.CDATA)
+                    output += renderCdata(elem);
+                else
+                    output += renderText(elem, opts);
+            }
+
+            return output;
+        };
+
+        function renderTag(elem, opts) {
+            // Handle SVG
+            if (elem.name === "svg") opts = {decodeEntities: opts.decodeEntities, xmlMode: true};
+
+            var tag = '<' + elem.name,
+                attribs = formatAttrs(elem.attribs, opts);
+
+            if (attribs) {
+                tag += ' ' + attribs;
+            }
+
+            if (
+                opts.xmlMode
+                && (!elem.children || elem.children.length === 0)
+            ) {
+                tag += '/>';
+            } else {
+                tag += '>';
+                if (elem.children) {
+                    tag += render(elem.children, opts);
+                }
+
+                if (!singleTag[elem.name] || opts.xmlMode) {
+                    tag += '</' + elem.name + '>';
+                }
+            }
+
+            return tag;
+        }
+
+        function renderDirective(elem) {
+            return '<' + elem.data + '>';
+        }
+
+        function renderText(elem, opts) {
+            var data = elem.data || '';
+
+            // if entities weren't decoded, no need to encode them back
+            if (opts.decodeEntities && !(elem.parent && elem.parent.name in unencodedElements)) {
+                data = entities.encodeXML(data);
+            }
+
+            return data;
+        }
+
+        function renderCdata(elem) {
+            return '<![CDATA[' + elem.children[0].data + ']]>';
+        }
+
+        function renderComment(elem) {
+            return '<!--' + elem.data + '-->';
+        }
+
+    }, {"domelementtype": 26, "entities": 27}],
+    26: [function (require, module, exports) {
+//Types of elements found in the DOM
+        module.exports = {
+            Text: "text", //Text
+            Directive: "directive", //<? ... ?>
+            Comment: "comment", //<!-- ... -->
+            Script: "script", //<script> tags
+            Style: "style", //<style> tags
+            Tag: "tag", //Any tag
+            CDATA: "cdata", //<![CDATA[ ... ]]>
+
+            isTag: function (elem) {
+                return elem.type === "tag" || elem.type === "script" || elem.type === "style";
+            }
+        };
+    }, {}],
+    27: [function (require, module, exports) {
+        var encode = require("./lib/encode.js"),
+            decode = require("./lib/decode.js");
+
+        exports.decode = function (data, level) {
+            return (!level || level <= 0 ? decode.XML : decode.HTML)(data);
+        };
+
+        exports.decodeStrict = function (data, level) {
+            return (!level || level <= 0 ? decode.XML : decode.HTMLStrict)(data);
+        };
+
+        exports.encode = function (data, level) {
+            return (!level || level <= 0 ? encode.XML : encode.HTML)(data);
+        };
+
+        exports.encodeXML = encode.XML;
+
+        exports.encodeHTML4 =
+            exports.encodeHTML5 =
+                exports.encodeHTML = encode.HTML;
+
+        exports.decodeXML =
+            exports.decodeXMLStrict = decode.XML;
+
+        exports.decodeHTML4 =
+            exports.decodeHTML5 =
+                exports.decodeHTML = decode.HTML;
+
+        exports.decodeHTML4Strict =
+            exports.decodeHTML5Strict =
+                exports.decodeHTMLStrict = decode.HTMLStrict;
+
+        exports.escape = encode.escape;
+
+    }, {"./lib/decode.js": 28, "./lib/encode.js": 30}],
+    28: [function (require, module, exports) {
+        var entityMap = require("../maps/entities.json"),
+            legacyMap = require("../maps/legacy.json"),
+            xmlMap = require("../maps/xml.json"),
+            decodeCodePoint = require("./decode_codepoint.js");
+
+        var decodeXMLStrict = getStrictDecoder(xmlMap),
+            decodeHTMLStrict = getStrictDecoder(entityMap);
+
+        function getStrictDecoder(map) {
+            var keys = Object.keys(map).join("|"),
+                replace = getReplacer(map);
+
+            keys += "|#[xX][\\da-fA-F]+|#\\d+";
+
+            var re = new RegExp("&(?:" + keys + ");", "g");
+
+            return function (str) {
+                return String(str).replace(re, replace);
+            };
+        }
+
+        var decodeHTML = (function () {
+            var legacy = Object.keys(legacyMap)
+                .sort(sorter);
+
+            var keys = Object.keys(entityMap)
+                .sort(sorter);
+
+            for (var i = 0, j = 0; i < keys.length; i++) {
+                if (legacy[j] === keys[i]) {
+                    keys[i] += ";?";
+                    j++;
+                } else {
+                    keys[i] += ";";
+                }
+            }
+
+            var re = new RegExp("&(?:" + keys.join("|") + "|#[xX][\\da-fA-F]+;?|#\\d+;?)", "g"),
+                replace = getReplacer(entityMap);
+
+            function replacer(str) {
+                if (str.substr(-1) !== ";") str += ";";
+                return replace(str);
+            }
+
+            //TODO consider creating a merged map
+            return function (str) {
+                return String(str).replace(re, replacer);
+            };
+        }());
+
+        function sorter(a, b) {
+            return a < b ? 1 : -1;
+        }
+
+        function getReplacer(map) {
+            return function replace(str) {
+                if (str.charAt(1) === "#") {
+                    if (str.charAt(2) === "X" || str.charAt(2) === "x") {
+                        return decodeCodePoint(parseInt(str.substr(3), 16));
+                    }
+                    return decodeCodePoint(parseInt(str.substr(2), 10));
+                }
+                return map[str.slice(1, -1)];
+            };
+        }
+
+        module.exports = {
+            XML: decodeXMLStrict,
+            HTML: decodeHTML,
+            HTMLStrict: decodeHTMLStrict
+        };
+    }, {"../maps/entities.json": 32, "../maps/legacy.json": 33, "../maps/xml.json": 34, "./decode_codepoint.js": 29}],
+    29: [function (require, module, exports) {
+        var decodeMap = require("../maps/decode.json");
+
+        module.exports = decodeCodePoint;
+
+// modified version of https://github.com/mathiasbynens/he/blob/master/src/he.js#L94-L119
+        function decodeCodePoint(codePoint) {
+
+            if ((codePoint >= 0xD800 && codePoint <= 0xDFFF) || codePoint > 0x10FFFF) {
+                return "\uFFFD";
+            }
+
+            if (codePoint in decodeMap) {
+                codePoint = decodeMap[codePoint];
+            }
+
+            var output = "";
+
+            if (codePoint > 0xFFFF) {
+                codePoint -= 0x10000;
+                output += String.fromCharCode(codePoint >>> 10 & 0x3FF | 0xD800);
+                codePoint = 0xDC00 | codePoint & 0x3FF;
+            }
+
+            output += String.fromCharCode(codePoint);
+            return output;
+        }
+
+    }, {"../maps/decode.json": 31}],
+    30: [function (require, module, exports) {
+        var inverseXML = getInverseObj(require("../maps/xml.json")),
+            xmlReplacer = getInverseReplacer(inverseXML);
+
+        exports.XML = getInverse(inverseXML, xmlReplacer);
+
+        var inverseHTML = getInverseObj(require("../maps/entities.json")),
+            htmlReplacer = getInverseReplacer(inverseHTML);
+
+        exports.HTML = getInverse(inverseHTML, htmlReplacer);
+
+        function getInverseObj(obj) {
+            return Object.keys(obj).sort().reduce(function (inverse, name) {
+                inverse[obj[name]] = "&" + name + ";";
+                return inverse;
+            }, {});
+        }
+
+        function getInverseReplacer(inverse) {
+            var single = [],
+                multiple = [];
+
+            Object.keys(inverse).forEach(function (k) {
+                if (k.length === 1) {
+                    single.push("\\" + k);
+                } else {
+                    multiple.push(k);
+                }
+            });
+
+            //TODO add ranges
+            multiple.unshift("[" + single.join("") + "]");
+
+            return new RegExp(multiple.join("|"), "g");
+        }
+
+        var re_nonASCII = /[^\0-\x7F]/g,
+            re_astralSymbols = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
+
+        function singleCharReplacer(c) {
+            return "&#x" + c.charCodeAt(0).toString(16).toUpperCase() + ";";
+        }
+
+        function astralReplacer(c) {
+            // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
+            var high = c.charCodeAt(0);
+            var low = c.charCodeAt(1);
+            var codePoint = (high - 0xD800) * 0x400 + low - 0xDC00 + 0x10000;
+            return "&#x" + codePoint.toString(16).toUpperCase() + ";";
+        }
+
+        function getInverse(inverse, re) {
+            function func(name) {
+                return inverse[name];
+            }
+
+            return function (data) {
+                return data
+                    .replace(re, func)
+                    .replace(re_astralSymbols, astralReplacer)
+                    .replace(re_nonASCII, singleCharReplacer);
+            };
+        }
+
+        var re_xmlChars = getInverseReplacer(inverseXML);
+
+        function escapeXML(data) {
+            return data
+                .replace(re_xmlChars, singleCharReplacer)
+                .replace(re_astralSymbols, astralReplacer)
+                .replace(re_nonASCII, singleCharReplacer);
+        }
+
+        exports.escape = escapeXML;
+
+    }, {"../maps/entities.json": 32, "../maps/xml.json": 34}],
+    31: [function (require, module, exports) {
+        module.exports = {
+            "0": 65533,
+            "128": 8364,
+            "130": 8218,
+            "131": 402,
+            "132": 8222,
+            "133": 8230,
+            "134": 8224,
+            "135": 8225,
+            "136": 710,
+            "137": 8240,
+            "138": 352,
+            "139": 8249,
+            "140": 338,
+            "142": 381,
+            "145": 8216,
+            "146": 8217,
+            "147": 8220,
+            "148": 8221,
+            "149": 8226,
+            "150": 8211,
+            "151": 8212,
+            "152": 732,
+            "153": 8482,
+            "154": 353,
+            "155": 8250,
+            "156": 339,
+            "158": 382,
+            "159": 376
+        }
+    }, {}],
+    32: [function (require, module, exports) {
+        module.exports = {
+            "Aacute": "\u00C1",
+            "aacute": "\u00E1",
+            "Abreve": "\u0102",
+            "abreve": "\u0103",
+            "ac": "\u223E",
+            "acd": "\u223F",
+            "acE": "\u223E\u0333",
+            "Acirc": "\u00C2",
+            "acirc": "\u00E2",
+            "acute": "\u00B4",
+            "Acy": "\u0410",
+            "acy": "\u0430",
+            "AElig": "\u00C6",
+            "aelig": "\u00E6",
+            "af": "\u2061",
+            "Afr": "\uD835\uDD04",
+            "afr": "\uD835\uDD1E",
+            "Agrave": "\u00C0",
+            "agrave": "\u00E0",
+            "alefsym": "\u2135",
+            "aleph": "\u2135",
+            "Alpha": "\u0391",
+            "alpha": "\u03B1",
+            "Amacr": "\u0100",
+            "amacr": "\u0101",
+            "amalg": "\u2A3F",
+            "amp": "&",
+            "AMP": "&",
+            "andand": "\u2A55",
+            "And": "\u2A53",
+            "and": "\u2227",
+            "andd": "\u2A5C",
+            "andslope": "\u2A58",
+            "andv": "\u2A5A",
+            "ang": "\u2220",
+            "ange": "\u29A4",
+            "angle": "\u2220",
+            "angmsdaa": "\u29A8",
+            "angmsdab": "\u29A9",
+            "angmsdac": "\u29AA",
+            "angmsdad": "\u29AB",
+            "angmsdae": "\u29AC",
+            "angmsdaf": "\u29AD",
+            "angmsdag": "\u29AE",
+            "angmsdah": "\u29AF",
+            "angmsd": "\u2221",
+            "angrt": "\u221F",
+            "angrtvb": "\u22BE",
+            "angrtvbd": "\u299D",
+            "angsph": "\u2222",
+            "angst": "\u00C5",
+            "angzarr": "\u237C",
+            "Aogon": "\u0104",
+            "aogon": "\u0105",
+            "Aopf": "\uD835\uDD38",
+            "aopf": "\uD835\uDD52",
+            "apacir": "\u2A6F",
+            "ap": "\u2248",
+            "apE": "\u2A70",
+            "ape": "\u224A",
+            "apid": "\u224B",
+            "apos": "'",
+            "ApplyFunction": "\u2061",
+            "approx": "\u2248",
+            "approxeq": "\u224A",
+            "Aring": "\u00C5",
+            "aring": "\u00E5",
+            "Ascr": "\uD835\uDC9C",
+            "ascr": "\uD835\uDCB6",
+            "Assign": "\u2254",
+            "ast": "*",
+            "asymp": "\u2248",
+            "asympeq": "\u224D",
+            "Atilde": "\u00C3",
+            "atilde": "\u00E3",
+            "Auml": "\u00C4",
+            "auml": "\u00E4",
+            "awconint": "\u2233",
+            "awint": "\u2A11",
+            "backcong": "\u224C",
+            "backepsilon": "\u03F6",
+            "backprime": "\u2035",
+            "backsim": "\u223D",
+            "backsimeq": "\u22CD",
+            "Backslash": "\u2216",
+            "Barv": "\u2AE7",
+            "barvee": "\u22BD",
+            "barwed": "\u2305",
+            "Barwed": "\u2306",
+            "barwedge": "\u2305",
+            "bbrk": "\u23B5",
+            "bbrktbrk": "\u23B6",
+            "bcong": "\u224C",
+            "Bcy": "\u0411",
+            "bcy": "\u0431",
+            "bdquo": "\u201E",
+            "becaus": "\u2235",
+            "because": "\u2235",
+            "Because": "\u2235",
+            "bemptyv": "\u29B0",
+            "bepsi": "\u03F6",
+            "bernou": "\u212C",
+            "Bernoullis": "\u212C",
+            "Beta": "\u0392",
+            "beta": "\u03B2",
+            "beth": "\u2136",
+            "between": "\u226C",
+            "Bfr": "\uD835\uDD05",
+            "bfr": "\uD835\uDD1F",
+            "bigcap": "\u22C2",
+            "bigcirc": "\u25EF",
+            "bigcup": "\u22C3",
+            "bigodot": "\u2A00",
+            "bigoplus": "\u2A01",
+            "bigotimes": "\u2A02",
+            "bigsqcup": "\u2A06",
+            "bigstar": "\u2605",
+            "bigtriangledown": "\u25BD",
+            "bigtriangleup": "\u25B3",
+            "biguplus": "\u2A04",
+            "bigvee": "\u22C1",
+            "bigwedge": "\u22C0",
+            "bkarow": "\u290D",
+            "blacklozenge": "\u29EB",
+            "blacksquare": "\u25AA",
+            "blacktriangle": "\u25B4",
+            "blacktriangledown": "\u25BE",
+            "blacktriangleleft": "\u25C2",
+            "blacktriangleright": "\u25B8",
+            "blank": "\u2423",
+            "blk12": "\u2592",
+            "blk14": "\u2591",
+            "blk34": "\u2593",
+            "block": "\u2588",
+            "bne": "=\u20E5",
+            "bnequiv": "\u2261\u20E5",
+            "bNot": "\u2AED",
+            "bnot": "\u2310",
+            "Bopf": "\uD835\uDD39",
+            "bopf": "\uD835\uDD53",
+            "bot": "\u22A5",
+            "bottom": "\u22A5",
+            "bowtie": "\u22C8",
+            "boxbox": "\u29C9",
+            "boxdl": "\u2510",
+            "boxdL": "\u2555",
+            "boxDl": "\u2556",
+            "boxDL": "\u2557",
+            "boxdr": "\u250C",
+            "boxdR": "\u2552",
+            "boxDr": "\u2553",
+            "boxDR": "\u2554",
+            "boxh": "\u2500",
+            "boxH": "\u2550",
+            "boxhd": "\u252C",
+            "boxHd": "\u2564",
+            "boxhD": "\u2565",
+            "boxHD": "\u2566",
+            "boxhu": "\u2534",
+            "boxHu": "\u2567",
+            "boxhU": "\u2568",
+            "boxHU": "\u2569",
+            "boxminus": "\u229F",
+            "boxplus": "\u229E",
+            "boxtimes": "\u22A0",
+            "boxul": "\u2518",
+            "boxuL": "\u255B",
+            "boxUl": "\u255C",
+            "boxUL": "\u255D",
+            "boxur": "\u2514",
+            "boxuR": "\u2558",
+            "boxUr": "\u2559",
+            "boxUR": "\u255A",
+            "boxv": "\u2502",
+            "boxV": "\u2551",
+            "boxvh": "\u253C",
+            "boxvH": "\u256A",
+            "boxVh": "\u256B",
+            "boxVH": "\u256C",
+            "boxvl": "\u2524",
+            "boxvL": "\u2561",
+            "boxVl": "\u2562",
+            "boxVL": "\u2563",
+            "boxvr": "\u251C",
+            "boxvR": "\u255E",
+            "boxVr": "\u255F",
+            "boxVR": "\u2560",
+            "bprime": "\u2035",
+            "breve": "\u02D8",
+            "Breve": "\u02D8",
+            "brvbar": "\u00A6",
+            "bscr": "\uD835\uDCB7",
+            "Bscr": "\u212C",
+            "bsemi": "\u204F",
+            "bsim": "\u223D",
+            "bsime": "\u22CD",
+            "bsolb": "\u29C5",
+            "bsol": "\\",
+            "bsolhsub": "\u27C8",
+            "bull": "\u2022",
+            "bullet": "\u2022",
+            "bump": "\u224E",
+            "bumpE": "\u2AAE",
+            "bumpe": "\u224F",
+            "Bumpeq": "\u224E",
+            "bumpeq": "\u224F",
+            "Cacute": "\u0106",
+            "cacute": "\u0107",
+            "capand": "\u2A44",
+            "capbrcup": "\u2A49",
+            "capcap": "\u2A4B",
+            "cap": "\u2229",
+            "Cap": "\u22D2",
+            "capcup": "\u2A47",
+            "capdot": "\u2A40",
+            "CapitalDifferentialD": "\u2145",
+            "caps": "\u2229\uFE00",
+            "caret": "\u2041",
+            "caron": "\u02C7",
+            "Cayleys": "\u212D",
+            "ccaps": "\u2A4D",
+            "Ccaron": "\u010C",
+            "ccaron": "\u010D",
+            "Ccedil": "\u00C7",
+            "ccedil": "\u00E7",
+            "Ccirc": "\u0108",
+            "ccirc": "\u0109",
+            "Cconint": "\u2230",
+            "ccups": "\u2A4C",
+            "ccupssm": "\u2A50",
+            "Cdot": "\u010A",
+            "cdot": "\u010B",
+            "cedil": "\u00B8",
+            "Cedilla": "\u00B8",
+            "cemptyv": "\u29B2",
+            "cent": "\u00A2",
+            "centerdot": "\u00B7",
+            "CenterDot": "\u00B7",
+            "cfr": "\uD835\uDD20",
+            "Cfr": "\u212D",
+            "CHcy": "\u0427",
+            "chcy": "\u0447",
+            "check": "\u2713",
+            "checkmark": "\u2713",
+            "Chi": "\u03A7",
+            "chi": "\u03C7",
+            "circ": "\u02C6",
+            "circeq": "\u2257",
+            "circlearrowleft": "\u21BA",
+            "circlearrowright": "\u21BB",
+            "circledast": "\u229B",
+            "circledcirc": "\u229A",
+            "circleddash": "\u229D",
+            "CircleDot": "\u2299",
+            "circledR": "\u00AE",
+            "circledS": "\u24C8",
+            "CircleMinus": "\u2296",
+            "CirclePlus": "\u2295",
+            "CircleTimes": "\u2297",
+            "cir": "\u25CB",
+            "cirE": "\u29C3",
+            "cire": "\u2257",
+            "cirfnint": "\u2A10",
+            "cirmid": "\u2AEF",
+            "cirscir": "\u29C2",
+            "ClockwiseContourIntegral": "\u2232",
+            "CloseCurlyDoubleQuote": "\u201D",
+            "CloseCurlyQuote": "\u2019",
+            "clubs": "\u2663",
+            "clubsuit": "\u2663",
+            "colon": ":",
+            "Colon": "\u2237",
+            "Colone": "\u2A74",
+            "colone": "\u2254",
+            "coloneq": "\u2254",
+            "comma": ",",
+            "commat": "@",
+            "comp": "\u2201",
+            "compfn": "\u2218",
+            "complement": "\u2201",
+            "complexes": "\u2102",
+            "cong": "\u2245",
+            "congdot": "\u2A6D",
+            "Congruent": "\u2261",
+            "conint": "\u222E",
+            "Conint": "\u222F",
+            "ContourIntegral": "\u222E",
+            "copf": "\uD835\uDD54",
+            "Copf": "\u2102",
+            "coprod": "\u2210",
+            "Coproduct": "\u2210",
+            "copy": "\u00A9",
+            "COPY": "\u00A9",
+            "copysr": "\u2117",
+            "CounterClockwiseContourIntegral": "\u2233",
+            "crarr": "\u21B5",
+            "cross": "\u2717",
+            "Cross": "\u2A2F",
+            "Cscr": "\uD835\uDC9E",
+            "cscr": "\uD835\uDCB8",
+            "csub": "\u2ACF",
+            "csube": "\u2AD1",
+            "csup": "\u2AD0",
+            "csupe": "\u2AD2",
+            "ctdot": "\u22EF",
+            "cudarrl": "\u2938",
+            "cudarrr": "\u2935",
+            "cuepr": "\u22DE",
+            "cuesc": "\u22DF",
+            "cularr": "\u21B6",
+            "cularrp": "\u293D",
+            "cupbrcap": "\u2A48",
+            "cupcap": "\u2A46",
+            "CupCap": "\u224D",
+            "cup": "\u222A",
+            "Cup": "\u22D3",
+            "cupcup": "\u2A4A",
+            "cupdot": "\u228D",
+            "cupor": "\u2A45",
+            "cups": "\u222A\uFE00",
+            "curarr": "\u21B7",
+            "curarrm": "\u293C",
+            "curlyeqprec": "\u22DE",
+            "curlyeqsucc": "\u22DF",
+            "curlyvee": "\u22CE",
+            "curlywedge": "\u22CF",
+            "curren": "\u00A4",
+            "curvearrowleft": "\u21B6",
+            "curvearrowright": "\u21B7",
+            "cuvee": "\u22CE",
+            "cuwed": "\u22CF",
+            "cwconint": "\u2232",
+            "cwint": "\u2231",
+            "cylcty": "\u232D",
+            "dagger": "\u2020",
+            "Dagger": "\u2021",
+            "daleth": "\u2138",
+            "darr": "\u2193",
+            "Darr": "\u21A1",
+            "dArr": "\u21D3",
+            "dash": "\u2010",
+            "Dashv": "\u2AE4",
+            "dashv": "\u22A3",
+            "dbkarow": "\u290F",
+            "dblac": "\u02DD",
+            "Dcaron": "\u010E",
+            "dcaron": "\u010F",
+            "Dcy": "\u0414",
+            "dcy": "\u0434",
+            "ddagger": "\u2021",
+            "ddarr": "\u21CA",
+            "DD": "\u2145",
+            "dd": "\u2146",
+            "DDotrahd": "\u2911",
+            "ddotseq": "\u2A77",
+            "deg": "\u00B0",
+            "Del": "\u2207",
+            "Delta": "\u0394",
+            "delta": "\u03B4",
+            "demptyv": "\u29B1",
+            "dfisht": "\u297F",
+            "Dfr": "\uD835\uDD07",
+            "dfr": "\uD835\uDD21",
+            "dHar": "\u2965",
+            "dharl": "\u21C3",
+            "dharr": "\u21C2",
+            "DiacriticalAcute": "\u00B4",
+            "DiacriticalDot": "\u02D9",
+            "DiacriticalDoubleAcute": "\u02DD",
+            "DiacriticalGrave": "`",
+            "DiacriticalTilde": "\u02DC",
+            "diam": "\u22C4",
+            "diamond": "\u22C4",
+            "Diamond": "\u22C4",
+            "diamondsuit": "\u2666",
+            "diams": "\u2666",
+            "die": "\u00A8",
+            "DifferentialD": "\u2146",
+            "digamma": "\u03DD",
+            "disin": "\u22F2",
+            "div": "\u00F7",
+            "divide": "\u00F7",
+            "divideontimes": "\u22C7",
+            "divonx": "\u22C7",
+            "DJcy": "\u0402",
+            "djcy": "\u0452",
+            "dlcorn": "\u231E",
+            "dlcrop": "\u230D",
+            "dollar": "$",
+            "Dopf": "\uD835\uDD3B",
+            "dopf": "\uD835\uDD55",
+            "Dot": "\u00A8",
+            "dot": "\u02D9",
+            "DotDot": "\u20DC",
+            "doteq": "\u2250",
+            "doteqdot": "\u2251",
+            "DotEqual": "\u2250",
+            "dotminus": "\u2238",
+            "dotplus": "\u2214",
+            "dotsquare": "\u22A1",
+            "doublebarwedge": "\u2306",
+            "DoubleContourIntegral": "\u222F",
+            "DoubleDot": "\u00A8",
+            "DoubleDownArrow": "\u21D3",
+            "DoubleLeftArrow": "\u21D0",
+            "DoubleLeftRightArrow": "\u21D4",
+            "DoubleLeftTee": "\u2AE4",
+            "DoubleLongLeftArrow": "\u27F8",
+            "DoubleLongLeftRightArrow": "\u27FA",
+            "DoubleLongRightArrow": "\u27F9",
+            "DoubleRightArrow": "\u21D2",
+            "DoubleRightTee": "\u22A8",
+            "DoubleUpArrow": "\u21D1",
+            "DoubleUpDownArrow": "\u21D5",
+            "DoubleVerticalBar": "\u2225",
+            "DownArrowBar": "\u2913",
+            "downarrow": "\u2193",
+            "DownArrow": "\u2193",
+            "Downarrow": "\u21D3",
+            "DownArrowUpArrow": "\u21F5",
+            "DownBreve": "\u0311",
+            "downdownarrows": "\u21CA",
+            "downharpoonleft": "\u21C3",
+            "downharpoonright": "\u21C2",
+            "DownLeftRightVector": "\u2950",
+            "DownLeftTeeVector": "\u295E",
+            "DownLeftVectorBar": "\u2956",
+            "DownLeftVector": "\u21BD",
+            "DownRightTeeVector": "\u295F",
+            "DownRightVectorBar": "\u2957",
+            "DownRightVector": "\u21C1",
+            "DownTeeArrow": "\u21A7",
+            "DownTee": "\u22A4",
+            "drbkarow": "\u2910",
+            "drcorn": "\u231F",
+            "drcrop": "\u230C",
+            "Dscr": "\uD835\uDC9F",
+            "dscr": "\uD835\uDCB9",
+            "DScy": "\u0405",
+            "dscy": "\u0455",
+            "dsol": "\u29F6",
+            "Dstrok": "\u0110",
+            "dstrok": "\u0111",
+            "dtdot": "\u22F1",
+            "dtri": "\u25BF",
+            "dtrif": "\u25BE",
+            "duarr": "\u21F5",
+            "duhar": "\u296F",
+            "dwangle": "\u29A6",
+            "DZcy": "\u040F",
+            "dzcy": "\u045F",
+            "dzigrarr": "\u27FF",
+            "Eacute": "\u00C9",
+            "eacute": "\u00E9",
+            "easter": "\u2A6E",
+            "Ecaron": "\u011A",
+            "ecaron": "\u011B",
+            "Ecirc": "\u00CA",
+            "ecirc": "\u00EA",
+            "ecir": "\u2256",
+            "ecolon": "\u2255",
+            "Ecy": "\u042D",
+            "ecy": "\u044D",
+            "eDDot": "\u2A77",
+            "Edot": "\u0116",
+            "edot": "\u0117",
+            "eDot": "\u2251",
+            "ee": "\u2147",
+            "efDot": "\u2252",
+            "Efr": "\uD835\uDD08",
+            "efr": "\uD835\uDD22",
+            "eg": "\u2A9A",
+            "Egrave": "\u00C8",
+            "egrave": "\u00E8",
+            "egs": "\u2A96",
+            "egsdot": "\u2A98",
+            "el": "\u2A99",
+            "Element": "\u2208",
+            "elinters": "\u23E7",
+            "ell": "\u2113",
+            "els": "\u2A95",
+            "elsdot": "\u2A97",
+            "Emacr": "\u0112",
+            "emacr": "\u0113",
+            "empty": "\u2205",
+            "emptyset": "\u2205",
+            "EmptySmallSquare": "\u25FB",
+            "emptyv": "\u2205",
+            "EmptyVerySmallSquare": "\u25AB",
+            "emsp13": "\u2004",
+            "emsp14": "\u2005",
+            "emsp": "\u2003",
+            "ENG": "\u014A",
+            "eng": "\u014B",
+            "ensp": "\u2002",
+            "Eogon": "\u0118",
+            "eogon": "\u0119",
+            "Eopf": "\uD835\uDD3C",
+            "eopf": "\uD835\uDD56",
+            "epar": "\u22D5",
+            "eparsl": "\u29E3",
+            "eplus": "\u2A71",
+            "epsi": "\u03B5",
+            "Epsilon": "\u0395",
+            "epsilon": "\u03B5",
+            "epsiv": "\u03F5",
+            "eqcirc": "\u2256",
+            "eqcolon": "\u2255",
+            "eqsim": "\u2242",
+            "eqslantgtr": "\u2A96",
+            "eqslantless": "\u2A95",
+            "Equal": "\u2A75",
+            "equals": "=",
+            "EqualTilde": "\u2242",
+            "equest": "\u225F",
+            "Equilibrium": "\u21CC",
+            "equiv": "\u2261",
+            "equivDD": "\u2A78",
+            "eqvparsl": "\u29E5",
+            "erarr": "\u2971",
+            "erDot": "\u2253",
+            "escr": "\u212F",
+            "Escr": "\u2130",
+            "esdot": "\u2250",
+            "Esim": "\u2A73",
+            "esim": "\u2242",
+            "Eta": "\u0397",
+            "eta": "\u03B7",
+            "ETH": "\u00D0",
+            "eth": "\u00F0",
+            "Euml": "\u00CB",
+            "euml": "\u00EB",
+            "euro": "\u20AC",
+            "excl": "!",
+            "exist": "\u2203",
+            "Exists": "\u2203",
+            "expectation": "\u2130",
+            "exponentiale": "\u2147",
+            "ExponentialE": "\u2147",
+            "fallingdotseq": "\u2252",
+            "Fcy": "\u0424",
+            "fcy": "\u0444",
+            "female": "\u2640",
+            "ffilig": "\uFB03",
+            "fflig": "\uFB00",
+            "ffllig": "\uFB04",
+            "Ffr": "\uD835\uDD09",
+            "ffr": "\uD835\uDD23",
+            "filig": "\uFB01",
+            "FilledSmallSquare": "\u25FC",
+            "FilledVerySmallSquare": "\u25AA",
+            "fjlig": "fj",
+            "flat": "\u266D",
+            "fllig": "\uFB02",
+            "fltns": "\u25B1",
+            "fnof": "\u0192",
+            "Fopf": "\uD835\uDD3D",
+            "fopf": "\uD835\uDD57",
+            "forall": "\u2200",
+            "ForAll": "\u2200",
+            "fork": "\u22D4",
+            "forkv": "\u2AD9",
+            "Fouriertrf": "\u2131",
+            "fpartint": "\u2A0D",
+            "frac12": "\u00BD",
+            "frac13": "\u2153",
+            "frac14": "\u00BC",
+            "frac15": "\u2155",
+            "frac16": "\u2159",
+            "frac18": "\u215B",
+            "frac23": "\u2154",
+            "frac25": "\u2156",
+            "frac34": "\u00BE",
+            "frac35": "\u2157",
+            "frac38": "\u215C",
+            "frac45": "\u2158",
+            "frac56": "\u215A",
+            "frac58": "\u215D",
+            "frac78": "\u215E",
+            "frasl": "\u2044",
+            "frown": "\u2322",
+            "fscr": "\uD835\uDCBB",
+            "Fscr": "\u2131",
+            "gacute": "\u01F5",
+            "Gamma": "\u0393",
+            "gamma": "\u03B3",
+            "Gammad": "\u03DC",
+            "gammad": "\u03DD",
+            "gap": "\u2A86",
+            "Gbreve": "\u011E",
+            "gbreve": "\u011F",
+            "Gcedil": "\u0122",
+            "Gcirc": "\u011C",
+            "gcirc": "\u011D",
+            "Gcy": "\u0413",
+            "gcy": "\u0433",
+            "Gdot": "\u0120",
+            "gdot": "\u0121",
+            "ge": "\u2265",
+            "gE": "\u2267",
+            "gEl": "\u2A8C",
+            "gel": "\u22DB",
+            "geq": "\u2265",
+            "geqq": "\u2267",
+            "geqslant": "\u2A7E",
+            "gescc": "\u2AA9",
+            "ges": "\u2A7E",
+            "gesdot": "\u2A80",
+            "gesdoto": "\u2A82",
+            "gesdotol": "\u2A84",
+            "gesl": "\u22DB\uFE00",
+            "gesles": "\u2A94",
+            "Gfr": "\uD835\uDD0A",
+            "gfr": "\uD835\uDD24",
+            "gg": "\u226B",
+            "Gg": "\u22D9",
+            "ggg": "\u22D9",
+            "gimel": "\u2137",
+            "GJcy": "\u0403",
+            "gjcy": "\u0453",
+            "gla": "\u2AA5",
+            "gl": "\u2277",
+            "glE": "\u2A92",
+            "glj": "\u2AA4",
+            "gnap": "\u2A8A",
+            "gnapprox": "\u2A8A",
+            "gne": "\u2A88",
+            "gnE": "\u2269",
+            "gneq": "\u2A88",
+            "gneqq": "\u2269",
+            "gnsim": "\u22E7",
+            "Gopf": "\uD835\uDD3E",
+            "gopf": "\uD835\uDD58",
+            "grave": "`",
+            "GreaterEqual": "\u2265",
+            "GreaterEqualLess": "\u22DB",
+            "GreaterFullEqual": "\u2267",
+            "GreaterGreater": "\u2AA2",
+            "GreaterLess": "\u2277",
+            "GreaterSlantEqual": "\u2A7E",
+            "GreaterTilde": "\u2273",
+            "Gscr": "\uD835\uDCA2",
+            "gscr": "\u210A",
+            "gsim": "\u2273",
+            "gsime": "\u2A8E",
+            "gsiml": "\u2A90",
+            "gtcc": "\u2AA7",
+            "gtcir": "\u2A7A",
+            "gt": ">",
+            "GT": ">",
+            "Gt": "\u226B",
+            "gtdot": "\u22D7",
+            "gtlPar": "\u2995",
+            "gtquest": "\u2A7C",
+            "gtrapprox": "\u2A86",
+            "gtrarr": "\u2978",
+            "gtrdot": "\u22D7",
+            "gtreqless": "\u22DB",
+            "gtreqqless": "\u2A8C",
+            "gtrless": "\u2277",
+            "gtrsim": "\u2273",
+            "gvertneqq": "\u2269\uFE00",
+            "gvnE": "\u2269\uFE00",
+            "Hacek": "\u02C7",
+            "hairsp": "\u200A",
+            "half": "\u00BD",
+            "hamilt": "\u210B",
+            "HARDcy": "\u042A",
+            "hardcy": "\u044A",
+            "harrcir": "\u2948",
+            "harr": "\u2194",
+            "hArr": "\u21D4",
+            "harrw": "\u21AD",
+            "Hat": "^",
+            "hbar": "\u210F",
+            "Hcirc": "\u0124",
+            "hcirc": "\u0125",
+            "hearts": "\u2665",
+            "heartsuit": "\u2665",
+            "hellip": "\u2026",
+            "hercon": "\u22B9",
+            "hfr": "\uD835\uDD25",
+            "Hfr": "\u210C",
+            "HilbertSpace": "\u210B",
+            "hksearow": "\u2925",
+            "hkswarow": "\u2926",
+            "hoarr": "\u21FF",
+            "homtht": "\u223B",
+            "hookleftarrow": "\u21A9",
+            "hookrightarrow": "\u21AA",
+            "hopf": "\uD835\uDD59",
+            "Hopf": "\u210D",
+            "horbar": "\u2015",
+            "HorizontalLine": "\u2500",
+            "hscr": "\uD835\uDCBD",
+            "Hscr": "\u210B",
+            "hslash": "\u210F",
+            "Hstrok": "\u0126",
+            "hstrok": "\u0127",
+            "HumpDownHump": "\u224E",
+            "HumpEqual": "\u224F",
+            "hybull": "\u2043",
+            "hyphen": "\u2010",
+            "Iacute": "\u00CD",
+            "iacute": "\u00ED",
+            "ic": "\u2063",
+            "Icirc": "\u00CE",
+            "icirc": "\u00EE",
+            "Icy": "\u0418",
+            "icy": "\u0438",
+            "Idot": "\u0130",
+            "IEcy": "\u0415",
+            "iecy": "\u0435",
+            "iexcl": "\u00A1",
+            "iff": "\u21D4",
+            "ifr": "\uD835\uDD26",
+            "Ifr": "\u2111",
+            "Igrave": "\u00CC",
+            "igrave": "\u00EC",
+            "ii": "\u2148",
+            "iiiint": "\u2A0C",
+            "iiint": "\u222D",
+            "iinfin": "\u29DC",
+            "iiota": "\u2129",
+            "IJlig": "\u0132",
+            "ijlig": "\u0133",
+            "Imacr": "\u012A",
+            "imacr": "\u012B",
+            "image": "\u2111",
+            "ImaginaryI": "\u2148",
+            "imagline": "\u2110",
+            "imagpart": "\u2111",
+            "imath": "\u0131",
+            "Im": "\u2111",
+            "imof": "\u22B7",
+            "imped": "\u01B5",
+            "Implies": "\u21D2",
+            "incare": "\u2105",
+            "in": "\u2208",
+            "infin": "\u221E",
+            "infintie": "\u29DD",
+            "inodot": "\u0131",
+            "intcal": "\u22BA",
+            "int": "\u222B",
+            "Int": "\u222C",
+            "integers": "\u2124",
+            "Integral": "\u222B",
+            "intercal": "\u22BA",
+            "Intersection": "\u22C2",
+            "intlarhk": "\u2A17",
+            "intprod": "\u2A3C",
+            "InvisibleComma": "\u2063",
+            "InvisibleTimes": "\u2062",
+            "IOcy": "\u0401",
+            "iocy": "\u0451",
+            "Iogon": "\u012E",
+            "iogon": "\u012F",
+            "Iopf": "\uD835\uDD40",
+            "iopf": "\uD835\uDD5A",
+            "Iota": "\u0399",
+            "iota": "\u03B9",
+            "iprod": "\u2A3C",
+            "iquest": "\u00BF",
+            "iscr": "\uD835\uDCBE",
+            "Iscr": "\u2110",
+            "isin": "\u2208",
+            "isindot": "\u22F5",
+            "isinE": "\u22F9",
+            "isins": "\u22F4",
+            "isinsv": "\u22F3",
+            "isinv": "\u2208",
+            "it": "\u2062",
+            "Itilde": "\u0128",
+            "itilde": "\u0129",
+            "Iukcy": "\u0406",
+            "iukcy": "\u0456",
+            "Iuml": "\u00CF",
+            "iuml": "\u00EF",
+            "Jcirc": "\u0134",
+            "jcirc": "\u0135",
+            "Jcy": "\u0419",
+            "jcy": "\u0439",
+            "Jfr": "\uD835\uDD0D",
+            "jfr": "\uD835\uDD27",
+            "jmath": "\u0237",
+            "Jopf": "\uD835\uDD41",
+            "jopf": "\uD835\uDD5B",
+            "Jscr": "\uD835\uDCA5",
+            "jscr": "\uD835\uDCBF",
+            "Jsercy": "\u0408",
+            "jsercy": "\u0458",
+            "Jukcy": "\u0404",
+            "jukcy": "\u0454",
+            "Kappa": "\u039A",
+            "kappa": "\u03BA",
+            "kappav": "\u03F0",
+            "Kcedil": "\u0136",
+            "kcedil": "\u0137",
+            "Kcy": "\u041A",
+            "kcy": "\u043A",
+            "Kfr": "\uD835\uDD0E",
+            "kfr": "\uD835\uDD28",
+            "kgreen": "\u0138",
+            "KHcy": "\u0425",
+            "khcy": "\u0445",
+            "KJcy": "\u040C",
+            "kjcy": "\u045C",
+            "Kopf": "\uD835\uDD42",
+            "kopf": "\uD835\uDD5C",
+            "Kscr": "\uD835\uDCA6",
+            "kscr": "\uD835\uDCC0",
+            "lAarr": "\u21DA",
+            "Lacute": "\u0139",
+            "lacute": "\u013A",
+            "laemptyv": "\u29B4",
+            "lagran": "\u2112",
+            "Lambda": "\u039B",
+            "lambda": "\u03BB",
+            "lang": "\u27E8",
+            "Lang": "\u27EA",
+            "langd": "\u2991",
+            "langle": "\u27E8",
+            "lap": "\u2A85",
+            "Laplacetrf": "\u2112",
+            "laquo": "\u00AB",
+            "larrb": "\u21E4",
+            "larrbfs": "\u291F",
+            "larr": "\u2190",
+            "Larr": "\u219E",
+            "lArr": "\u21D0",
+            "larrfs": "\u291D",
+            "larrhk": "\u21A9",
+            "larrlp": "\u21AB",
+            "larrpl": "\u2939",
+            "larrsim": "\u2973",
+            "larrtl": "\u21A2",
+            "latail": "\u2919",
+            "lAtail": "\u291B",
+            "lat": "\u2AAB",
+            "late": "\u2AAD",
+            "lates": "\u2AAD\uFE00",
+            "lbarr": "\u290C",
+            "lBarr": "\u290E",
+            "lbbrk": "\u2772",
+            "lbrace": "{",
+            "lbrack": "[",
+            "lbrke": "\u298B",
+            "lbrksld": "\u298F",
+            "lbrkslu": "\u298D",
+            "Lcaron": "\u013D",
+            "lcaron": "\u013E",
+            "Lcedil": "\u013B",
+            "lcedil": "\u013C",
+            "lceil": "\u2308",
+            "lcub": "{",
+            "Lcy": "\u041B",
+            "lcy": "\u043B",
+            "ldca": "\u2936",
+            "ldquo": "\u201C",
+            "ldquor": "\u201E",
+            "ldrdhar": "\u2967",
+            "ldrushar": "\u294B",
+            "ldsh": "\u21B2",
+            "le": "\u2264",
+            "lE": "\u2266",
+            "LeftAngleBracket": "\u27E8",
+            "LeftArrowBar": "\u21E4",
+            "leftarrow": "\u2190",
+            "LeftArrow": "\u2190",
+            "Leftarrow": "\u21D0",
+            "LeftArrowRightArrow": "\u21C6",
+            "leftarrowtail": "\u21A2",
+            "LeftCeiling": "\u2308",
+            "LeftDoubleBracket": "\u27E6",
+            "LeftDownTeeVector": "\u2961",
+            "LeftDownVectorBar": "\u2959",
+            "LeftDownVector": "\u21C3",
+            "LeftFloor": "\u230A",
+            "leftharpoondown": "\u21BD",
+            "leftharpoonup": "\u21BC",
+            "leftleftarrows": "\u21C7",
+            "leftrightarrow": "\u2194",
+            "LeftRightArrow": "\u2194",
+            "Leftrightarrow": "\u21D4",
+            "leftrightarrows": "\u21C6",
+            "leftrightharpoons": "\u21CB",
+            "leftrightsquigarrow": "\u21AD",
+            "LeftRightVector": "\u294E",
+            "LeftTeeArrow": "\u21A4",
+            "LeftTee": "\u22A3",
+            "LeftTeeVector": "\u295A",
+            "leftthreetimes": "\u22CB",
+            "LeftTriangleBar": "\u29CF",
+            "LeftTriangle": "\u22B2",
+            "LeftTriangleEqual": "\u22B4",
+            "LeftUpDownVector": "\u2951",
+            "LeftUpTeeVector": "\u2960",
+            "LeftUpVectorBar": "\u2958",
+            "LeftUpVector": "\u21BF",
+            "LeftVectorBar": "\u2952",
+            "LeftVector": "\u21BC",
+            "lEg": "\u2A8B",
+            "leg": "\u22DA",
+            "leq": "\u2264",
+            "leqq": "\u2266",
+            "leqslant": "\u2A7D",
+            "lescc": "\u2AA8",
+            "les": "\u2A7D",
+            "lesdot": "\u2A7F",
+            "lesdoto": "\u2A81",
+            "lesdotor": "\u2A83",
+            "lesg": "\u22DA\uFE00",
+            "lesges": "\u2A93",
+            "lessapprox": "\u2A85",
+            "lessdot": "\u22D6",
+            "lesseqgtr": "\u22DA",
+            "lesseqqgtr": "\u2A8B",
+            "LessEqualGreater": "\u22DA",
+            "LessFullEqual": "\u2266",
+            "LessGreater": "\u2276",
+            "lessgtr": "\u2276",
+            "LessLess": "\u2AA1",
+            "lesssim": "\u2272",
+            "LessSlantEqual": "\u2A7D",
+            "LessTilde": "\u2272",
+            "lfisht": "\u297C",
+            "lfloor": "\u230A",
+            "Lfr": "\uD835\uDD0F",
+            "lfr": "\uD835\uDD29",
+            "lg": "\u2276",
+            "lgE": "\u2A91",
+            "lHar": "\u2962",
+            "lhard": "\u21BD",
+            "lharu": "\u21BC",
+            "lharul": "\u296A",
+            "lhblk": "\u2584",
+            "LJcy": "\u0409",
+            "ljcy": "\u0459",
+            "llarr": "\u21C7",
+            "ll": "\u226A",
+            "Ll": "\u22D8",
+            "llcorner": "\u231E",
+            "Lleftarrow": "\u21DA",
+            "llhard": "\u296B",
+            "lltri": "\u25FA",
+            "Lmidot": "\u013F",
+            "lmidot": "\u0140",
+            "lmoustache": "\u23B0",
+            "lmoust": "\u23B0",
+            "lnap": "\u2A89",
+            "lnapprox": "\u2A89",
+            "lne": "\u2A87",
+            "lnE": "\u2268",
+            "lneq": "\u2A87",
+            "lneqq": "\u2268",
+            "lnsim": "\u22E6",
+            "loang": "\u27EC",
+            "loarr": "\u21FD",
+            "lobrk": "\u27E6",
+            "longleftarrow": "\u27F5",
+            "LongLeftArrow": "\u27F5",
+            "Longleftarrow": "\u27F8",
+            "longleftrightarrow": "\u27F7",
+            "LongLeftRightArrow": "\u27F7",
+            "Longleftrightarrow": "\u27FA",
+            "longmapsto": "\u27FC",
+            "longrightarrow": "\u27F6",
+            "LongRightArrow": "\u27F6",
+            "Longrightarrow": "\u27F9",
+            "looparrowleft": "\u21AB",
+            "looparrowright": "\u21AC",
+            "lopar": "\u2985",
+            "Lopf": "\uD835\uDD43",
+            "lopf": "\uD835\uDD5D",
+            "loplus": "\u2A2D",
+            "lotimes": "\u2A34",
+            "lowast": "\u2217",
+            "lowbar": "_",
+            "LowerLeftArrow": "\u2199",
+            "LowerRightArrow": "\u2198",
+            "loz": "\u25CA",
+            "lozenge": "\u25CA",
+            "lozf": "\u29EB",
+            "lpar": "(",
+            "lparlt": "\u2993",
+            "lrarr": "\u21C6",
+            "lrcorner": "\u231F",
+            "lrhar": "\u21CB",
+            "lrhard": "\u296D",
+            "lrm": "\u200E",
+            "lrtri": "\u22BF",
+            "lsaquo": "\u2039",
+            "lscr": "\uD835\uDCC1",
+            "Lscr": "\u2112",
+            "lsh": "\u21B0",
+            "Lsh": "\u21B0",
+            "lsim": "\u2272",
+            "lsime": "\u2A8D",
+            "lsimg": "\u2A8F",
+            "lsqb": "[",
+            "lsquo": "\u2018",
+            "lsquor": "\u201A",
+            "Lstrok": "\u0141",
+            "lstrok": "\u0142",
+            "ltcc": "\u2AA6",
+            "ltcir": "\u2A79",
+            "lt": "<",
+            "LT": "<",
+            "Lt": "\u226A",
+            "ltdot": "\u22D6",
+            "lthree": "\u22CB",
+            "ltimes": "\u22C9",
+            "ltlarr": "\u2976",
+            "ltquest": "\u2A7B",
+            "ltri": "\u25C3",
+            "ltrie": "\u22B4",
+            "ltrif": "\u25C2",
+            "ltrPar": "\u2996",
+            "lurdshar": "\u294A",
+            "luruhar": "\u2966",
+            "lvertneqq": "\u2268\uFE00",
+            "lvnE": "\u2268\uFE00",
+            "macr": "\u00AF",
+            "male": "\u2642",
+            "malt": "\u2720",
+            "maltese": "\u2720",
+            "Map": "\u2905",
+            "map": "\u21A6",
+            "mapsto": "\u21A6",
+            "mapstodown": "\u21A7",
+            "mapstoleft": "\u21A4",
+            "mapstoup": "\u21A5",
+            "marker": "\u25AE",
+            "mcomma": "\u2A29",
+            "Mcy": "\u041C",
+            "mcy": "\u043C",
+            "mdash": "\u2014",
+            "mDDot": "\u223A",
+            "measuredangle": "\u2221",
+            "MediumSpace": "\u205F",
+            "Mellintrf": "\u2133",
+            "Mfr": "\uD835\uDD10",
+            "mfr": "\uD835\uDD2A",
+            "mho": "\u2127",
+            "micro": "\u00B5",
+            "midast": "*",
+            "midcir": "\u2AF0",
+            "mid": "\u2223",
+            "middot": "\u00B7",
+            "minusb": "\u229F",
+            "minus": "\u2212",
+            "minusd": "\u2238",
+            "minusdu": "\u2A2A",
+            "MinusPlus": "\u2213",
+            "mlcp": "\u2ADB",
+            "mldr": "\u2026",
+            "mnplus": "\u2213",
+            "models": "\u22A7",
+            "Mopf": "\uD835\uDD44",
+            "mopf": "\uD835\uDD5E",
+            "mp": "\u2213",
+            "mscr": "\uD835\uDCC2",
+            "Mscr": "\u2133",
+            "mstpos": "\u223E",
+            "Mu": "\u039C",
+            "mu": "\u03BC",
+            "multimap": "\u22B8",
+            "mumap": "\u22B8",
+            "nabla": "\u2207",
+            "Nacute": "\u0143",
+            "nacute": "\u0144",
+            "nang": "\u2220\u20D2",
+            "nap": "\u2249",
+            "napE": "\u2A70\u0338",
+            "napid": "\u224B\u0338",
+            "napos": "\u0149",
+            "napprox": "\u2249",
+            "natural": "\u266E",
+            "naturals": "\u2115",
+            "natur": "\u266E",
+            "nbsp": "\u00A0",
+            "nbump": "\u224E\u0338",
+            "nbumpe": "\u224F\u0338",
+            "ncap": "\u2A43",
+            "Ncaron": "\u0147",
+            "ncaron": "\u0148",
+            "Ncedil": "\u0145",
+            "ncedil": "\u0146",
+            "ncong": "\u2247",
+            "ncongdot": "\u2A6D\u0338",
+            "ncup": "\u2A42",
+            "Ncy": "\u041D",
+            "ncy": "\u043D",
+            "ndash": "\u2013",
+            "nearhk": "\u2924",
+            "nearr": "\u2197",
+            "neArr": "\u21D7",
+            "nearrow": "\u2197",
+            "ne": "\u2260",
+            "nedot": "\u2250\u0338",
+            "NegativeMediumSpace": "\u200B",
+            "NegativeThickSpace": "\u200B",
+            "NegativeThinSpace": "\u200B",
+            "NegativeVeryThinSpace": "\u200B",
+            "nequiv": "\u2262",
+            "nesear": "\u2928",
+            "nesim": "\u2242\u0338",
+            "NestedGreaterGreater": "\u226B",
+            "NestedLessLess": "\u226A",
+            "NewLine": "\n",
+            "nexist": "\u2204",
+            "nexists": "\u2204",
+            "Nfr": "\uD835\uDD11",
+            "nfr": "\uD835\uDD2B",
+            "ngE": "\u2267\u0338",
+            "nge": "\u2271",
+            "ngeq": "\u2271",
+            "ngeqq": "\u2267\u0338",
+            "ngeqslant": "\u2A7E\u0338",
+            "nges": "\u2A7E\u0338",
+            "nGg": "\u22D9\u0338",
+            "ngsim": "\u2275",
+            "nGt": "\u226B\u20D2",
+            "ngt": "\u226F",
+            "ngtr": "\u226F",
+            "nGtv": "\u226B\u0338",
+            "nharr": "\u21AE",
+            "nhArr": "\u21CE",
+            "nhpar": "\u2AF2",
+            "ni": "\u220B",
+            "nis": "\u22FC",
+            "nisd": "\u22FA",
+            "niv": "\u220B",
+            "NJcy": "\u040A",
+            "njcy": "\u045A",
+            "nlarr": "\u219A",
+            "nlArr": "\u21CD",
+            "nldr": "\u2025",
+            "nlE": "\u2266\u0338",
+            "nle": "\u2270",
+            "nleftarrow": "\u219A",
+            "nLeftarrow": "\u21CD",
+            "nleftrightarrow": "\u21AE",
+            "nLeftrightarrow": "\u21CE",
+            "nleq": "\u2270",
+            "nleqq": "\u2266\u0338",
+            "nleqslant": "\u2A7D\u0338",
+            "nles": "\u2A7D\u0338",
+            "nless": "\u226E",
+            "nLl": "\u22D8\u0338",
+            "nlsim": "\u2274",
+            "nLt": "\u226A\u20D2",
+            "nlt": "\u226E",
+            "nltri": "\u22EA",
+            "nltrie": "\u22EC",
+            "nLtv": "\u226A\u0338",
+            "nmid": "\u2224",
+            "NoBreak": "\u2060",
+            "NonBreakingSpace": "\u00A0",
+            "nopf": "\uD835\uDD5F",
+            "Nopf": "\u2115",
+            "Not": "\u2AEC",
+            "not": "\u00AC",
+            "NotCongruent": "\u2262",
+            "NotCupCap": "\u226D",
+            "NotDoubleVerticalBar": "\u2226",
+            "NotElement": "\u2209",
+            "NotEqual": "\u2260",
+            "NotEqualTilde": "\u2242\u0338",
+            "NotExists": "\u2204",
+            "NotGreater": "\u226F",
+            "NotGreaterEqual": "\u2271",
+            "NotGreaterFullEqual": "\u2267\u0338",
+            "NotGreaterGreater": "\u226B\u0338",
+            "NotGreaterLess": "\u2279",
+            "NotGreaterSlantEqual": "\u2A7E\u0338",
+            "NotGreaterTilde": "\u2275",
+            "NotHumpDownHump": "\u224E\u0338",
+            "NotHumpEqual": "\u224F\u0338",
+            "notin": "\u2209",
+            "notindot": "\u22F5\u0338",
+            "notinE": "\u22F9\u0338",
+            "notinva": "\u2209",
+            "notinvb": "\u22F7",
+            "notinvc": "\u22F6",
+            "NotLeftTriangleBar": "\u29CF\u0338",
+            "NotLeftTriangle": "\u22EA",
+            "NotLeftTriangleEqual": "\u22EC",
+            "NotLess": "\u226E",
+            "NotLessEqual": "\u2270",
+            "NotLessGreater": "\u2278",
+            "NotLessLess": "\u226A\u0338",
+            "NotLessSlantEqual": "\u2A7D\u0338",
+            "NotLessTilde": "\u2274",
+            "NotNestedGreaterGreater": "\u2AA2\u0338",
+            "NotNestedLessLess": "\u2AA1\u0338",
+            "notni": "\u220C",
+            "notniva": "\u220C",
+            "notnivb": "\u22FE",
+            "notnivc": "\u22FD",
+            "NotPrecedes": "\u2280",
+            "NotPrecedesEqual": "\u2AAF\u0338",
+            "NotPrecedesSlantEqual": "\u22E0",
+            "NotReverseElement": "\u220C",
+            "NotRightTriangleBar": "\u29D0\u0338",
+            "NotRightTriangle": "\u22EB",
+            "NotRightTriangleEqual": "\u22ED",
+            "NotSquareSubset": "\u228F\u0338",
+            "NotSquareSubsetEqual": "\u22E2",
+            "NotSquareSuperset": "\u2290\u0338",
+            "NotSquareSupersetEqual": "\u22E3",
+            "NotSubset": "\u2282\u20D2",
+            "NotSubsetEqual": "\u2288",
+            "NotSucceeds": "\u2281",
+            "NotSucceedsEqual": "\u2AB0\u0338",
+            "NotSucceedsSlantEqual": "\u22E1",
+            "NotSucceedsTilde": "\u227F\u0338",
+            "NotSuperset": "\u2283\u20D2",
+            "NotSupersetEqual": "\u2289",
+            "NotTilde": "\u2241",
+            "NotTildeEqual": "\u2244",
+            "NotTildeFullEqual": "\u2247",
+            "NotTildeTilde": "\u2249",
+            "NotVerticalBar": "\u2224",
+            "nparallel": "\u2226",
+            "npar": "\u2226",
+            "nparsl": "\u2AFD\u20E5",
+            "npart": "\u2202\u0338",
+            "npolint": "\u2A14",
+            "npr": "\u2280",
+            "nprcue": "\u22E0",
+            "nprec": "\u2280",
+            "npreceq": "\u2AAF\u0338",
+            "npre": "\u2AAF\u0338",
+            "nrarrc": "\u2933\u0338",
+            "nrarr": "\u219B",
+            "nrArr": "\u21CF",
+            "nrarrw": "\u219D\u0338",
+            "nrightarrow": "\u219B",
+            "nRightarrow": "\u21CF",
+            "nrtri": "\u22EB",
+            "nrtrie": "\u22ED",
+            "nsc": "\u2281",
+            "nsccue": "\u22E1",
+            "nsce": "\u2AB0\u0338",
+            "Nscr": "\uD835\uDCA9",
+            "nscr": "\uD835\uDCC3",
+            "nshortmid": "\u2224",
+            "nshortparallel": "\u2226",
+            "nsim": "\u2241",
+            "nsime": "\u2244",
+            "nsimeq": "\u2244",
+            "nsmid": "\u2224",
+            "nspar": "\u2226",
+            "nsqsube": "\u22E2",
+            "nsqsupe": "\u22E3",
+            "nsub": "\u2284",
+            "nsubE": "\u2AC5\u0338",
+            "nsube": "\u2288",
+            "nsubset": "\u2282\u20D2",
+            "nsubseteq": "\u2288",
+            "nsubseteqq": "\u2AC5\u0338",
+            "nsucc": "\u2281",
+            "nsucceq": "\u2AB0\u0338",
+            "nsup": "\u2285",
+            "nsupE": "\u2AC6\u0338",
+            "nsupe": "\u2289",
+            "nsupset": "\u2283\u20D2",
+            "nsupseteq": "\u2289",
+            "nsupseteqq": "\u2AC6\u0338",
+            "ntgl": "\u2279",
+            "Ntilde": "\u00D1",
+            "ntilde": "\u00F1",
+            "ntlg": "\u2278",
+            "ntriangleleft": "\u22EA",
+            "ntrianglelefteq": "\u22EC",
+            "ntriangleright": "\u22EB",
+            "ntrianglerighteq": "\u22ED",
+            "Nu": "\u039D",
+            "nu": "\u03BD",
+            "num": "#",
+            "numero": "\u2116",
+            "numsp": "\u2007",
+            "nvap": "\u224D\u20D2",
+            "nvdash": "\u22AC",
+            "nvDash": "\u22AD",
+            "nVdash": "\u22AE",
+            "nVDash": "\u22AF",
+            "nvge": "\u2265\u20D2",
+            "nvgt": ">\u20D2",
+            "nvHarr": "\u2904",
+            "nvinfin": "\u29DE",
+            "nvlArr": "\u2902",
+            "nvle": "\u2264\u20D2",
+            "nvlt": "<\u20D2",
+            "nvltrie": "\u22B4\u20D2",
+            "nvrArr": "\u2903",
+            "nvrtrie": "\u22B5\u20D2",
+            "nvsim": "\u223C\u20D2",
+            "nwarhk": "\u2923",
+            "nwarr": "\u2196",
+            "nwArr": "\u21D6",
+            "nwarrow": "\u2196",
+            "nwnear": "\u2927",
+            "Oacute": "\u00D3",
+            "oacute": "\u00F3",
+            "oast": "\u229B",
+            "Ocirc": "\u00D4",
+            "ocirc": "\u00F4",
+            "ocir": "\u229A",
+            "Ocy": "\u041E",
+            "ocy": "\u043E",
+            "odash": "\u229D",
+            "Odblac": "\u0150",
+            "odblac": "\u0151",
+            "odiv": "\u2A38",
+            "odot": "\u2299",
+            "odsold": "\u29BC",
+            "OElig": "\u0152",
+            "oelig": "\u0153",
+            "ofcir": "\u29BF",
+            "Ofr": "\uD835\uDD12",
+            "ofr": "\uD835\uDD2C",
+            "ogon": "\u02DB",
+            "Ograve": "\u00D2",
+            "ograve": "\u00F2",
+            "ogt": "\u29C1",
+            "ohbar": "\u29B5",
+            "ohm": "\u03A9",
+            "oint": "\u222E",
+            "olarr": "\u21BA",
+            "olcir": "\u29BE",
+            "olcross": "\u29BB",
+            "oline": "\u203E",
+            "olt": "\u29C0",
+            "Omacr": "\u014C",
+            "omacr": "\u014D",
+            "Omega": "\u03A9",
+            "omega": "\u03C9",
+            "Omicron": "\u039F",
+            "omicron": "\u03BF",
+            "omid": "\u29B6",
+            "ominus": "\u2296",
+            "Oopf": "\uD835\uDD46",
+            "oopf": "\uD835\uDD60",
+            "opar": "\u29B7",
+            "OpenCurlyDoubleQuote": "\u201C",
+            "OpenCurlyQuote": "\u2018",
+            "operp": "\u29B9",
+            "oplus": "\u2295",
+            "orarr": "\u21BB",
+            "Or": "\u2A54",
+            "or": "\u2228",
+            "ord": "\u2A5D",
+            "order": "\u2134",
+            "orderof": "\u2134",
+            "ordf": "\u00AA",
+            "ordm": "\u00BA",
+            "origof": "\u22B6",
+            "oror": "\u2A56",
+            "orslope": "\u2A57",
+            "orv": "\u2A5B",
+            "oS": "\u24C8",
+            "Oscr": "\uD835\uDCAA",
+            "oscr": "\u2134",
+            "Oslash": "\u00D8",
+            "oslash": "\u00F8",
+            "osol": "\u2298",
+            "Otilde": "\u00D5",
+            "otilde": "\u00F5",
+            "otimesas": "\u2A36",
+            "Otimes": "\u2A37",
+            "otimes": "\u2297",
+            "Ouml": "\u00D6",
+            "ouml": "\u00F6",
+            "ovbar": "\u233D",
+            "OverBar": "\u203E",
+            "OverBrace": "\u23DE",
+            "OverBracket": "\u23B4",
+            "OverParenthesis": "\u23DC",
+            "para": "\u00B6",
+            "parallel": "\u2225",
+            "par": "\u2225",
+            "parsim": "\u2AF3",
+            "parsl": "\u2AFD",
+            "part": "\u2202",
+            "PartialD": "\u2202",
+            "Pcy": "\u041F",
+            "pcy": "\u043F",
+            "percnt": "%",
+            "period": ".",
+            "permil": "\u2030",
+            "perp": "\u22A5",
+            "pertenk": "\u2031",
+            "Pfr": "\uD835\uDD13",
+            "pfr": "\uD835\uDD2D",
+            "Phi": "\u03A6",
+            "phi": "\u03C6",
+            "phiv": "\u03D5",
+            "phmmat": "\u2133",
+            "phone": "\u260E",
+            "Pi": "\u03A0",
+            "pi": "\u03C0",
+            "pitchfork": "\u22D4",
+            "piv": "\u03D6",
+            "planck": "\u210F",
+            "planckh": "\u210E",
+            "plankv": "\u210F",
+            "plusacir": "\u2A23",
+            "plusb": "\u229E",
+            "pluscir": "\u2A22",
+            "plus": "+",
+            "plusdo": "\u2214",
+            "plusdu": "\u2A25",
+            "pluse": "\u2A72",
+            "PlusMinus": "\u00B1",
+            "plusmn": "\u00B1",
+            "plussim": "\u2A26",
+            "plustwo": "\u2A27",
+            "pm": "\u00B1",
+            "Poincareplane": "\u210C",
+            "pointint": "\u2A15",
+            "popf": "\uD835\uDD61",
+            "Popf": "\u2119",
+            "pound": "\u00A3",
+            "prap": "\u2AB7",
+            "Pr": "\u2ABB",
+            "pr": "\u227A",
+            "prcue": "\u227C",
+            "precapprox": "\u2AB7",
+            "prec": "\u227A",
+            "preccurlyeq": "\u227C",
+            "Precedes": "\u227A",
+            "PrecedesEqual": "\u2AAF",
+            "PrecedesSlantEqual": "\u227C",
+            "PrecedesTilde": "\u227E",
+            "preceq": "\u2AAF",
+            "precnapprox": "\u2AB9",
+            "precneqq": "\u2AB5",
+            "precnsim": "\u22E8",
+            "pre": "\u2AAF",
+            "prE": "\u2AB3",
+            "precsim": "\u227E",
+            "prime": "\u2032",
+            "Prime": "\u2033",
+            "primes": "\u2119",
+            "prnap": "\u2AB9",
+            "prnE": "\u2AB5",
+            "prnsim": "\u22E8",
+            "prod": "\u220F",
+            "Product": "\u220F",
+            "profalar": "\u232E",
+            "profline": "\u2312",
+            "profsurf": "\u2313",
+            "prop": "\u221D",
+            "Proportional": "\u221D",
+            "Proportion": "\u2237",
+            "propto": "\u221D",
+            "prsim": "\u227E",
+            "prurel": "\u22B0",
+            "Pscr": "\uD835\uDCAB",
+            "pscr": "\uD835\uDCC5",
+            "Psi": "\u03A8",
+            "psi": "\u03C8",
+            "puncsp": "\u2008",
+            "Qfr": "\uD835\uDD14",
+            "qfr": "\uD835\uDD2E",
+            "qint": "\u2A0C",
+            "qopf": "\uD835\uDD62",
+            "Qopf": "\u211A",
+            "qprime": "\u2057",
+            "Qscr": "\uD835\uDCAC",
+            "qscr": "\uD835\uDCC6",
+            "quaternions": "\u210D",
+            "quatint": "\u2A16",
+            "quest": "?",
+            "questeq": "\u225F",
+            "quot": "\"",
+            "QUOT": "\"",
+            "rAarr": "\u21DB",
+            "race": "\u223D\u0331",
+            "Racute": "\u0154",
+            "racute": "\u0155",
+            "radic": "\u221A",
+            "raemptyv": "\u29B3",
+            "rang": "\u27E9",
+            "Rang": "\u27EB",
+            "rangd": "\u2992",
+            "range": "\u29A5",
+            "rangle": "\u27E9",
+            "raquo": "\u00BB",
+            "rarrap": "\u2975",
+            "rarrb": "\u21E5",
+            "rarrbfs": "\u2920",
+            "rarrc": "\u2933",
+            "rarr": "\u2192",
+            "Rarr": "\u21A0",
+            "rArr": "\u21D2",
+            "rarrfs": "\u291E",
+            "rarrhk": "\u21AA",
+            "rarrlp": "\u21AC",
+            "rarrpl": "\u2945",
+            "rarrsim": "\u2974",
+            "Rarrtl": "\u2916",
+            "rarrtl": "\u21A3",
+            "rarrw": "\u219D",
+            "ratail": "\u291A",
+            "rAtail": "\u291C",
+            "ratio": "\u2236",
+            "rationals": "\u211A",
+            "rbarr": "\u290D",
+            "rBarr": "\u290F",
+            "RBarr": "\u2910",
+            "rbbrk": "\u2773",
+            "rbrace": "}",
+            "rbrack": "]",
+            "rbrke": "\u298C",
+            "rbrksld": "\u298E",
+            "rbrkslu": "\u2990",
+            "Rcaron": "\u0158",
+            "rcaron": "\u0159",
+            "Rcedil": "\u0156",
+            "rcedil": "\u0157",
+            "rceil": "\u2309",
+            "rcub": "}",
+            "Rcy": "\u0420",
+            "rcy": "\u0440",
+            "rdca": "\u2937",
+            "rdldhar": "\u2969",
+            "rdquo": "\u201D",
+            "rdquor": "\u201D",
+            "rdsh": "\u21B3",
+            "real": "\u211C",
+            "realine": "\u211B",
+            "realpart": "\u211C",
+            "reals": "\u211D",
+            "Re": "\u211C",
+            "rect": "\u25AD",
+            "reg": "\u00AE",
+            "REG": "\u00AE",
+            "ReverseElement": "\u220B",
+            "ReverseEquilibrium": "\u21CB",
+            "ReverseUpEquilibrium": "\u296F",
+            "rfisht": "\u297D",
+            "rfloor": "\u230B",
+            "rfr": "\uD835\uDD2F",
+            "Rfr": "\u211C",
+            "rHar": "\u2964",
+            "rhard": "\u21C1",
+            "rharu": "\u21C0",
+            "rharul": "\u296C",
+            "Rho": "\u03A1",
+            "rho": "\u03C1",
+            "rhov": "\u03F1",
+            "RightAngleBracket": "\u27E9",
+            "RightArrowBar": "\u21E5",
+            "rightarrow": "\u2192",
+            "RightArrow": "\u2192",
+            "Rightarrow": "\u21D2",
+            "RightArrowLeftArrow": "\u21C4",
+            "rightarrowtail": "\u21A3",
+            "RightCeiling": "\u2309",
+            "RightDoubleBracket": "\u27E7",
+            "RightDownTeeVector": "\u295D",
+            "RightDownVectorBar": "\u2955",
+            "RightDownVector": "\u21C2",
+            "RightFloor": "\u230B",
+            "rightharpoondown": "\u21C1",
+            "rightharpoonup": "\u21C0",
+            "rightleftarrows": "\u21C4",
+            "rightleftharpoons": "\u21CC",
+            "rightrightarrows": "\u21C9",
+            "rightsquigarrow": "\u219D",
+            "RightTeeArrow": "\u21A6",
+            "RightTee": "\u22A2",
+            "RightTeeVector": "\u295B",
+            "rightthreetimes": "\u22CC",
+            "RightTriangleBar": "\u29D0",
+            "RightTriangle": "\u22B3",
+            "RightTriangleEqual": "\u22B5",
+            "RightUpDownVector": "\u294F",
+            "RightUpTeeVector": "\u295C",
+            "RightUpVectorBar": "\u2954",
+            "RightUpVector": "\u21BE",
+            "RightVectorBar": "\u2953",
+            "RightVector": "\u21C0",
+            "ring": "\u02DA",
+            "risingdotseq": "\u2253",
+            "rlarr": "\u21C4",
+            "rlhar": "\u21CC",
+            "rlm": "\u200F",
+            "rmoustache": "\u23B1",
+            "rmoust": "\u23B1",
+            "rnmid": "\u2AEE",
+            "roang": "\u27ED",
+            "roarr": "\u21FE",
+            "robrk": "\u27E7",
+            "ropar": "\u2986",
+            "ropf": "\uD835\uDD63",
+            "Ropf": "\u211D",
+            "roplus": "\u2A2E",
+            "rotimes": "\u2A35",
+            "RoundImplies": "\u2970",
+            "rpar": ")",
+            "rpargt": "\u2994",
+            "rppolint": "\u2A12",
+            "rrarr": "\u21C9",
+            "Rrightarrow": "\u21DB",
+            "rsaquo": "\u203A",
+            "rscr": "\uD835\uDCC7",
+            "Rscr": "\u211B",
+            "rsh": "\u21B1",
+            "Rsh": "\u21B1",
+            "rsqb": "]",
+            "rsquo": "\u2019",
+            "rsquor": "\u2019",
+            "rthree": "\u22CC",
+            "rtimes": "\u22CA",
+            "rtri": "\u25B9",
+            "rtrie": "\u22B5",
+            "rtrif": "\u25B8",
+            "rtriltri": "\u29CE",
+            "RuleDelayed": "\u29F4",
+            "ruluhar": "\u2968",
+            "rx": "\u211E",
+            "Sacute": "\u015A",
+            "sacute": "\u015B",
+            "sbquo": "\u201A",
+            "scap": "\u2AB8",
+            "Scaron": "\u0160",
+            "scaron": "\u0161",
+            "Sc": "\u2ABC",
+            "sc": "\u227B",
+            "sccue": "\u227D",
+            "sce": "\u2AB0",
+            "scE": "\u2AB4",
+            "Scedil": "\u015E",
+            "scedil": "\u015F",
+            "Scirc": "\u015C",
+            "scirc": "\u015D",
+            "scnap": "\u2ABA",
+            "scnE": "\u2AB6",
+            "scnsim": "\u22E9",
+            "scpolint": "\u2A13",
+            "scsim": "\u227F",
+            "Scy": "\u0421",
+            "scy": "\u0441",
+            "sdotb": "\u22A1",
+            "sdot": "\u22C5",
+            "sdote": "\u2A66",
+            "searhk": "\u2925",
+            "searr": "\u2198",
+            "seArr": "\u21D8",
+            "searrow": "\u2198",
+            "sect": "\u00A7",
+            "semi": ";",
+            "seswar": "\u2929",
+            "setminus": "\u2216",
+            "setmn": "\u2216",
+            "sext": "\u2736",
+            "Sfr": "\uD835\uDD16",
+            "sfr": "\uD835\uDD30",
+            "sfrown": "\u2322",
+            "sharp": "\u266F",
+            "SHCHcy": "\u0429",
+            "shchcy": "\u0449",
+            "SHcy": "\u0428",
+            "shcy": "\u0448",
+            "ShortDownArrow": "\u2193",
+            "ShortLeftArrow": "\u2190",
+            "shortmid": "\u2223",
+            "shortparallel": "\u2225",
+            "ShortRightArrow": "\u2192",
+            "ShortUpArrow": "\u2191",
+            "shy": "\u00AD",
+            "Sigma": "\u03A3",
+            "sigma": "\u03C3",
+            "sigmaf": "\u03C2",
+            "sigmav": "\u03C2",
+            "sim": "\u223C",
+            "simdot": "\u2A6A",
+            "sime": "\u2243",
+            "simeq": "\u2243",
+            "simg": "\u2A9E",
+            "simgE": "\u2AA0",
+            "siml": "\u2A9D",
+            "simlE": "\u2A9F",
+            "simne": "\u2246",
+            "simplus": "\u2A24",
+            "simrarr": "\u2972",
+            "slarr": "\u2190",
+            "SmallCircle": "\u2218",
+            "smallsetminus": "\u2216",
+            "smashp": "\u2A33",
+            "smeparsl": "\u29E4",
+            "smid": "\u2223",
+            "smile": "\u2323",
+            "smt": "\u2AAA",
+            "smte": "\u2AAC",
+            "smtes": "\u2AAC\uFE00",
+            "SOFTcy": "\u042C",
+            "softcy": "\u044C",
+            "solbar": "\u233F",
+            "solb": "\u29C4",
+            "sol": "/",
+            "Sopf": "\uD835\uDD4A",
+            "sopf": "\uD835\uDD64",
+            "spades": "\u2660",
+            "spadesuit": "\u2660",
+            "spar": "\u2225",
+            "sqcap": "\u2293",
+            "sqcaps": "\u2293\uFE00",
+            "sqcup": "\u2294",
+            "sqcups": "\u2294\uFE00",
+            "Sqrt": "\u221A",
+            "sqsub": "\u228F",
+            "sqsube": "\u2291",
+            "sqsubset": "\u228F",
+            "sqsubseteq": "\u2291",
+            "sqsup": "\u2290",
+            "sqsupe": "\u2292",
+            "sqsupset": "\u2290",
+            "sqsupseteq": "\u2292",
+            "square": "\u25A1",
+            "Square": "\u25A1",
+            "SquareIntersection": "\u2293",
+            "SquareSubset": "\u228F",
+            "SquareSubsetEqual": "\u2291",
+            "SquareSuperset": "\u2290",
+            "SquareSupersetEqual": "\u2292",
+            "SquareUnion": "\u2294",
+            "squarf": "\u25AA",
+            "squ": "\u25A1",
+            "squf": "\u25AA",
+            "srarr": "\u2192",
+            "Sscr": "\uD835\uDCAE",
+            "sscr": "\uD835\uDCC8",
+            "ssetmn": "\u2216",
+            "ssmile": "\u2323",
+            "sstarf": "\u22C6",
+            "Star": "\u22C6",
+            "star": "\u2606",
+            "starf": "\u2605",
+            "straightepsilon": "\u03F5",
+            "straightphi": "\u03D5",
+            "strns": "\u00AF",
+            "sub": "\u2282",
+            "Sub": "\u22D0",
+            "subdot": "\u2ABD",
+            "subE": "\u2AC5",
+            "sube": "\u2286",
+            "subedot": "\u2AC3",
+            "submult": "\u2AC1",
+            "subnE": "\u2ACB",
+            "subne": "\u228A",
+            "subplus": "\u2ABF",
+            "subrarr": "\u2979",
+            "subset": "\u2282",
+            "Subset": "\u22D0",
+            "subseteq": "\u2286",
+            "subseteqq": "\u2AC5",
+            "SubsetEqual": "\u2286",
+            "subsetneq": "\u228A",
+            "subsetneqq": "\u2ACB",
+            "subsim": "\u2AC7",
+            "subsub": "\u2AD5",
+            "subsup": "\u2AD3",
+            "succapprox": "\u2AB8",
+            "succ": "\u227B",
+            "succcurlyeq": "\u227D",
+            "Succeeds": "\u227B",
+            "SucceedsEqual": "\u2AB0",
+            "SucceedsSlantEqual": "\u227D",
+            "SucceedsTilde": "\u227F",
+            "succeq": "\u2AB0",
+            "succnapprox": "\u2ABA",
+            "succneqq": "\u2AB6",
+            "succnsim": "\u22E9",
+            "succsim": "\u227F",
+            "SuchThat": "\u220B",
+            "sum": "\u2211",
+            "Sum": "\u2211",
+            "sung": "\u266A",
+            "sup1": "\u00B9",
+            "sup2": "\u00B2",
+            "sup3": "\u00B3",
+            "sup": "\u2283",
+            "Sup": "\u22D1",
+            "supdot": "\u2ABE",
+            "supdsub": "\u2AD8",
+            "supE": "\u2AC6",
+            "supe": "\u2287",
+            "supedot": "\u2AC4",
+            "Superset": "\u2283",
+            "SupersetEqual": "\u2287",
+            "suphsol": "\u27C9",
+            "suphsub": "\u2AD7",
+            "suplarr": "\u297B",
+            "supmult": "\u2AC2",
+            "supnE": "\u2ACC",
+            "supne": "\u228B",
+            "supplus": "\u2AC0",
+            "supset": "\u2283",
+            "Supset": "\u22D1",
+            "supseteq": "\u2287",
+            "supseteqq": "\u2AC6",
+            "supsetneq": "\u228B",
+            "supsetneqq": "\u2ACC",
+            "supsim": "\u2AC8",
+            "supsub": "\u2AD4",
+            "supsup": "\u2AD6",
+            "swarhk": "\u2926",
+            "swarr": "\u2199",
+            "swArr": "\u21D9",
+            "swarrow": "\u2199",
+            "swnwar": "\u292A",
+            "szlig": "\u00DF",
+            "Tab": "\t",
+            "target": "\u2316",
+            "Tau": "\u03A4",
+            "tau": "\u03C4",
+            "tbrk": "\u23B4",
+            "Tcaron": "\u0164",
+            "tcaron": "\u0165",
+            "Tcedil": "\u0162",
+            "tcedil": "\u0163",
+            "Tcy": "\u0422",
+            "tcy": "\u0442",
+            "tdot": "\u20DB",
+            "telrec": "\u2315",
+            "Tfr": "\uD835\uDD17",
+            "tfr": "\uD835\uDD31",
+            "there4": "\u2234",
+            "therefore": "\u2234",
+            "Therefore": "\u2234",
+            "Theta": "\u0398",
+            "theta": "\u03B8",
+            "thetasym": "\u03D1",
+            "thetav": "\u03D1",
+            "thickapprox": "\u2248",
+            "thicksim": "\u223C",
+            "ThickSpace": "\u205F\u200A",
+            "ThinSpace": "\u2009",
+            "thinsp": "\u2009",
+            "thkap": "\u2248",
+            "thksim": "\u223C",
+            "THORN": "\u00DE",
+            "thorn": "\u00FE",
+            "tilde": "\u02DC",
+            "Tilde": "\u223C",
+            "TildeEqual": "\u2243",
+            "TildeFullEqual": "\u2245",
+            "TildeTilde": "\u2248",
+            "timesbar": "\u2A31",
+            "timesb": "\u22A0",
+            "times": "\u00D7",
+            "timesd": "\u2A30",
+            "tint": "\u222D",
+            "toea": "\u2928",
+            "topbot": "\u2336",
+            "topcir": "\u2AF1",
+            "top": "\u22A4",
+            "Topf": "\uD835\uDD4B",
+            "topf": "\uD835\uDD65",
+            "topfork": "\u2ADA",
+            "tosa": "\u2929",
+            "tprime": "\u2034",
+            "trade": "\u2122",
+            "TRADE": "\u2122",
+            "triangle": "\u25B5",
+            "triangledown": "\u25BF",
+            "triangleleft": "\u25C3",
+            "trianglelefteq": "\u22B4",
+            "triangleq": "\u225C",
+            "triangleright": "\u25B9",
+            "trianglerighteq": "\u22B5",
+            "tridot": "\u25EC",
+            "trie": "\u225C",
+            "triminus": "\u2A3A",
+            "TripleDot": "\u20DB",
+            "triplus": "\u2A39",
+            "trisb": "\u29CD",
+            "tritime": "\u2A3B",
+            "trpezium": "\u23E2",
+            "Tscr": "\uD835\uDCAF",
+            "tscr": "\uD835\uDCC9",
+            "TScy": "\u0426",
+            "tscy": "\u0446",
+            "TSHcy": "\u040B",
+            "tshcy": "\u045B",
+            "Tstrok": "\u0166",
+            "tstrok": "\u0167",
+            "twixt": "\u226C",
+            "twoheadleftarrow": "\u219E",
+            "twoheadrightarrow": "\u21A0",
+            "Uacute": "\u00DA",
+            "uacute": "\u00FA",
+            "uarr": "\u2191",
+            "Uarr": "\u219F",
+            "uArr": "\u21D1",
+            "Uarrocir": "\u2949",
+            "Ubrcy": "\u040E",
+            "ubrcy": "\u045E",
+            "Ubreve": "\u016C",
+            "ubreve": "\u016D",
+            "Ucirc": "\u00DB",
+            "ucirc": "\u00FB",
+            "Ucy": "\u0423",
+            "ucy": "\u0443",
+            "udarr": "\u21C5",
+            "Udblac": "\u0170",
+            "udblac": "\u0171",
+            "udhar": "\u296E",
+            "ufisht": "\u297E",
+            "Ufr": "\uD835\uDD18",
+            "ufr": "\uD835\uDD32",
+            "Ugrave": "\u00D9",
+            "ugrave": "\u00F9",
+            "uHar": "\u2963",
+            "uharl": "\u21BF",
+            "uharr": "\u21BE",
+            "uhblk": "\u2580",
+            "ulcorn": "\u231C",
+            "ulcorner": "\u231C",
+            "ulcrop": "\u230F",
+            "ultri": "\u25F8",
+            "Umacr": "\u016A",
+            "umacr": "\u016B",
+            "uml": "\u00A8",
+            "UnderBar": "_",
+            "UnderBrace": "\u23DF",
+            "UnderBracket": "\u23B5",
+            "UnderParenthesis": "\u23DD",
+            "Union": "\u22C3",
+            "UnionPlus": "\u228E",
+            "Uogon": "\u0172",
+            "uogon": "\u0173",
+            "Uopf": "\uD835\uDD4C",
+            "uopf": "\uD835\uDD66",
+            "UpArrowBar": "\u2912",
+            "uparrow": "\u2191",
+            "UpArrow": "\u2191",
+            "Uparrow": "\u21D1",
+            "UpArrowDownArrow": "\u21C5",
+            "updownarrow": "\u2195",
+            "UpDownArrow": "\u2195",
+            "Updownarrow": "\u21D5",
+            "UpEquilibrium": "\u296E",
+            "upharpoonleft": "\u21BF",
+            "upharpoonright": "\u21BE",
+            "uplus": "\u228E",
+            "UpperLeftArrow": "\u2196",
+            "UpperRightArrow": "\u2197",
+            "upsi": "\u03C5",
+            "Upsi": "\u03D2",
+            "upsih": "\u03D2",
+            "Upsilon": "\u03A5",
+            "upsilon": "\u03C5",
+            "UpTeeArrow": "\u21A5",
+            "UpTee": "\u22A5",
+            "upuparrows": "\u21C8",
+            "urcorn": "\u231D",
+            "urcorner": "\u231D",
+            "urcrop": "\u230E",
+            "Uring": "\u016E",
+            "uring": "\u016F",
+            "urtri": "\u25F9",
+            "Uscr": "\uD835\uDCB0",
+            "uscr": "\uD835\uDCCA",
+            "utdot": "\u22F0",
+            "Utilde": "\u0168",
+            "utilde": "\u0169",
+            "utri": "\u25B5",
+            "utrif": "\u25B4",
+            "uuarr": "\u21C8",
+            "Uuml": "\u00DC",
+            "uuml": "\u00FC",
+            "uwangle": "\u29A7",
+            "vangrt": "\u299C",
+            "varepsilon": "\u03F5",
+            "varkappa": "\u03F0",
+            "varnothing": "\u2205",
+            "varphi": "\u03D5",
+            "varpi": "\u03D6",
+            "varpropto": "\u221D",
+            "varr": "\u2195",
+            "vArr": "\u21D5",
+            "varrho": "\u03F1",
+            "varsigma": "\u03C2",
+            "varsubsetneq": "\u228A\uFE00",
+            "varsubsetneqq": "\u2ACB\uFE00",
+            "varsupsetneq": "\u228B\uFE00",
+            "varsupsetneqq": "\u2ACC\uFE00",
+            "vartheta": "\u03D1",
+            "vartriangleleft": "\u22B2",
+            "vartriangleright": "\u22B3",
+            "vBar": "\u2AE8",
+            "Vbar": "\u2AEB",
+            "vBarv": "\u2AE9",
+            "Vcy": "\u0412",
+            "vcy": "\u0432",
+            "vdash": "\u22A2",
+            "vDash": "\u22A8",
+            "Vdash": "\u22A9",
+            "VDash": "\u22AB",
+            "Vdashl": "\u2AE6",
+            "veebar": "\u22BB",
+            "vee": "\u2228",
+            "Vee": "\u22C1",
+            "veeeq": "\u225A",
+            "vellip": "\u22EE",
+            "verbar": "|",
+            "Verbar": "\u2016",
+            "vert": "|",
+            "Vert": "\u2016",
+            "VerticalBar": "\u2223",
+            "VerticalLine": "|",
+            "VerticalSeparator": "\u2758",
+            "VerticalTilde": "\u2240",
+            "VeryThinSpace": "\u200A",
+            "Vfr": "\uD835\uDD19",
+            "vfr": "\uD835\uDD33",
+            "vltri": "\u22B2",
+            "vnsub": "\u2282\u20D2",
+            "vnsup": "\u2283\u20D2",
+            "Vopf": "\uD835\uDD4D",
+            "vopf": "\uD835\uDD67",
+            "vprop": "\u221D",
+            "vrtri": "\u22B3",
+            "Vscr": "\uD835\uDCB1",
+            "vscr": "\uD835\uDCCB",
+            "vsubnE": "\u2ACB\uFE00",
+            "vsubne": "\u228A\uFE00",
+            "vsupnE": "\u2ACC\uFE00",
+            "vsupne": "\u228B\uFE00",
+            "Vvdash": "\u22AA",
+            "vzigzag": "\u299A",
+            "Wcirc": "\u0174",
+            "wcirc": "\u0175",
+            "wedbar": "\u2A5F",
+            "wedge": "\u2227",
+            "Wedge": "\u22C0",
+            "wedgeq": "\u2259",
+            "weierp": "\u2118",
+            "Wfr": "\uD835\uDD1A",
+            "wfr": "\uD835\uDD34",
+            "Wopf": "\uD835\uDD4E",
+            "wopf": "\uD835\uDD68",
+            "wp": "\u2118",
+            "wr": "\u2240",
+            "wreath": "\u2240",
+            "Wscr": "\uD835\uDCB2",
+            "wscr": "\uD835\uDCCC",
+            "xcap": "\u22C2",
+            "xcirc": "\u25EF",
+            "xcup": "\u22C3",
+            "xdtri": "\u25BD",
+            "Xfr": "\uD835\uDD1B",
+            "xfr": "\uD835\uDD35",
+            "xharr": "\u27F7",
+            "xhArr": "\u27FA",
+            "Xi": "\u039E",
+            "xi": "\u03BE",
+            "xlarr": "\u27F5",
+            "xlArr": "\u27F8",
+            "xmap": "\u27FC",
+            "xnis": "\u22FB",
+            "xodot": "\u2A00",
+            "Xopf": "\uD835\uDD4F",
+            "xopf": "\uD835\uDD69",
+            "xoplus": "\u2A01",
+            "xotime": "\u2A02",
+            "xrarr": "\u27F6",
+            "xrArr": "\u27F9",
+            "Xscr": "\uD835\uDCB3",
+            "xscr": "\uD835\uDCCD",
+            "xsqcup": "\u2A06",
+            "xuplus": "\u2A04",
+            "xutri": "\u25B3",
+            "xvee": "\u22C1",
+            "xwedge": "\u22C0",
+            "Yacute": "\u00DD",
+            "yacute": "\u00FD",
+            "YAcy": "\u042F",
+            "yacy": "\u044F",
+            "Ycirc": "\u0176",
+            "ycirc": "\u0177",
+            "Ycy": "\u042B",
+            "ycy": "\u044B",
+            "yen": "\u00A5",
+            "Yfr": "\uD835\uDD1C",
+            "yfr": "\uD835\uDD36",
+            "YIcy": "\u0407",
+            "yicy": "\u0457",
+            "Yopf": "\uD835\uDD50",
+            "yopf": "\uD835\uDD6A",
+            "Yscr": "\uD835\uDCB4",
+            "yscr": "\uD835\uDCCE",
+            "YUcy": "\u042E",
+            "yucy": "\u044E",
+            "yuml": "\u00FF",
+            "Yuml": "\u0178",
+            "Zacute": "\u0179",
+            "zacute": "\u017A",
+            "Zcaron": "\u017D",
+            "zcaron": "\u017E",
+            "Zcy": "\u0417",
+            "zcy": "\u0437",
+            "Zdot": "\u017B",
+            "zdot": "\u017C",
+            "zeetrf": "\u2128",
+            "ZeroWidthSpace": "\u200B",
+            "Zeta": "\u0396",
+            "zeta": "\u03B6",
+            "zfr": "\uD835\uDD37",
+            "Zfr": "\u2128",
+            "ZHcy": "\u0416",
+            "zhcy": "\u0436",
+            "zigrarr": "\u21DD",
+            "zopf": "\uD835\uDD6B",
+            "Zopf": "\u2124",
+            "Zscr": "\uD835\uDCB5",
+            "zscr": "\uD835\uDCCF",
+            "zwj": "\u200D",
+            "zwnj": "\u200C"
+        }
+    }, {}],
+    33: [function (require, module, exports) {
+        module.exports = {
+            "Aacute": "\u00C1",
+            "aacute": "\u00E1",
+            "Acirc": "\u00C2",
+            "acirc": "\u00E2",
+            "acute": "\u00B4",
+            "AElig": "\u00C6",
+            "aelig": "\u00E6",
+            "Agrave": "\u00C0",
+            "agrave": "\u00E0",
+            "amp": "&",
+            "AMP": "&",
+            "Aring": "\u00C5",
+            "aring": "\u00E5",
+            "Atilde": "\u00C3",
+            "atilde": "\u00E3",
+            "Auml": "\u00C4",
+            "auml": "\u00E4",
+            "brvbar": "\u00A6",
+            "Ccedil": "\u00C7",
+            "ccedil": "\u00E7",
+            "cedil": "\u00B8",
+            "cent": "\u00A2",
+            "copy": "\u00A9",
+            "COPY": "\u00A9",
+            "curren": "\u00A4",
+            "deg": "\u00B0",
+            "divide": "\u00F7",
+            "Eacute": "\u00C9",
+            "eacute": "\u00E9",
+            "Ecirc": "\u00CA",
+            "ecirc": "\u00EA",
+            "Egrave": "\u00C8",
+            "egrave": "\u00E8",
+            "ETH": "\u00D0",
+            "eth": "\u00F0",
+            "Euml": "\u00CB",
+            "euml": "\u00EB",
+            "frac12": "\u00BD",
+            "frac14": "\u00BC",
+            "frac34": "\u00BE",
+            "gt": ">",
+            "GT": ">",
+            "Iacute": "\u00CD",
+            "iacute": "\u00ED",
+            "Icirc": "\u00CE",
+            "icirc": "\u00EE",
+            "iexcl": "\u00A1",
+            "Igrave": "\u00CC",
+            "igrave": "\u00EC",
+            "iquest": "\u00BF",
+            "Iuml": "\u00CF",
+            "iuml": "\u00EF",
+            "laquo": "\u00AB",
+            "lt": "<",
+            "LT": "<",
+            "macr": "\u00AF",
+            "micro": "\u00B5",
+            "middot": "\u00B7",
+            "nbsp": "\u00A0",
+            "not": "\u00AC",
+            "Ntilde": "\u00D1",
+            "ntilde": "\u00F1",
+            "Oacute": "\u00D3",
+            "oacute": "\u00F3",
+            "Ocirc": "\u00D4",
+            "ocirc": "\u00F4",
+            "Ograve": "\u00D2",
+            "ograve": "\u00F2",
+            "ordf": "\u00AA",
+            "ordm": "\u00BA",
+            "Oslash": "\u00D8",
+            "oslash": "\u00F8",
+            "Otilde": "\u00D5",
+            "otilde": "\u00F5",
+            "Ouml": "\u00D6",
+            "ouml": "\u00F6",
+            "para": "\u00B6",
+            "plusmn": "\u00B1",
+            "pound": "\u00A3",
+            "quot": "\"",
+            "QUOT": "\"",
+            "raquo": "\u00BB",
+            "reg": "\u00AE",
+            "REG": "\u00AE",
+            "sect": "\u00A7",
+            "shy": "\u00AD",
+            "sup1": "\u00B9",
+            "sup2": "\u00B2",
+            "sup3": "\u00B3",
+            "szlig": "\u00DF",
+            "THORN": "\u00DE",
+            "thorn": "\u00FE",
+            "times": "\u00D7",
+            "Uacute": "\u00DA",
+            "uacute": "\u00FA",
+            "Ucirc": "\u00DB",
+            "ucirc": "\u00FB",
+            "Ugrave": "\u00D9",
+            "ugrave": "\u00F9",
+            "uml": "\u00A8",
+            "Uuml": "\u00DC",
+            "uuml": "\u00FC",
+            "Yacute": "\u00DD",
+            "yacute": "\u00FD",
+            "yen": "\u00A5",
+            "yuml": "\u00FF"
+        }
+    }, {}],
+    34: [function (require, module, exports) {
+        module.exports = {"amp": "&", "apos": "'", "gt": ">", "lt": "<", "quot": "\""}
+
+    }, {}],
+    35: [function (require, module, exports) {
+
+    }, {}],
+    36: [function (require, module, exports) {
+        (function (global) {
+            /*!
+ * The buffer module from node.js, for the browser.
+ *
+ * @author   Feross Aboukhadijeh <[email protected]> <http://feross.org>
+ * @license  MIT
+ */
+            /* eslint-disable no-proto */
+
+            'use strict'
+
+            var base64 = require('base64-js')
+            var ieee754 = require('ieee754')
+            var isArray = require('isarray')
+
+            exports.Buffer = Buffer
+            exports.SlowBuffer = SlowBuffer
+            exports.INSPECT_MAX_BYTES = 50
+            Buffer.poolSize = 8192 // not used by this implementation
+
+            var rootParent = {}
+
+            /**
+             * If `Buffer.TYPED_ARRAY_SUPPORT`:
+             *   === true    Use Uint8Array implementation (fastest)
+             *   === false   Use Object implementation (most compatible, even IE6)
+             *
+             * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
+             * Opera 11.6+, iOS 4.2+.
+             *
+             * Due to various browser bugs, sometimes the Object implementation will be used even
+             * when the browser supports typed arrays.
+             *
+             * Note:
+             *
+             *   - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
+             *     See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
+             *
+             *   - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
+             *
+             *   - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
+             *     incorrect length in some situations.
+
+             * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
+             * get the Object implementation, which is slower but behaves correctly.
+             */
+            Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
+                ? global.TYPED_ARRAY_SUPPORT
+                : typedArraySupport()
+
+            function typedArraySupport() {
+                try {
+                    var arr = new Uint8Array(1)
+                    arr.foo = function () {
+                        return 42
+                    }
+                    return arr.foo() === 42 && // typed array instances can be augmented
+                        typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
+                        arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
+                } catch (e) {
+                    return false
+                }
+            }
+
+            function kMaxLength() {
+                return Buffer.TYPED_ARRAY_SUPPORT
+                    ? 0x7fffffff
+                    : 0x3fffffff
+            }
+
+            /**
+             * The Buffer constructor returns instances of `Uint8Array` that have their
+             * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
+             * `Uint8Array`, so the returned instances will have all the node `Buffer` methods
+             * and the `Uint8Array` methods. Square bracket notation works as expected -- it
+             * returns a single octet.
+             *
+             * The `Uint8Array` prototype remains unmodified.
+             */
+            function Buffer(arg) {
+                if (!(this instanceof Buffer)) {
+                    // Avoid going through an ArgumentsAdaptorTrampoline in the common case.
+                    if (arguments.length > 1) return new Buffer(arg, arguments[1])
+                    return new Buffer(arg)
+                }
+
+                if (!Buffer.TYPED_ARRAY_SUPPORT) {
+                    this.length = 0
+                    this.parent = undefined
+                }
+
+                // Common case.
+                if (typeof arg === 'number') {
+                    return fromNumber(this, arg)
+                }
+
+                // Slightly less common case.
+                if (typeof arg === 'string') {
+                    return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8')
+                }
+
+                // Unusual.
+                return fromObject(this, arg)
+            }
+
+// TODO: Legacy, not needed anymore. Remove in next major version.
+            Buffer._augment = function (arr) {
+                arr.__proto__ = Buffer.prototype
+                return arr
+            }
+
+            function fromNumber(that, length) {
+                that = allocate(that, length < 0 ? 0 : checked(length) | 0)
+                if (!Buffer.TYPED_ARRAY_SUPPORT) {
+                    for (var i = 0; i < length; i++) {
+                        that[i] = 0
+                    }
+                }
+                return that
+            }
+
+            function fromString(that, string, encoding) {
+                if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8'
+
+                // Assumption: byteLength() return value is always < kMaxLength.
+                var length = byteLength(string, encoding) | 0
+                that = allocate(that, length)
+
+                that.write(string, encoding)
+                return that
+            }
+
+            function fromObject(that, object) {
+                if (Buffer.isBuffer(object)) return fromBuffer(that, object)
+
+                if (isArray(object)) return fromArray(that, object)
+
+                if (object == null) {
+                    throw new TypeError('must start with number, buffer, array or string')
+                }
+
+                if (typeof ArrayBuffer !== 'undefined') {
+                    if (object.buffer instanceof ArrayBuffer) {
+                        return fromTypedArray(that, object)
+                    }
+                    if (object instanceof ArrayBuffer) {
+                        return fromArrayBuffer(that, object)
+                    }
+                }
+
+                if (object.length) return fromArrayLike(that, object)
+
+                return fromJsonObject(that, object)
+            }
+
+            function fromBuffer(that, buffer) {
+                var length = checked(buffer.length) | 0
+                that = allocate(that, length)
+                buffer.copy(that, 0, 0, length)
+                return that
+            }
+
+            function fromArray(that, array) {
+                var length = checked(array.length) | 0
+                that = allocate(that, length)
+                for (var i = 0; i < length; i += 1) {
+                    that[i] = array[i] & 255
+                }
+                return that
+            }
+
+// Duplicate of fromArray() to keep fromArray() monomorphic.
+            function fromTypedArray(that, array) {
+                var length = checked(array.length) | 0
+                that = allocate(that, length)
+                // Truncating the elements is probably not what people expect from typed
+                // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior
+                // of the old Buffer constructor.
+                for (var i = 0; i < length; i += 1) {
+                    that[i] = array[i] & 255
+                }
+                return that
+            }
+
+            function fromArrayBuffer(that, array) {
+                array.byteLength // this throws if `array` is not a valid ArrayBuffer
+
+                if (Buffer.TYPED_ARRAY_SUPPORT) {
+                    // Return an augmented `Uint8Array` instance, for best performance
+                    that = new Uint8Array(array)
+                    that.__proto__ = Buffer.prototype
+                } else {
+                    // Fallback: Return an object instance of the Buffer class
+                    that = fromTypedArray(that, new Uint8Array(array))
+                }
+                return that
+            }
+
+            function fromArrayLike(that, array) {
+                var length = checked(array.length) | 0
+                that = allocate(that, length)
+                for (var i = 0; i < length; i += 1) {
+                    that[i] = array[i] & 255
+                }
+                return that
+            }
+
+// Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object.
+// Returns a zero-length buffer for inputs that don't conform to the spec.
+            function fromJsonObject(that, object) {
+                var array
+                var length = 0
+
+                if (object.type === 'Buffer' && isArray(object.data)) {
+                    array = object.data
+                    length = checked(array.length) | 0
+                }
+                that = allocate(that, length)
+
+                for (var i = 0; i < length; i += 1) {
+                    that[i] = array[i] & 255
+                }
+                return that
+            }
+
+            if (Buffer.TYPED_ARRAY_SUPPORT) {
+                Buffer.prototype.__proto__ = Uint8Array.prototype
+                Buffer.__proto__ = Uint8Array
+                if (typeof Symbol !== 'undefined' && Symbol.species &&
+                    Buffer[Symbol.species] === Buffer) {
+                    // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
+                    Object.defineProperty(Buffer, Symbol.species, {
+                        value: null,
+                        configurable: true
+                    })
+                }
+            } else {
+                // pre-set for values that may exist in the future
+                Buffer.prototype.length = undefined
+                Buffer.prototype.parent = undefined
+            }
+
+            function allocate(that, length) {
+                if (Buffer.TYPED_ARRAY_SUPPORT) {
+                    // Return an augmented `Uint8Array` instance, for best performance
+                    that = new Uint8Array(length)
+                    that.__proto__ = Buffer.prototype
+                } else {
+                    // Fallback: Return an object instance of the Buffer class
+                    that.length = length
+                }
+
+                var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1
+                if (fromPool) that.parent = rootParent
+
+                return that
+            }
+
+            function checked(length) {
+                // Note: cannot use `length < kMaxLength` here because that fails when
+                // length is NaN (which is otherwise coerced to zero.)
+                if (length >= kMaxLength()) {
+                    throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
+                        'size: 0x' + kMaxLength().toString(16) + ' bytes')
+                }
+                return length | 0
+            }
+
+            function SlowBuffer(subject, encoding) {
+                if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding)
+
+                var buf = new Buffer(subject, encoding)
+                delete buf.parent
+                return buf
+            }
+
+            Buffer.isBuffer = function isBuffer(b) {
+                return !!(b != null && b._isBuffer)
+            }
+
+            Buffer.compare = function compare(a, b) {
+                if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
+                    throw new TypeError('Arguments must be Buffers')
+                }
+
+                if (a === b) return 0
+
+                var x = a.length
+                var y = b.length
+
+                for (var i = 0, len = Math.min(x, y); i < len; ++i) {
+                    if (a[i] !== b[i]) {
+                        x = a[i]
+                        y = b[i]
+                        break
+                    }
+                }
+
+                if (x < y) return -1
+                if (y < x) return 1
+                return 0
+            }
+
+            Buffer.isEncoding = function isEncoding(encoding) {
+                switch (String(encoding).toLowerCase()) {
+                    case 'hex':
+                    case 'utf8':
+                    case 'utf-8':
+                    case 'ascii':
+                    case 'binary':
+                    case 'base64':
+                    case 'raw':
+                    case 'ucs2':
+                    case 'ucs-2':
+                    case 'utf16le':
+                    case 'utf-16le':
+                        return true
+                    default:
+                        return false
+                }
+            }
+
+            Buffer.concat = function concat(list, length) {
+                if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.')
+
+                if (list.length === 0) {
+                    return new Buffer(0)
+                }
+
+                var i
+                if (length === undefined) {
+                    length = 0
+                    for (i = 0; i < list.length; i++) {
+                        length += list[i].length
+                    }
+                }
+
+                var buf = new Buffer(length)
+                var pos = 0
+                for (i = 0; i < list.length; i++) {
+                    var item = list[i]
+                    item.copy(buf, pos)
+                    pos += item.length
+                }
+                return buf
+            }
+
+            function byteLength(string, encoding) {
+                if (typeof string !== 'string') string = '' + string
+
+                var len = string.length
+                if (len === 0) return 0
+
+                // Use a for loop to avoid recursion
+                var loweredCase = false
+                for (; ;) {
+                    switch (encoding) {
+                        case 'ascii':
+                        case 'binary':
+                        // Deprecated
+                        case 'raw':
+                        case 'raws':
+                            return len
+                        case 'utf8':
+                        case 'utf-8':
+                            return utf8ToBytes(string).length
+                        case 'ucs2':
+                        case 'ucs-2':
+                        case 'utf16le':
+                        case 'utf-16le':
+                            return len * 2
+                        case 'hex':
+                            return len >>> 1
+                        case 'base64':
+                            return base64ToBytes(string).length
+                        default:
+                            if (loweredCase) return utf8ToBytes(string).length // assume utf8
+                            encoding = ('' + encoding).toLowerCase()
+                            loweredCase = true
+                    }
+                }
+            }
+
+            Buffer.byteLength = byteLength
+
+            function slowToString(encoding, start, end) {
+                var loweredCase = false
+
+                start = start | 0
+                end = end === undefined || end === Infinity ? this.length : end | 0
+
+                if (!encoding) encoding = 'utf8'
+                if (start < 0) start = 0
+                if (end > this.length) end = this.length
+                if (end <= start) return ''
+
+                while (true) {
+                    switch (encoding) {
+                        case 'hex':
+                            return hexSlice(this, start, end)
+
+                        case 'utf8':
+                        case 'utf-8':
+                            return utf8Slice(this, start, end)
+
+                        case 'ascii':
+                            return asciiSlice(this, start, end)
+
+                        case 'binary':
+                            return binarySlice(this, start, end)
+
+                        case 'base64':
+                            return base64Slice(this, start, end)
+
+                        case 'ucs2':
+                        case 'ucs-2':
+                        case 'utf16le':
+                        case 'utf-16le':
+                            return utf16leSlice(this, start, end)
+
+                        default:
+                            if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
+                            encoding = (encoding + '').toLowerCase()
+                            loweredCase = true
+                    }
+                }
+            }
+
+// The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect
+// Buffer instances.
+            Buffer.prototype._isBuffer = true
+
+            Buffer.prototype.toString = function toString() {
+                var length = this.length | 0
+                if (length === 0) return ''
+                if (arguments.length === 0) return utf8Slice(this, 0, length)
+                return slowToString.apply(this, arguments)
+            }
+
+            Buffer.prototype.equals = function equals(b) {
+                if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
+                if (this === b) return true
+                return Buffer.compare(this, b) === 0
+            }
+
+            Buffer.prototype.inspect = function inspect() {
+                var str = ''
+                var max = exports.INSPECT_MAX_BYTES
+                if (this.length > 0) {
+                    str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
+                    if (this.length > max) str += ' ... '
+                }
+                return '<Buffer ' + str + '>'
+            }
+
+            Buffer.prototype.compare = function compare(b) {
+                if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
+                return Buffer.compare(this, b)
+            }
+
+            Buffer.prototype.indexOf = function indexOf(val, byteOffset) {
+                if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff
+                else if (byteOffset < -0x80000000) byteOffset = -0x80000000
+                byteOffset >>= 0
+
+                if (this.length === 0) return -1
+                if (byteOffset >= this.length) return -1
+
+                // Negative offsets start from the end of the buffer
+                if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0)
+
+                if (typeof val === 'string') {
+                    if (val.length === 0) return -1 // special case: looking for empty string always fails
+                    return String.prototype.indexOf.call(this, val, byteOffset)
+                }
+                if (Buffer.isBuffer(val)) {
+                    return arrayIndexOf(this, val, byteOffset)
+                }
+                if (typeof val === 'number') {
+                    if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') {
+                        return Uint8Array.prototype.indexOf.call(this, val, byteOffset)
+                    }
+                    return arrayIndexOf(this, [val], byteOffset)
+                }
+
+                function arrayIndexOf(arr, val, byteOffset) {
+                    var foundIndex = -1
+                    for (var i = 0; byteOffset + i < arr.length; i++) {
+                        if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) {
+                            if (foundIndex === -1) foundIndex = i
+                            if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex
+                        } else {
+                            foundIndex = -1
+                        }
+                    }
+                    return -1
+                }
+
+                throw new TypeError('val must be string, number or Buffer')
+            }
+
+            function hexWrite(buf, string, offset, length) {
+                offset = Number(offset) || 0
+                var remaining = buf.length - offset
+                if (!length) {
+                    length = remaining
+                } else {
+                    length = Number(length)
+                    if (length > remaining) {
+                        length = remaining
+                    }
+                }
+
+                // must be an even number of digits
+                var strLen = string.length
+                if (strLen % 2 !== 0) throw new Error('Invalid hex string')
+
+                if (length > strLen / 2) {
+                    length = strLen / 2
+                }
+                for (var i = 0; i < length; i++) {
+                    var parsed = parseInt(string.substr(i * 2, 2), 16)
+                    if (isNaN(parsed)) throw new Error('Invalid hex string')
+                    buf[offset + i] = parsed
+                }
+                return i
+            }
+
+            function utf8Write(buf, string, offset, length) {
+                return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
+            }
+
+            function asciiWrite(buf, string, offset, length) {
+                return blitBuffer(asciiToBytes(string), buf, offset, length)
+            }
+
+            function binaryWrite(buf, string, offset, length) {
+                return asciiWrite(buf, string, offset, length)
+            }
+
+            function base64Write(buf, string, offset, length) {
+                return blitBuffer(base64ToBytes(string), buf, offset, length)
+            }
+
+            function ucs2Write(buf, string, offset, length) {
+                return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
+            }
+
+            Buffer.prototype.write = function write(string, offset, length, encoding) {
+                // Buffer#write(string)
+                if (offset === undefined) {
+                    encoding = 'utf8'
+                    length = this.length
+                    offset = 0
+                    // Buffer#write(string, encoding)
+                } else if (length === undefined && typeof offset === 'string') {
+                    encoding = offset
+                    length = this.length
+                    offset = 0
+                    // Buffer#write(string, offset[, length][, encoding])
+                } else if (isFinite(offset)) {
+                    offset = offset | 0
+                    if (isFinite(length)) {
+                        length = length | 0
+                        if (encoding === undefined) encoding = 'utf8'
+                    } else {
+                        encoding = length
+                        length = undefined
+                    }
+                    // legacy write(string, encoding, offset, length) - remove in v0.13
+                } else {
+                    var swap = encoding
+                    encoding = offset
+                    offset = length | 0
+                    length = swap
+                }
+
+                var remaining = this.length - offset
+                if (length === undefined || length > remaining) length = remaining
+
+                if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
+                    throw new RangeError('attempt to write outside buffer bounds')
+                }
+
+                if (!encoding) encoding = 'utf8'
+
+                var loweredCase = false
+                for (; ;) {
+                    switch (encoding) {
+                        case 'hex':
+                            return hexWrite(this, string, offset, length)
+
+                        case 'utf8':
+                        case 'utf-8':
+                            return utf8Write(this, string, offset, length)
+
+                        case 'ascii':
+                            return asciiWrite(this, string, offset, length)
+
+                        case 'binary':
+                            return binaryWrite(this, string, offset, length)
+
+                        case 'base64':
+                            // Warning: maxLength not taken into account in base64Write
+                            return base64Write(this, string, offset, length)
+
+                        case 'ucs2':
+                        case 'ucs-2':
+                        case 'utf16le':
+                        case 'utf-16le':
+                            return ucs2Write(this, string, offset, length)
+
+                        default:
+                            if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
+                            encoding = ('' + encoding).toLowerCase()
+                            loweredCase = true
+                    }
+                }
+            }
+
+            Buffer.prototype.toJSON = function toJSON() {
+                return {
+                    type: 'Buffer',
+                    data: Array.prototype.slice.call(this._arr || this, 0)
+                }
+            }
+
+            function base64Slice(buf, start, end) {
+                if (start === 0 && end === buf.length) {
+                    return base64.fromByteArray(buf)
+                } else {
+                    return base64.fromByteArray(buf.slice(start, end))
+                }
+            }
+
+            function utf8Slice(buf, start, end) {
+                end = Math.min(buf.length, end)
+                var res = []
+
+                var i = start
+                while (i < end) {
+                    var firstByte = buf[i]
+                    var codePoint = null
+                    var bytesPerSequence = (firstByte > 0xEF) ? 4
+                        : (firstByte > 0xDF) ? 3
+                            : (firstByte > 0xBF) ? 2
+                                : 1
+
+                    if (i + bytesPerSequence <= end) {
+                        var secondByte, thirdByte, fourthByte, tempCodePoint
+
+                        switch (bytesPerSequence) {
+                            case 1:
+                                if (firstByte < 0x80) {
+                                    codePoint = firstByte
+                                }
+                                break
+                            case 2:
+                                secondByte = buf[i + 1]
+                                if ((secondByte & 0xC0) === 0x80) {
+                                    tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
+                                    if (tempCodePoint > 0x7F) {
+                                        codePoint = tempCodePoint
+                                    }
+                                }
+                                break
+                            case 3:
+                                secondByte = buf[i + 1]
+                                thirdByte = buf[i + 2]
+                                if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
+                                    tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
+                                    if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
+                                        codePoint = tempCodePoint
+                                    }
+                                }
+                                break
+                            case 4:
+                                secondByte = buf[i + 1]
+                                thirdByte = buf[i + 2]
+                                fourthByte = buf[i + 3]
+                                if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
+                                    tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
+                                    if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
+                                        codePoint = tempCodePoint
+                                    }
+                                }
+                        }
+                    }
+
+                    if (codePoint === null) {
+                        // we did not generate a valid codePoint so insert a
+                        // replacement char (U+FFFD) and advance only 1 byte
+                        codePoint = 0xFFFD
+                        bytesPerSequence = 1
+                    } else if (codePoint > 0xFFFF) {
+                        // encode to utf16 (surrogate pair dance)
+                        codePoint -= 0x10000
+                        res.push(codePoint >>> 10 & 0x3FF | 0xD800)
+                        codePoint = 0xDC00 | codePoint & 0x3FF
+                    }
+
+                    res.push(codePoint)
+                    i += bytesPerSequence
+                }
+
+                return decodeCodePointsArray(res)
+            }
+
+// Based on http://stackoverflow.com/a/22747272/680742, the browser with
+// the lowest limit is Chrome, with 0x10000 args.
+// We go 1 magnitude less, for safety
+            var MAX_ARGUMENTS_LENGTH = 0x1000
+
+            function decodeCodePointsArray(codePoints) {
+                var len = codePoints.length
+                if (len <= MAX_ARGUMENTS_LENGTH) {
+                    return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
+                }
+
+                // Decode in chunks to avoid "call stack size exceeded".
+                var res = ''
+                var i = 0
+                while (i < len) {
+                    res += String.fromCharCode.apply(
+                        String,
+                        codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
+                    )
+                }
+                return res
+            }
+
+            function asciiSlice(buf, start, end) {
+                var ret = ''
+                end = Math.min(buf.length, end)
+
+                for (var i = start; i < end; i++) {
+                    ret += String.fromCharCode(buf[i] & 0x7F)
+                }
+                return ret
+            }
+
+            function binarySlice(buf, start, end) {
+                var ret = ''
+                end = Math.min(buf.length, end)
+
+                for (var i = start; i < end; i++) {
+                    ret += String.fromCharCode(buf[i])
+                }
+                return ret
+            }
+
+            function hexSlice(buf, start, end) {
+                var len = buf.length
+
+                if (!start || start < 0) start = 0
+                if (!end || end < 0 || end > len) end = len
+
+                var out = ''
+                for (var i = start; i < end; i++) {
+                    out += toHex(buf[i])
+                }
+                return out
+            }
+
+            function utf16leSlice(buf, start, end) {
+                var bytes = buf.slice(start, end)
+                var res = ''
+                for (var i = 0; i < bytes.length; i += 2) {
+                    res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
+                }
+                return res
+            }
+
+            Buffer.prototype.slice = function slice(start, end) {
+                var len = this.length
+                start = ~~start
+                end = end === undefined ? len : ~~end
+
+                if (start < 0) {
+                    start += len
+                    if (start < 0) start = 0
+                } else if (start > len) {
+                    start = len
+                }
+
+                if (end < 0) {
+                    end += len
+                    if (end < 0) end = 0
+                } else if (end > len) {
+                    end = len
+                }
+
+                if (end < start) end = start
+
+                var newBuf
+                if (Buffer.TYPED_ARRAY_SUPPORT) {
+                    newBuf = this.subarray(start, end)
+                    newBuf.__proto__ = Buffer.prototype
+                } else {
+                    var sliceLen = end - start
+                    newBuf = new Buffer(sliceLen, undefined)
+                    for (var i = 0; i < sliceLen; i++) {
+                        newBuf[i] = this[i + start]
+                    }
+                }
+
+                if (newBuf.length) newBuf.parent = this.parent || this
+
+                return newBuf
+            }
+
+            /*
+ * Need to make sure that buffer isn't trying to write out of bounds.
+ */
+            function checkOffset(offset, ext, length) {
+                if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
+                if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
+            }
+
+            Buffer.prototype.readUIntLE = function readUIntLE(offset, byteLength, noAssert) {
+                offset = offset | 0
+                byteLength = byteLength | 0
+                if (!noAssert) checkOffset(offset, byteLength, this.length)
+
+                var val = this[offset]
+                var mul = 1
+                var i = 0
+                while (++i < byteLength && (mul *= 0x100)) {
+                    val += this[offset + i] * mul
+                }
+
+                return val
+            }
+
+            Buffer.prototype.readUIntBE = function readUIntBE(offset, byteLength, noAssert) {
+                offset = offset | 0
+                byteLength = byteLength | 0
+                if (!noAssert) {
+                    checkOffset(offset, byteLength, this.length)
+                }
+
+                var val = this[offset + --byteLength]
+                var mul = 1
+                while (byteLength > 0 && (mul *= 0x100)) {
+                    val += this[offset + --byteLength] * mul
+                }
+
+                return val
+            }
+
+            Buffer.prototype.readUInt8 = function readUInt8(offset, noAssert) {
+                if (!noAssert) checkOffset(offset, 1, this.length)
+                return this[offset]
+            }
+
+            Buffer.prototype.readUInt16LE = function readUInt16LE(offset, noAssert) {
+                if (!noAssert) checkOffset(offset, 2, this.length)
+                return this[offset] | (this[offset + 1] << 8)
+            }
+
+            Buffer.prototype.readUInt16BE = function readUInt16BE(offset, noAssert) {
+                if (!noAssert) checkOffset(offset, 2, this.length)
+                return (this[offset] << 8) | this[offset + 1]
+            }
+
+            Buffer.prototype.readUInt32LE = function readUInt32LE(offset, noAssert) {
+                if (!noAssert) checkOffset(offset, 4, this.length)
+
+                return ((this[offset]) |
+                    (this[offset + 1] << 8) |
+                    (this[offset + 2] << 16)) +
+                    (this[offset + 3] * 0x1000000)
+            }
+
+            Buffer.prototype.readUInt32BE = function readUInt32BE(offset, noAssert) {
+                if (!noAssert) checkOffset(offset, 4, this.length)
+
+                return (this[offset] * 0x1000000) +
+                    ((this[offset + 1] << 16) |
+                        (this[offset + 2] << 8) |
+                        this[offset + 3])
+            }
+
+            Buffer.prototype.readIntLE = function readIntLE(offset, byteLength, noAssert) {
+                offset = offset | 0
+                byteLength = byteLength | 0
+                if (!noAssert) checkOffset(offset, byteLength, this.length)
+
+                var val = this[offset]
+                var mul = 1
+                var i = 0
+                while (++i < byteLength && (mul *= 0x100)) {
+                    val += this[offset + i] * mul
+                }
+                mul *= 0x80
+
+                if (val >= mul) val -= Math.pow(2, 8 * byteLength)
+
+                return val
+            }
+
+            Buffer.prototype.readIntBE = function readIntBE(offset, byteLength, noAssert) {
+                offset = offset | 0
+                byteLength = byteLength | 0
+                if (!noAssert) checkOffset(offset, byteLength, this.length)
+
+                var i = byteLength
+                var mul = 1
+                var val = this[offset + --i]
+                while (i > 0 && (mul *= 0x100)) {
+                    val += this[offset + --i] * mul
+                }
+                mul *= 0x80
+
+                if (val >= mul) val -= Math.pow(2, 8 * byteLength)
+
+                return val
+            }
+
+            Buffer.prototype.readInt8 = function readInt8(offset, noAssert) {
+                if (!noAssert) checkOffset(offset, 1, this.length)
+                if (!(this[offset] & 0x80)) return (this[offset])
+                return ((0xff - this[offset] + 1) * -1)
+            }
+
+            Buffer.prototype.readInt16LE = function readInt16LE(offset, noAssert) {
+                if (!noAssert) checkOffset(offset, 2, this.length)
+                var val = this[offset] | (this[offset + 1] << 8)
+                return (val & 0x8000) ? val | 0xFFFF0000 : val
+            }
+
+            Buffer.prototype.readInt16BE = function readInt16BE(offset, noAssert) {
+                if (!noAssert) checkOffset(offset, 2, this.length)
+                var val = this[offset + 1] | (this[offset] << 8)
+                return (val & 0x8000) ? val | 0xFFFF0000 : val
+            }
+
+            Buffer.prototype.readInt32LE = function readInt32LE(offset, noAssert) {
+                if (!noAssert) checkOffset(offset, 4, this.length)
+
+                return (this[offset]) |
+                    (this[offset + 1] << 8) |
+                    (this[offset + 2] << 16) |
+                    (this[offset + 3] << 24)
+            }
+
+            Buffer.prototype.readInt32BE = function readInt32BE(offset, noAssert) {
+                if (!noAssert) checkOffset(offset, 4, this.length)
+
+                return (this[offset] << 24) |
+                    (this[offset + 1] << 16) |
+                    (this[offset + 2] << 8) |
+                    (this[offset + 3])
+            }
+
+            Buffer.prototype.readFloatLE = function readFloatLE(offset, noAssert) {
+                if (!noAssert) checkOffset(offset, 4, this.length)
+                return ieee754.read(this, offset, true, 23, 4)
+            }
+
+            Buffer.prototype.readFloatBE = function readFloatBE(offset, noAssert) {
+                if (!noAssert) checkOffset(offset, 4, this.length)
+                return ieee754.read(this, offset, false, 23, 4)
+            }
+
+            Buffer.prototype.readDoubleLE = function readDoubleLE(offset, noAssert) {
+                if (!noAssert) checkOffset(offset, 8, this.length)
+                return ieee754.read(this, offset, true, 52, 8)
+            }
+
+            Buffer.prototype.readDoubleBE = function readDoubleBE(offset, noAssert) {
+                if (!noAssert) checkOffset(offset, 8, this.length)
+                return ieee754.read(this, offset, false, 52, 8)
+            }
+
+            function checkInt(buf, value, offset, ext, max, min) {
+                if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
+                if (value > max || value < min) throw new RangeError('value is out of bounds')
+                if (offset + ext > buf.length) throw new RangeError('index out of range')
+            }
+
+            Buffer.prototype.writeUIntLE = function writeUIntLE(value, offset, byteLength, noAssert) {
+                value = +value
+                offset = offset | 0
+                byteLength = byteLength | 0
+                if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
+
+                var mul = 1
+                var i = 0
+                this[offset] = value & 0xFF
+                while (++i < byteLength && (mul *= 0x100)) {
+                    this[offset + i] = (value / mul) & 0xFF
+                }
+
+                return offset + byteLength
+            }
+
+            Buffer.prototype.writeUIntBE = function writeUIntBE(value, offset, byteLength, noAssert) {
+                value = +value
+                offset = offset | 0
+                byteLength = byteLength | 0
+                if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
+
+                var i = byteLength - 1
+                var mul = 1
+                this[offset + i] = value & 0xFF
+                while (--i >= 0 && (mul *= 0x100)) {
+                    this[offset + i] = (value / mul) & 0xFF
+                }
+
+                return offset + byteLength
+            }
+
+            Buffer.prototype.writeUInt8 = function writeUInt8(value, offset, noAssert) {
+                value = +value
+                offset = offset | 0
+                if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
+                if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
+                this[offset] = (value & 0xff)
+                return offset + 1
+            }
+
+            function objectWriteUInt16(buf, value, offset, littleEndian) {
+                if (value < 0) value = 0xffff + value + 1
+                for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
+                    buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
+                        (littleEndian ? i : 1 - i) * 8
+                }
+            }
+
+            Buffer.prototype.writeUInt16LE = function writeUInt16LE(value, offset, noAssert) {
+                value = +value
+                offset = offset | 0
+                if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
+                if (Buffer.TYPED_ARRAY_SUPPORT) {
+                    this[offset] = (value & 0xff)
+                    this[offset + 1] = (value >>> 8)
+                } else {
+                    objectWriteUInt16(this, value, offset, true)
+                }
+                return offset + 2
+            }
+
+            Buffer.prototype.writeUInt16BE = function writeUInt16BE(value, offset, noAssert) {
+                value = +value
+                offset = offset | 0
+                if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
+                if (Buffer.TYPED_ARRAY_SUPPORT) {
+                    this[offset] = (value >>> 8)
+                    this[offset + 1] = (value & 0xff)
+                } else {
+                    objectWriteUInt16(this, value, offset, false)
+                }
+                return offset + 2
+            }
+
+            function objectWriteUInt32(buf, value, offset, littleEndian) {
+                if (value < 0) value = 0xffffffff + value + 1
+                for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
+                    buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
+                }
+            }
+
+            Buffer.prototype.writeUInt32LE = function writeUInt32LE(value, offset, noAssert) {
+                value = +value
+                offset = offset | 0
+                if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
+                if (Buffer.TYPED_ARRAY_SUPPORT) {
+                    this[offset + 3] = (value >>> 24)
+                    this[offset + 2] = (value >>> 16)
+                    this[offset + 1] = (value >>> 8)
+                    this[offset] = (value & 0xff)
+                } else {
+                    objectWriteUInt32(this, value, offset, true)
+                }
+                return offset + 4
+            }
+
+            Buffer.prototype.writeUInt32BE = function writeUInt32BE(value, offset, noAssert) {
+                value = +value
+                offset = offset | 0
+                if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
+                if (Buffer.TYPED_ARRAY_SUPPORT) {
+                    this[offset] = (value >>> 24)
+                    this[offset + 1] = (value >>> 16)
+                    this[offset + 2] = (value >>> 8)
+                    this[offset + 3] = (value & 0xff)
+                } else {
+                    objectWriteUInt32(this, value, offset, false)
+                }
+                return offset + 4
+            }
+
+            Buffer.prototype.writeIntLE = function writeIntLE(value, offset, byteLength, noAssert) {
+                value = +value
+                offset = offset | 0
+                if (!noAssert) {
+                    var limit = Math.pow(2, 8 * byteLength - 1)
+
+                    checkInt(this, value, offset, byteLength, limit - 1, -limit)
+                }
+
+                var i = 0
+                var mul = 1
+                var sub = value < 0 ? 1 : 0
+                this[offset] = value & 0xFF
+                while (++i < byteLength && (mul *= 0x100)) {
+                    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
+                }
+
+                return offset + byteLength
+            }
+
+            Buffer.prototype.writeIntBE = function writeIntBE(value, offset, byteLength, noAssert) {
+                value = +value
+                offset = offset | 0
+                if (!noAssert) {
+                    var limit = Math.pow(2, 8 * byteLength - 1)
+
+                    checkInt(this, value, offset, byteLength, limit - 1, -limit)
+                }
+
+                var i = byteLength - 1
+                var mul = 1
+                var sub = value < 0 ? 1 : 0
+                this[offset + i] = value & 0xFF
+                while (--i >= 0 && (mul *= 0x100)) {
+                    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
+                }
+
+                return offset + byteLength
+            }
+
+            Buffer.prototype.writeInt8 = function writeInt8(value, offset, noAssert) {
+                value = +value
+                offset = offset | 0
+                if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
+                if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
+                if (value < 0) value = 0xff + value + 1
+                this[offset] = (value & 0xff)
+                return offset + 1
+            }
+
+            Buffer.prototype.writeInt16LE = function writeInt16LE(value, offset, noAssert) {
+                value = +value
+                offset = offset | 0
+                if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
+                if (Buffer.TYPED_ARRAY_SUPPORT) {
+                    this[offset] = (value & 0xff)
+                    this[offset + 1] = (value >>> 8)
+                } else {
+                    objectWriteUInt16(this, value, offset, true)
+                }
+                return offset + 2
+            }
+
+            Buffer.prototype.writeInt16BE = function writeInt16BE(value, offset, noAssert) {
+                value = +value
+                offset = offset | 0
+                if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
+                if (Buffer.TYPED_ARRAY_SUPPORT) {
+                    this[offset] = (value >>> 8)
+                    this[offset + 1] = (value & 0xff)
+                } else {
+                    objectWriteUInt16(this, value, offset, false)
+                }
+                return offset + 2
+            }
+
+            Buffer.prototype.writeInt32LE = function writeInt32LE(value, offset, noAssert) {
+                value = +value
+                offset = offset | 0
+                if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
+                if (Buffer.TYPED_ARRAY_SUPPORT) {
+                    this[offset] = (value & 0xff)
+                    this[offset + 1] = (value >>> 8)
+                    this[offset + 2] = (value >>> 16)
+                    this[offset + 3] = (value >>> 24)
+                } else {
+                    objectWriteUInt32(this, value, offset, true)
+                }
+                return offset + 4
+            }
+
+            Buffer.prototype.writeInt32BE = function writeInt32BE(value, offset, noAssert) {
+                value = +value
+                offset = offset | 0
+                if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
+                if (value < 0) value = 0xffffffff + value + 1
+                if (Buffer.TYPED_ARRAY_SUPPORT) {
+                    this[offset] = (value >>> 24)
+                    this[offset + 1] = (value >>> 16)
+                    this[offset + 2] = (value >>> 8)
+                    this[offset + 3] = (value & 0xff)
+                } else {
+                    objectWriteUInt32(this, value, offset, false)
+                }
+                return offset + 4
+            }
+
+            function checkIEEE754(buf, value, offset, ext, max, min) {
+                if (offset + ext > buf.length) throw new RangeError('index out of range')
+                if (offset < 0) throw new RangeError('index out of range')
+            }
+
+            function writeFloat(buf, value, offset, littleEndian, noAssert) {
+                if (!noAssert) {
+                    checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
+                }
+                ieee754.write(buf, value, offset, littleEndian, 23, 4)
+                return offset + 4
+            }
+
+            Buffer.prototype.writeFloatLE = function writeFloatLE(value, offset, noAssert) {
+                return writeFloat(this, value, offset, true, noAssert)
+            }
+
+            Buffer.prototype.writeFloatBE = function writeFloatBE(value, offset, noAssert) {
+                return writeFloat(this, value, offset, false, noAssert)
+            }
+
+            function writeDouble(buf, value, offset, littleEndian, noAssert) {
+                if (!noAssert) {
+                    checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
+                }
+                ieee754.write(buf, value, offset, littleEndian, 52, 8)
+                return offset + 8
+            }
+
+            Buffer.prototype.writeDoubleLE = function writeDoubleLE(value, offset, noAssert) {
+                return writeDouble(this, value, offset, true, noAssert)
+            }
+
+            Buffer.prototype.writeDoubleBE = function writeDoubleBE(value, offset, noAssert) {
+                return writeDouble(this, value, offset, false, noAssert)
+            }
+
+// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
+            Buffer.prototype.copy = function copy(target, targetStart, start, end) {
+                if (!start) start = 0
+                if (!end && end !== 0) end = this.length
+                if (targetStart >= target.length) targetStart = target.length
+                if (!targetStart) targetStart = 0
+                if (end > 0 && end < start) end = start
+
+                // Copy 0 bytes; we're done
+                if (end === start) return 0
+                if (target.length === 0 || this.length === 0) return 0
+
+                // Fatal error conditions
+                if (targetStart < 0) {
+                    throw new RangeError('targetStart out of bounds')
+                }
+                if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
+                if (end < 0) throw new RangeError('sourceEnd out of bounds')
+
+                // Are we oob?
+                if (end > this.length) end = this.length
+                if (target.length - targetStart < end - start) {
+                    end = target.length - targetStart + start
+                }
+
+                var len = end - start
+                var i
+
+                if (this === target && start < targetStart && targetStart < end) {
+                    // descending copy from end
+                    for (i = len - 1; i >= 0; i--) {
+                        target[i + targetStart] = this[i + start]
+                    }
+                } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
+                    // ascending copy from start
+                    for (i = 0; i < len; i++) {
+                        target[i + targetStart] = this[i + start]
+                    }
+                } else {
+                    Uint8Array.prototype.set.call(
+                        target,
+                        this.subarray(start, start + len),
+                        targetStart
+                    )
+                }
+
+                return len
+            }
+
+// fill(value, start=0, end=buffer.length)
+            Buffer.prototype.fill = function fill(value, start, end) {
+                if (!value) value = 0
+                if (!start) start = 0
+                if (!end) end = this.length
+
+                if (end < start) throw new RangeError('end < start')
+
+                // Fill 0 bytes; we're done
+                if (end === start) return
+                if (this.length === 0) return
+
+                if (start < 0 || start >= this.length) throw new RangeError('start out of bounds')
+                if (end < 0 || end > this.length) throw new RangeError('end out of bounds')
+
+                var i
+                if (typeof value === 'number') {
+                    for (i = start; i < end; i++) {
+                        this[i] = value
+                    }
+                } else {
+                    var bytes = utf8ToBytes(value.toString())
+                    var len = bytes.length
+                    for (i = start; i < end; i++) {
+                        this[i] = bytes[i % len]
+                    }
+                }
+
+                return this
+            }
+
+// HELPER FUNCTIONS
+// ================
+
+            var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
+
+            function base64clean(str) {
+                // Node strips out invalid characters like \n and \t from the string, base64-js does not
+                str = stringtrim(str).replace(INVALID_BASE64_RE, '')
+                // Node converts strings with length < 2 to ''
+                if (str.length < 2) return ''
+                // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
+                while (str.length % 4 !== 0) {
+                    str = str + '='
+                }
+                return str
+            }
+
+            function stringtrim(str) {
+                if (str.trim) return str.trim()
+                return str.replace(/^\s+|\s+$/g, '')
+            }
+
+            function toHex(n) {
+                if (n < 16) return '0' + n.toString(16)
+                return n.toString(16)
+            }
+
+            function utf8ToBytes(string, units) {
+                units = units || Infinity
+                var codePoint
+                var length = string.length
+                var leadSurrogate = null
+                var bytes = []
+
+                for (var i = 0; i < length; i++) {
+                    codePoint = string.charCodeAt(i)
+
+                    // is surrogate component
+                    if (codePoint > 0xD7FF && codePoint < 0xE000) {
+                        // last char was a lead
+                        if (!leadSurrogate) {
+                            // no lead yet
+                            if (codePoint > 0xDBFF) {
+                                // unexpected trail
+                                if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+                                continue
+                            } else if (i + 1 === length) {
+                                // unpaired lead
+                                if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+                                continue
+                            }
+
+                            // valid lead
+                            leadSurrogate = codePoint
+
+                            continue
+                        }
+
+                        // 2 leads in a row
+                        if (codePoint < 0xDC00) {
+                            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+                            leadSurrogate = codePoint
+                            continue
+                        }
+
+                        // valid surrogate pair
+                        codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
+                    } else if (leadSurrogate) {
+                        // valid bmp char, but last char was a lead
+                        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+                    }
+
+                    leadSurrogate = null
+
+                    // encode utf8
+                    if (codePoint < 0x80) {
+                        if ((units -= 1) < 0) break
+                        bytes.push(codePoint)
+                    } else if (codePoint < 0x800) {
+                        if ((units -= 2) < 0) break
+                        bytes.push(
+                            codePoint >> 0x6 | 0xC0,
+                            codePoint & 0x3F | 0x80
+                        )
+                    } else if (codePoint < 0x10000) {
+                        if ((units -= 3) < 0) break
+                        bytes.push(
+                            codePoint >> 0xC | 0xE0,
+                            codePoint >> 0x6 & 0x3F | 0x80,
+                            codePoint & 0x3F | 0x80
+                        )
+                    } else if (codePoint < 0x110000) {
+                        if ((units -= 4) < 0) break
+                        bytes.push(
+                            codePoint >> 0x12 | 0xF0,
+                            codePoint >> 0xC & 0x3F | 0x80,
+                            codePoint >> 0x6 & 0x3F | 0x80,
+                            codePoint & 0x3F | 0x80
+                        )
+                    } else {
+                        throw new Error('Invalid code point')
+                    }
+                }
+
+                return bytes
+            }
+
+            function asciiToBytes(str) {
+                var byteArray = []
+                for (var i = 0; i < str.length; i++) {
+                    // Node's code seems to be doing this and not & 0x7F..
+                    byteArray.push(str.charCodeAt(i) & 0xFF)
+                }
+                return byteArray
+            }
+
+            function utf16leToBytes(str, units) {
+                var c, hi, lo
+                var byteArray = []
+                for (var i = 0; i < str.length; i++) {
+                    if ((units -= 2) < 0) break
+
+                    c = str.charCodeAt(i)
+                    hi = c >> 8
+                    lo = c % 256
+                    byteArray.push(lo)
+                    byteArray.push(hi)
+                }
+
+                return byteArray
+            }
+
+            function base64ToBytes(str) {
+                return base64.toByteArray(base64clean(str))
+            }
+
+            function blitBuffer(src, dst, offset, length) {
+                for (var i = 0; i < length; i++) {
+                    if ((i + offset >= dst.length) || (i >= src.length)) break
+                    dst[i + offset] = src[i]
+                }
+                return i
+            }
+
+        }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+    }, {"base64-js": 37, "ieee754": 38, "isarray": 39}],
+    37: [function (require, module, exports) {
+        'use strict'
+
+        exports.toByteArray = toByteArray
+        exports.fromByteArray = fromByteArray
+
+        var lookup = []
+        var revLookup = []
+        var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
+
+        function init() {
+            var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
+            for (var i = 0, len = code.length; i < len; ++i) {
+                lookup[i] = code[i]
+                revLookup[code.charCodeAt(i)] = i
+            }
+
+            revLookup['-'.charCodeAt(0)] = 62
+            revLookup['_'.charCodeAt(0)] = 63
+        }
+
+        init()
+
+        function toByteArray(b64) {
+            var i, j, l, tmp, placeHolders, arr
+            var len = b64.length
+
+            if (len % 4 > 0) {
+                throw new Error('Invalid string. Length must be a multiple of 4')
+            }
+
+            // the number of equal signs (place holders)
+            // if there are two placeholders, than the two characters before it
+            // represent one byte
+            // if there is only one, then the three characters before it represent 2 bytes
+            // this is just a cheap hack to not do indexOf twice
+            placeHolders = b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0
+
+            // base64 is 4/3 + up to two characters of the original data
+            arr = new Arr(len * 3 / 4 - placeHolders)
+
+            // if there are placeholders, only get up to the last complete 4 chars
+            l = placeHolders > 0 ? len - 4 : len
+
+            var L = 0
+
+            for (i = 0, j = 0; i < l; i += 4, j += 3) {
+                tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]
+                arr[L++] = (tmp >> 16) & 0xFF
+                arr[L++] = (tmp >> 8) & 0xFF
+                arr[L++] = tmp & 0xFF
+            }
+
+            if (placeHolders === 2) {
+                tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)
+                arr[L++] = tmp & 0xFF
+            } else if (placeHolders === 1) {
+                tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)
+                arr[L++] = (tmp >> 8) & 0xFF
+                arr[L++] = tmp & 0xFF
+            }
+
+            return arr
+        }
+
+        function tripletToBase64(num) {
+            return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]
+        }
+
+        function encodeChunk(uint8, start, end) {
+            var tmp
+            var output = []
+            for (var i = start; i < end; i += 3) {
+                tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
+                output.push(tripletToBase64(tmp))
+            }
+            return output.join('')
+        }
+
+        function fromByteArray(uint8) {
+            var tmp
+            var len = uint8.length
+            var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
+            var output = ''
+            var parts = []
+            var maxChunkLength = 16383 // must be multiple of 3
+
+            // go through the array every three bytes, we'll deal with trailing stuff later
+            for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
+                parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
+            }
+
+            // pad the end with zeros, but make sure to not forget the extra bytes
+            if (extraBytes === 1) {
+                tmp = uint8[len - 1]
+                output += lookup[tmp >> 2]
+                output += lookup[(tmp << 4) & 0x3F]
+                output += '=='
+            } else if (extraBytes === 2) {
+                tmp = (uint8[len - 2] << 8) + (uint8[len - 1])
+                output += lookup[tmp >> 10]
+                output += lookup[(tmp >> 4) & 0x3F]
+                output += lookup[(tmp << 2) & 0x3F]
+                output += '='
+            }
+
+            parts.push(output)
+
+            return parts.join('')
+        }
+
+    }, {}],
+    38: [function (require, module, exports) {
+        exports.read = function (buffer, offset, isLE, mLen, nBytes) {
+            var e, m
+            var eLen = nBytes * 8 - mLen - 1
+            var eMax = (1 << eLen) - 1
+            var eBias = eMax >> 1
+            var nBits = -7
+            var i = isLE ? (nBytes - 1) : 0
+            var d = isLE ? -1 : 1
+            var s = buffer[offset + i]
+
+            i += d
+
+            e = s & ((1 << (-nBits)) - 1)
+            s >>= (-nBits)
+            nBits += eLen
+            for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {
+            }
+
+            m = e & ((1 << (-nBits)) - 1)
+            e >>= (-nBits)
+            nBits += mLen
+            for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {
+            }
+
+            if (e === 0) {
+                e = 1 - eBias
+            } else if (e === eMax) {
+                return m ? NaN : ((s ? -1 : 1) * Infinity)
+            } else {
+                m = m + Math.pow(2, mLen)
+                e = e - eBias
+            }
+            return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
+        }
+
+        exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
+            var e, m, c
+            var eLen = nBytes * 8 - mLen - 1
+            var eMax = (1 << eLen) - 1
+            var eBias = eMax >> 1
+            var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
+            var i = isLE ? 0 : (nBytes - 1)
+            var d = isLE ? 1 : -1
+            var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
+
+            value = Math.abs(value)
+
+            if (isNaN(value) || value === Infinity) {
+                m = isNaN(value) ? 1 : 0
+                e = eMax
+            } else {
+                e = Math.floor(Math.log(value) / Math.LN2)
+                if (value * (c = Math.pow(2, -e)) < 1) {
+                    e--
+                    c *= 2
+                }
+                if (e + eBias >= 1) {
+                    value += rt / c
+                } else {
+                    value += rt * Math.pow(2, 1 - eBias)
+                }
+                if (value * c >= 2) {
+                    e++
+                    c /= 2
+                }
+
+                if (e + eBias >= eMax) {
+                    m = 0
+                    e = eMax
+                } else if (e + eBias >= 1) {
+                    m = (value * c - 1) * Math.pow(2, mLen)
+                    e = e + eBias
+                } else {
+                    m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
+                    e = 0
+                }
+            }
+
+            for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {
+            }
+
+            e = (e << mLen) | m
+            eLen += mLen
+            for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {
+            }
+
+            buffer[offset + i - d] |= s * 128
+        }
+
+    }, {}],
+    39: [function (require, module, exports) {
+        var toString = {}.toString;
+
+        module.exports = Array.isArray || function (arr) {
+            return toString.call(arr) == '[object Array]';
+        };
+
+    }, {}],
+    40: [function (require, module, exports) {
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+        function EventEmitter() {
+            this._events = this._events || {};
+            this._maxListeners = this._maxListeners || undefined;
+        }
+
+        module.exports = EventEmitter;
+
+// Backwards-compat with node 0.10.x
+        EventEmitter.EventEmitter = EventEmitter;
+
+        EventEmitter.prototype._events = undefined;
+        EventEmitter.prototype._maxListeners = undefined;
+
+// By default EventEmitters will print a warning if more than 10 listeners are
+// added to it. This is a useful default which helps finding memory leaks.
+        EventEmitter.defaultMaxListeners = 10;
+
+// Obviously not all Emitters should be limited to 10. This function allows
+// that to be increased. Set to zero for unlimited.
+        EventEmitter.prototype.setMaxListeners = function (n) {
+            if (!isNumber(n) || n < 0 || isNaN(n))
+                throw TypeError('n must be a positive number');
+            this._maxListeners = n;
+            return this;
+        };
+
+        EventEmitter.prototype.emit = function (type) {
+            var er, handler, len, args, i, listeners;
+
+            if (!this._events)
+                this._events = {};
+
+            // If there is no 'error' event listener then throw.
+            if (type === 'error') {
+                if (!this._events.error ||
+                    (isObject(this._events.error) && !this._events.error.length)) {
+                    er = arguments[1];
+                    if (er instanceof Error) {
+                        throw er; // Unhandled 'error' event
+                    }
+                    throw TypeError('Uncaught, unspecified "error" event.');
+                }
+            }
+
+            handler = this._events[type];
+
+            if (isUndefined(handler))
+                return false;
+
+            if (isFunction(handler)) {
+                switch (arguments.length) {
+                    // fast cases
+                    case 1:
+                        handler.call(this);
+                        break;
+                    case 2:
+                        handler.call(this, arguments[1]);
+                        break;
+                    case 3:
+                        handler.call(this, arguments[1], arguments[2]);
+                        break;
+                    // slower
+                    default:
+                        args = Array.prototype.slice.call(arguments, 1);
+                        handler.apply(this, args);
+                }
+            } else if (isObject(handler)) {
+                args = Array.prototype.slice.call(arguments, 1);
+                listeners = handler.slice();
+                len = listeners.length;
+                for (i = 0; i < len; i++)
+                    listeners[i].apply(this, args);
+            }
+
+            return true;
+        };
+
+        EventEmitter.prototype.addListener = function (type, listener) {
+            var m;
+
+            if (!isFunction(listener))
+                throw TypeError('listener must be a function');
+
+            if (!this._events)
+                this._events = {};
+
+            // To avoid recursion in the case that type === "newListener"! Before
+            // adding it to the listeners, first emit "newListener".
+            if (this._events.newListener)
+                this.emit('newListener', type,
+                    isFunction(listener.listener) ?
+                        listener.listener : listener);
+
+            if (!this._events[type])
+            // Optimize the case of one listener. Don't need the extra array object.
+                this._events[type] = listener;
+            else if (isObject(this._events[type]))
+            // If we've already got an array, just append.
+                this._events[type].push(listener);
+            else
+            // Adding the second element, need to change to array.
+                this._events[type] = [this._events[type], listener];
+
+            // Check for listener leak
+            if (isObject(this._events[type]) && !this._events[type].warned) {
+                if (!isUndefined(this._maxListeners)) {
+                    m = this._maxListeners;
+                } else {
+                    m = EventEmitter.defaultMaxListeners;
+                }
+
+                if (m && m > 0 && this._events[type].length > m) {
+                    this._events[type].warned = true;
+                    console.error('(node) warning: possible EventEmitter memory ' +
+                        'leak detected. %d listeners added. ' +
+                        'Use emitter.setMaxListeners() to increase limit.',
+                        this._events[type].length);
+                    if (typeof console.trace === 'function') {
+                        // not supported in IE 10
+                        console.trace();
+                    }
+                }
+            }
+
+            return this;
+        };
+
+        EventEmitter.prototype.on = EventEmitter.prototype.addListener;
+
+        EventEmitter.prototype.once = function (type, listener) {
+            if (!isFunction(listener))
+                throw TypeError('listener must be a function');
+
+            var fired = false;
+
+            function g() {
+                this.removeListener(type, g);
+
+                if (!fired) {
+                    fired = true;
+                    listener.apply(this, arguments);
+                }
+            }
+
+            g.listener = listener;
+            this.on(type, g);
+
+            return this;
+        };
+
+// emits a 'removeListener' event iff the listener was removed
+        EventEmitter.prototype.removeListener = function (type, listener) {
+            var list, position, length, i;
+
+            if (!isFunction(listener))
+                throw TypeError('listener must be a function');
+
+            if (!this._events || !this._events[type])
+                return this;
+
+            list = this._events[type];
+            length = list.length;
+            position = -1;
+
+            if (list === listener ||
+                (isFunction(list.listener) && list.listener === listener)) {
+                delete this._events[type];
+                if (this._events.removeListener)
+                    this.emit('removeListener', type, listener);
+
+            } else if (isObject(list)) {
+                for (i = length; i-- > 0;) {
+                    if (list[i] === listener ||
+                        (list[i].listener && list[i].listener === listener)) {
+                        position = i;
+                        break;
+                    }
+                }
+
+                if (position < 0)
+                    return this;
+
+                if (list.length === 1) {
+                    list.length = 0;
+                    delete this._events[type];
+                } else {
+                    list.splice(position, 1);
+                }
+
+                if (this._events.removeListener)
+                    this.emit('removeListener', type, listener);
+            }
+
+            return this;
+        };
+
+        EventEmitter.prototype.removeAllListeners = function (type) {
+            var key, listeners;
+
+            if (!this._events)
+                return this;
+
+            // not listening for removeListener, no need to emit
+            if (!this._events.removeListener) {
+                if (arguments.length === 0)
+                    this._events = {};
+                else if (this._events[type])
+                    delete this._events[type];
+                return this;
+            }
+
+            // emit removeListener for all listeners on all events
+            if (arguments.length === 0) {
+                for (key in this._events) {
+                    if (key === 'removeListener') continue;
+                    this.removeAllListeners(key);
+                }
+                this.removeAllListeners('removeListener');
+                this._events = {};
+                return this;
+            }
+
+            listeners = this._events[type];
+
+            if (isFunction(listeners)) {
+                this.removeListener(type, listeners);
+            } else if (listeners) {
+                // LIFO order
+                while (listeners.length)
+                    this.removeListener(type, listeners[listeners.length - 1]);
+            }
+            delete this._events[type];
+
+            return this;
+        };
+
+        EventEmitter.prototype.listeners = function (type) {
+            var ret;
+            if (!this._events || !this._events[type])
+                ret = [];
+            else if (isFunction(this._events[type]))
+                ret = [this._events[type]];
+            else
+                ret = this._events[type].slice();
+            return ret;
+        };
+
+        EventEmitter.prototype.listenerCount = function (type) {
+            if (this._events) {
+                var evlistener = this._events[type];
+
+                if (isFunction(evlistener))
+                    return 1;
+                else if (evlistener)
+                    return evlistener.length;
+            }
+            return 0;
+        };
+
+        EventEmitter.listenerCount = function (emitter, type) {
+            return emitter.listenerCount(type);
+        };
+
+        function isFunction(arg) {
+            return typeof arg === 'function';
+        }
+
+        function isNumber(arg) {
+            return typeof arg === 'number';
+        }
+
+        function isObject(arg) {
+            return typeof arg === 'object' && arg !== null;
+        }
+
+        function isUndefined(arg) {
+            return arg === void 0;
+        }
+
+    }, {}],
+    41: [function (require, module, exports) {
+        if (typeof Object.create === 'function') {
+            // implementation from standard node.js 'util' module
+            module.exports = function inherits(ctor, superCtor) {
+                ctor.super_ = superCtor
+                ctor.prototype = Object.create(superCtor.prototype, {
+                    constructor: {
+                        value: ctor,
+                        enumerable: false,
+                        writable: true,
+                        configurable: true
+                    }
+                });
+            };
+        } else {
+            // old school shim for old browsers
+            module.exports = function inherits(ctor, superCtor) {
+                ctor.super_ = superCtor
+                var TempCtor = function () {
+                }
+                TempCtor.prototype = superCtor.prototype
+                ctor.prototype = new TempCtor()
+                ctor.prototype.constructor = ctor
+            }
+        }
+
+    }, {}],
+    42: [function (require, module, exports) {
+        /**
+         * Determine if an object is Buffer
+         *
+         * Author:   Feross Aboukhadijeh <[email protected]> <http://feross.org>
+         * License:  MIT
+         *
+         * `npm install is-buffer`
+         */
+
+        module.exports = function (obj) {
+            return !!(obj != null &&
+                (obj._isBuffer || // For Safari 5-7 (missing Object.prototype.constructor)
+                    (obj.constructor &&
+                        typeof obj.constructor.isBuffer === 'function' &&
+                        obj.constructor.isBuffer(obj))
+                ))
+        }
+
+    }, {}],
+    43: [function (require, module, exports) {
+// shim for using process in browser
+
+        var process = module.exports = {};
+        var queue = [];
+        var draining = false;
+        var currentQueue;
+        var queueIndex = -1;
+
+        function cleanUpNextTick() {
+            draining = false;
+            if (currentQueue.length) {
+                queue = currentQueue.concat(queue);
+            } else {
+                queueIndex = -1;
+            }
+            if (queue.length) {
+                drainQueue();
+            }
+        }
+
+        function drainQueue() {
+            if (draining) {
+                return;
+            }
+            var timeout = setTimeout(cleanUpNextTick);
+            draining = true;
+
+            var len = queue.length;
+            while (len) {
+                currentQueue = queue;
+                queue = [];
+                while (++queueIndex < len) {
+                    if (currentQueue) {
+                        currentQueue[queueIndex].run();
+                    }
+                }
+                queueIndex = -1;
+                len = queue.length;
+            }
+            currentQueue = null;
+            draining = false;
+            clearTimeout(timeout);
+        }
+
+        process.nextTick = function (fun) {
+            var args = new Array(arguments.length - 1);
+            if (arguments.length > 1) {
+                for (var i = 1; i < arguments.length; i++) {
+                    args[i - 1] = arguments[i];
+                }
+            }
+            queue.push(new Item(fun, args));
+            if (queue.length === 1 && !draining) {
+                setTimeout(drainQueue, 0);
+            }
+        };
+
+// v8 likes predictible objects
+        function Item(fun, array) {
+            this.fun = fun;
+            this.array = array;
+        }
+
+        Item.prototype.run = function () {
+            this.fun.apply(null, this.array);
+        };
+        process.title = 'browser';
+        process.browser = true;
+        process.env = {};
+        process.argv = [];
+        process.version = ''; // empty string to avoid regexp issues
+        process.versions = {};
+
+        function noop() {
+        }
+
+        process.on = noop;
+        process.addListener = noop;
+        process.once = noop;
+        process.off = noop;
+        process.removeListener = noop;
+        process.removeAllListeners = noop;
+        process.emit = noop;
+
+        process.binding = function (name) {
+            throw new Error('process.binding is not supported');
+        };
+
+        process.cwd = function () {
+            return '/'
+        };
+        process.chdir = function (dir) {
+            throw new Error('process.chdir is not supported');
+        };
+        process.umask = function () {
+            return 0;
+        };
+
+    }, {}],
+    44: [function (require, module, exports) {
+        module.exports = require("./lib/_stream_duplex.js")
+
+    }, {"./lib/_stream_duplex.js": 45}],
+    45: [function (require, module, exports) {
+// a duplex stream is just a stream that is both readable and writable.
+// Since JS doesn't have multiple prototypal inheritance, this class
+// prototypally inherits from Readable, and then parasitically from
+// Writable.
+
+        'use strict';
+
+        /*<replacement>*/
+
+        var objectKeys = Object.keys || function (obj) {
+            var keys = [];
+            for (var key in obj) {
+                keys.push(key);
+            }
+            return keys;
+        };
+        /*</replacement>*/
+
+        module.exports = Duplex;
+
+        /*<replacement>*/
+        var processNextTick = require('process-nextick-args');
+        /*</replacement>*/
+
+        /*<replacement>*/
+        var util = require('core-util-is');
+        util.inherits = require('inherits');
+        /*</replacement>*/
+
+        var Readable = require('./_stream_readable');
+        var Writable = require('./_stream_writable');
+
+        util.inherits(Duplex, Readable);
+
+        var keys = objectKeys(Writable.prototype);
+        for (var v = 0; v < keys.length; v++) {
+            var method = keys[v];
+            if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method];
+        }
+
+        function Duplex(options) {
+            if (!(this instanceof Duplex)) return new Duplex(options);
+
+            Readable.call(this, options);
+            Writable.call(this, options);
+
+            if (options && options.readable === false) this.readable = false;
+
+            if (options && options.writable === false) this.writable = false;
+
+            this.allowHalfOpen = true;
+            if (options && options.allowHalfOpen === false) this.allowHalfOpen = false;
+
+            this.once('end', onend);
+        }
+
+// the no-half-open enforcer
+        function onend() {
+            // if we allow half-open state, or if the writable side ended,
+            // then we're ok.
+            if (this.allowHalfOpen || this._writableState.ended) return;
+
+            // no more data can be written.
+            // But allow more writes to happen in this tick.
+            processNextTick(onEndNT, this);
+        }
+
+        function onEndNT(self) {
+            self.end();
+        }
+
+        function forEach(xs, f) {
+            for (var i = 0, l = xs.length; i < l; i++) {
+                f(xs[i], i);
+            }
+        }
+    }, {
+        "./_stream_readable": 47,
+        "./_stream_writable": 49,
+        "core-util-is": 50,
+        "inherits": 41,
+        "process-nextick-args": 52
+    }],
+    46: [function (require, module, exports) {
+// a passthrough stream.
+// basically just the most minimal sort of Transform stream.
+// Every written chunk gets output as-is.
+
+        'use strict';
+
+        module.exports = PassThrough;
+
+        var Transform = require('./_stream_transform');
+
+        /*<replacement>*/
+        var util = require('core-util-is');
+        util.inherits = require('inherits');
+        /*</replacement>*/
+
+        util.inherits(PassThrough, Transform);
+
+        function PassThrough(options) {
+            if (!(this instanceof PassThrough)) return new PassThrough(options);
+
+            Transform.call(this, options);
+        }
+
+        PassThrough.prototype._transform = function (chunk, encoding, cb) {
+            cb(null, chunk);
+        };
+    }, {"./_stream_transform": 48, "core-util-is": 50, "inherits": 41}],
+    47: [function (require, module, exports) {
+        (function (process) {
+            'use strict';
+
+            module.exports = Readable;
+
+            /*<replacement>*/
+            var processNextTick = require('process-nextick-args');
+            /*</replacement>*/
+
+            /*<replacement>*/
+            var isArray = require('isarray');
+            /*</replacement>*/
+
+            /*<replacement>*/
+            var Buffer = require('buffer').Buffer;
+            /*</replacement>*/
+
+            Readable.ReadableState = ReadableState;
+
+            var EE = require('events');
+
+            /*<replacement>*/
+            var EElistenerCount = function (emitter, type) {
+                return emitter.listeners(type).length;
+            };
+            /*</replacement>*/
+
+            /*<replacement>*/
+            var Stream;
+            (function () {
+                try {
+                    Stream = require('st' + 'ream');
+                } catch (_) {
+                } finally {
+                    if (!Stream) Stream = require('events').EventEmitter;
+                }
+            })();
+            /*</replacement>*/
+
+            var Buffer = require('buffer').Buffer;
+
+            /*<replacement>*/
+            var util = require('core-util-is');
+            util.inherits = require('inherits');
+            /*</replacement>*/
+
+            /*<replacement>*/
+            var debugUtil = require('util');
+            var debug = undefined;
+            if (debugUtil && debugUtil.debuglog) {
+                debug = debugUtil.debuglog('stream');
+            } else {
+                debug = function () {
+                };
+            }
+            /*</replacement>*/
+
+            var StringDecoder;
+
+            util.inherits(Readable, Stream);
+
+            var Duplex;
+
+            function ReadableState(options, stream) {
+                Duplex = Duplex || require('./_stream_duplex');
+
+                options = options || {};
+
+                // object stream flag. Used to make read(n) ignore n and to
+                // make all the buffer merging and length checks go away
+                this.objectMode = !!options.objectMode;
+
+                if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.readableObjectMode;
+
+                // the point at which it stops calling _read() to fill the buffer
+                // Note: 0 is a valid value, means "don't call _read preemptively ever"
+                var hwm = options.highWaterMark;
+                var defaultHwm = this.objectMode ? 16 : 16 * 1024;
+                this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm;
+
+                // cast to ints.
+                this.highWaterMark = ~~this.highWaterMark;
+
+                this.buffer = [];
+                this.length = 0;
+                this.pipes = null;
+                this.pipesCount = 0;
+                this.flowing = null;
+                this.ended = false;
+                this.endEmitted = false;
+                this.reading = false;
+
+                // a flag to be able to tell if the onwrite cb is called immediately,
+                // or on a later tick.  We set this to true at first, because any
+                // actions that shouldn't happen until "later" should generally also
+                // not happen before the first write call.
+                this.sync = true;
+
+                // whenever we return null, then we set a flag to say
+                // that we're awaiting a 'readable' event emission.
+                this.needReadable = false;
+                this.emittedReadable = false;
+                this.readableListening = false;
+                this.resumeScheduled = false;
+
+                // Crypto is kind of old and crusty.  Historically, its default string
+                // encoding is 'binary' so we have to make this configurable.
+                // Everything else in the universe uses 'utf8', though.
+                this.defaultEncoding = options.defaultEncoding || 'utf8';
+
+                // when piping, we only care about 'readable' events that happen
+                // after read()ing all the bytes and not getting any pushback.
+                this.ranOut = false;
+
+                // the number of writers that are awaiting a drain event in .pipe()s
+                this.awaitDrain = 0;
+
+                // if true, a maybeReadMore has been scheduled
+                this.readingMore = false;
+
+                this.decoder = null;
+                this.encoding = null;
+                if (options.encoding) {
+                    if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder;
+                    this.decoder = new StringDecoder(options.encoding);
+                    this.encoding = options.encoding;
+                }
+            }
+
+            var Duplex;
+
+            function Readable(options) {
+                Duplex = Duplex || require('./_stream_duplex');
+
+                if (!(this instanceof Readable)) return new Readable(options);
+
+                this._readableState = new ReadableState(options, this);
+
+                // legacy
+                this.readable = true;
+
+                if (options && typeof options.read === 'function') this._read = options.read;
+
+                Stream.call(this);
+            }
+
+// Manually shove something into the read() buffer.
+// This returns true if the highWaterMark has not been hit yet,
+// similar to how Writable.write() returns true if you should
+// write() some more.
+            Readable.prototype.push = function (chunk, encoding) {
+                var state = this._readableState;
+
+                if (!state.objectMode && typeof chunk === 'string') {
+                    encoding = encoding || state.defaultEncoding;
+                    if (encoding !== state.encoding) {
+                        chunk = new Buffer(chunk, encoding);
+                        encoding = '';
+                    }
+                }
+
+                return readableAddChunk(this, state, chunk, encoding, false);
+            };
+
+// Unshift should *always* be something directly out of read()
+            Readable.prototype.unshift = function (chunk) {
+                var state = this._readableState;
+                return readableAddChunk(this, state, chunk, '', true);
+            };
+
+            Readable.prototype.isPaused = function () {
+                return this._readableState.flowing === false;
+            };
+
+            function readableAddChunk(stream, state, chunk, encoding, addToFront) {
+                var er = chunkInvalid(state, chunk);
+                if (er) {
+                    stream.emit('error', er);
+                } else if (chunk === null) {
+                    state.reading = false;
+                    onEofChunk(stream, state);
+                } else if (state.objectMode || chunk && chunk.length > 0) {
+                    if (state.ended && !addToFront) {
+                        var e = new Error('stream.push() after EOF');
+                        stream.emit('error', e);
+                    } else if (state.endEmitted && addToFront) {
+                        var e = new Error('stream.unshift() after end event');
+                        stream.emit('error', e);
+                    } else {
+                        var skipAdd;
+                        if (state.decoder && !addToFront && !encoding) {
+                            chunk = state.decoder.write(chunk);
+                            skipAdd = !state.objectMode && chunk.length === 0;
+                        }
+
+                        if (!addToFront) state.reading = false;
+
+                        // Don't add to the buffer if we've decoded to an empty string chunk and
+                        // we're not in object mode
+                        if (!skipAdd) {
+                            // if we want the data now, just emit it.
+                            if (state.flowing && state.length === 0 && !state.sync) {
+                                stream.emit('data', chunk);
+                                stream.read(0);
+                            } else {
+                                // update the buffer info.
+                                state.length += state.objectMode ? 1 : chunk.length;
+                                if (addToFront) state.buffer.unshift(chunk); else state.buffer.push(chunk);
+
+                                if (state.needReadable) emitReadable(stream);
+                            }
+                        }
+
+                        maybeReadMore(stream, state);
+                    }
+                } else if (!addToFront) {
+                    state.reading = false;
+                }
+
+                return needMoreData(state);
+            }
+
+// if it's past the high water mark, we can push in some more.
+// Also, if we have no data yet, we can stand some
+// more bytes.  This is to work around cases where hwm=0,
+// such as the repl.  Also, if the push() triggered a
+// readable event, and the user called read(largeNumber) such that
+// needReadable was set, then we ought to push more, so that another
+// 'readable' event will be triggered.
+            function needMoreData(state) {
+                return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0);
+            }
+
+// backwards compatibility.
+            Readable.prototype.setEncoding = function (enc) {
+                if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder;
+                this._readableState.decoder = new StringDecoder(enc);
+                this._readableState.encoding = enc;
+                return this;
+            };
+
+// Don't raise the hwm > 8MB
+            var MAX_HWM = 0x800000;
+
+            function computeNewHighWaterMark(n) {
+                if (n >= MAX_HWM) {
+                    n = MAX_HWM;
+                } else {
+                    // Get the next highest power of 2
+                    n--;
+                    n |= n >>> 1;
+                    n |= n >>> 2;
+                    n |= n >>> 4;
+                    n |= n >>> 8;
+                    n |= n >>> 16;
+                    n++;
+                }
+                return n;
+            }
+
+            function howMuchToRead(n, state) {
+                if (state.length === 0 && state.ended) return 0;
+
+                if (state.objectMode) return n === 0 ? 0 : 1;
+
+                if (n === null || isNaN(n)) {
+                    // only flow one buffer at a time
+                    if (state.flowing && state.buffer.length) return state.buffer[0].length; else return state.length;
+                }
+
+                if (n <= 0) return 0;
+
+                // If we're asking for more than the target buffer level,
+                // then raise the water mark.  Bump up to the next highest
+                // power of 2, to prevent increasing it excessively in tiny
+                // amounts.
+                if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n);
+
+                // don't have that much.  return null, unless we've ended.
+                if (n > state.length) {
+                    if (!state.ended) {
+                        state.needReadable = true;
+                        return 0;
+                    } else {
+                        return state.length;
+                    }
+                }
+
+                return n;
+            }
+
+// you can override either this method, or the async _read(n) below.
+            Readable.prototype.read = function (n) {
+                debug('read', n);
+                var state = this._readableState;
+                var nOrig = n;
+
+                if (typeof n !== 'number' || n > 0) state.emittedReadable = false;
+
+                // if we're doing read(0) to trigger a readable event, but we
+                // already have a bunch of data in the buffer, then just trigger
+                // the 'readable' event and move on.
+                if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) {
+                    debug('read: emitReadable', state.length, state.ended);
+                    if (state.length === 0 && state.ended) endReadable(this); else emitReadable(this);
+                    return null;
+                }
+
+                n = howMuchToRead(n, state);
+
+                // if we've ended, and we're now clear, then finish it up.
+                if (n === 0 && state.ended) {
+                    if (state.length === 0) endReadable(this);
+                    return null;
+                }
+
+                // All the actual chunk generation logic needs to be
+                // *below* the call to _read.  The reason is that in certain
+                // synthetic stream cases, such as passthrough streams, _read
+                // may be a completely synchronous operation which may change
+                // the state of the read buffer, providing enough data when
+                // before there was *not* enough.
+                //
+                // So, the steps are:
+                // 1. Figure out what the state of things will be after we do
+                // a read from the buffer.
+                //
+                // 2. If that resulting state will trigger a _read, then call _read.
+                // Note that this may be asynchronous, or synchronous.  Yes, it is
+                // deeply ugly to write APIs this way, but that still doesn't mean
+                // that the Readable class should behave improperly, as streams are
+                // designed to be sync/async agnostic.
+                // Take note if the _read call is sync or async (ie, if the read call
+                // has returned yet), so that we know whether or not it's safe to emit
+                // 'readable' etc.
+                //
+                // 3. Actually pull the requested chunks out of the buffer and return.
+
+                // if we need a readable event, then we need to do some reading.
+                var doRead = state.needReadable;
+                debug('need readable', doRead);
+
+                // if we currently have less than the highWaterMark, then also read some
+                if (state.length === 0 || state.length - n < state.highWaterMark) {
+                    doRead = true;
+                    debug('length less than watermark', doRead);
+                }
+
+                // however, if we've ended, then there's no point, and if we're already
+                // reading, then it's unnecessary.
+                if (state.ended || state.reading) {
+                    doRead = false;
+                    debug('reading or ended', doRead);
+                }
+
+                if (doRead) {
+                    debug('do read');
+                    state.reading = true;
+                    state.sync = true;
+                    // if the length is currently zero, then we *need* a readable event.
+                    if (state.length === 0) state.needReadable = true;
+                    // call internal read method
+                    this._read(state.highWaterMark);
+                    state.sync = false;
+                }
+
+                // If _read pushed data synchronously, then `reading` will be false,
+                // and we need to re-evaluate how much data we can return to the user.
+                if (doRead && !state.reading) n = howMuchToRead(nOrig, state);
+
+                var ret;
+                if (n > 0) ret = fromList(n, state); else ret = null;
+
+                if (ret === null) {
+                    state.needReadable = true;
+                    n = 0;
+                }
+
+                state.length -= n;
+
+                // If we have nothing in the buffer, then we want to know
+                // as soon as we *do* get something into the buffer.
+                if (state.length === 0 && !state.ended) state.needReadable = true;
+
+                // If we tried to read() past the EOF, then emit end on the next tick.
+                if (nOrig !== n && state.ended && state.length === 0) endReadable(this);
+
+                if (ret !== null) this.emit('data', ret);
+
+                return ret;
+            };
+
+            function chunkInvalid(state, chunk) {
+                var er = null;
+                if (!Buffer.isBuffer(chunk) && typeof chunk !== 'string' && chunk !== null && chunk !== undefined && !state.objectMode) {
+                    er = new TypeError('Invalid non-string/buffer chunk');
+                }
+                return er;
+            }
+
+            function onEofChunk(stream, state) {
+                if (state.ended) return;
+                if (state.decoder) {
+                    var chunk = state.decoder.end();
+                    if (chunk && chunk.length) {
+                        state.buffer.push(chunk);
+                        state.length += state.objectMode ? 1 : chunk.length;
+                    }
+                }
+                state.ended = true;
+
+                // emit 'readable' now to make sure it gets picked up.
+                emitReadable(stream);
+            }
+
+// Don't emit readable right away in sync mode, because this can trigger
+// another read() call => stack overflow.  This way, it might trigger
+// a nextTick recursion warning, but that's not so bad.
+            function emitReadable(stream) {
+                var state = stream._readableState;
+                state.needReadable = false;
+                if (!state.emittedReadable) {
+                    debug('emitReadable', state.flowing);
+                    state.emittedReadable = true;
+                    if (state.sync) processNextTick(emitReadable_, stream); else emitReadable_(stream);
+                }
+            }
+
+            function emitReadable_(stream) {
+                debug('emit readable');
+                stream.emit('readable');
+                flow(stream);
+            }
+
+// at this point, the user has presumably seen the 'readable' event,
+// and called read() to consume some data.  that may have triggered
+// in turn another _read(n) call, in which case reading = true if
+// it's in progress.
+// However, if we're not ended, or reading, and the length < hwm,
+// then go ahead and try to read some more preemptively.
+            function maybeReadMore(stream, state) {
+                if (!state.readingMore) {
+                    state.readingMore = true;
+                    processNextTick(maybeReadMore_, stream, state);
+                }
+            }
+
+            function maybeReadMore_(stream, state) {
+                var len = state.length;
+                while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) {
+                    debug('maybeReadMore read 0');
+                    stream.read(0);
+                    if (len === state.length)
+                    // didn't get any data, stop spinning.
+                        break; else len = state.length;
+                }
+                state.readingMore = false;
+            }
+
+// abstract method.  to be overridden in specific implementation classes.
+// call cb(er, data) where data is <= n in length.
+// for virtual (non-string, non-buffer) streams, "length" is somewhat
+// arbitrary, and perhaps not very meaningful.
+            Readable.prototype._read = function (n) {
+                this.emit('error', new Error('not implemented'));
+            };
+
+            Readable.prototype.pipe = function (dest, pipeOpts) {
+                var src = this;
+                var state = this._readableState;
+
+                switch (state.pipesCount) {
+                    case 0:
+                        state.pipes = dest;
+                        break;
+                    case 1:
+                        state.pipes = [state.pipes, dest];
+                        break;
+                    default:
+                        state.pipes.push(dest);
+                        break;
+                }
+                state.pipesCount += 1;
+                debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts);
+
+                var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr;
+
+                var endFn = doEnd ? onend : cleanup;
+                if (state.endEmitted) processNextTick(endFn); else src.once('end', endFn);
+
+                dest.on('unpipe', onunpipe);
+
+                function onunpipe(readable) {
+                    debug('onunpipe');
+                    if (readable === src) {
+                        cleanup();
+                    }
+                }
+
+                function onend() {
+                    debug('onend');
+                    dest.end();
+                }
+
+                // when the dest drains, it reduces the awaitDrain counter
+                // on the source.  This would be more elegant with a .once()
+                // handler in flow(), but adding and removing repeatedly is
+                // too slow.
+                var ondrain = pipeOnDrain(src);
+                dest.on('drain', ondrain);
+
+                var cleanedUp = false;
+
+                function cleanup() {
+                    debug('cleanup');
+                    // cleanup event handlers once the pipe is broken
+                    dest.removeListener('close', onclose);
+                    dest.removeListener('finish', onfinish);
+                    dest.removeListener('drain', ondrain);
+                    dest.removeListener('error', onerror);
+                    dest.removeListener('unpipe', onunpipe);
+                    src.removeListener('end', onend);
+                    src.removeListener('end', cleanup);
+                    src.removeListener('data', ondata);
+
+                    cleanedUp = true;
+
+                    // if the reader is waiting for a drain event from this
+                    // specific writer, then it would cause it to never start
+                    // flowing again.
+                    // So, if this is awaiting a drain, then we just call it now.
+                    // If we don't know, then assume that we are waiting for one.
+                    if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain();
+                }
+
+                src.on('data', ondata);
+
+                function ondata(chunk) {
+                    debug('ondata');
+                    var ret = dest.write(chunk);
+                    if (false === ret) {
+                        // If the user unpiped during `dest.write()`, it is possible
+                        // to get stuck in a permanently paused state if that write
+                        // also returned false.
+                        if (state.pipesCount === 1 && state.pipes[0] === dest && src.listenerCount('data') === 1 && !cleanedUp) {
+                            debug('false write response, pause', src._readableState.awaitDrain);
+                            src._readableState.awaitDrain++;
+                        }
+                        src.pause();
+                    }
+                }
+
+                // if the dest has an error, then stop piping into it.
+                // however, don't suppress the throwing behavior for this.
+                function onerror(er) {
+                    debug('onerror', er);
+                    unpipe();
+                    dest.removeListener('error', onerror);
+                    if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er);
+                }
+
+                // This is a brutally ugly hack to make sure that our error handler
+                // is attached before any userland ones.  NEVER DO THIS.
+                if (!dest._events || !dest._events.error) dest.on('error', onerror); else if (isArray(dest._events.error)) dest._events.error.unshift(onerror); else dest._events.error = [onerror, dest._events.error];
+
+                // Both close and finish should trigger unpipe, but only once.
+                function onclose() {
+                    dest.removeListener('finish', onfinish);
+                    unpipe();
+                }
+
+                dest.once('close', onclose);
+
+                function onfinish() {
+                    debug('onfinish');
+                    dest.removeListener('close', onclose);
+                    unpipe();
+                }
+
+                dest.once('finish', onfinish);
+
+                function unpipe() {
+                    debug('unpipe');
+                    src.unpipe(dest);
+                }
+
+                // tell the dest that it's being piped to
+                dest.emit('pipe', src);
+
+                // start the flow if it hasn't been started already.
+                if (!state.flowing) {
+                    debug('pipe resume');
+                    src.resume();
+                }
+
+                return dest;
+            };
+
+            function pipeOnDrain(src) {
+                return function () {
+                    var state = src._readableState;
+                    debug('pipeOnDrain', state.awaitDrain);
+                    if (state.awaitDrain) state.awaitDrain--;
+                    if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) {
+                        state.flowing = true;
+                        flow(src);
+                    }
+                };
+            }
+
+            Readable.prototype.unpipe = function (dest) {
+                var state = this._readableState;
+
+                // if we're not piping anywhere, then do nothing.
+                if (state.pipesCount === 0) return this;
+
+                // just one destination.  most common case.
+                if (state.pipesCount === 1) {
+                    // passed in one, but it's not the right one.
+                    if (dest && dest !== state.pipes) return this;
+
+                    if (!dest) dest = state.pipes;
+
+                    // got a match.
+                    state.pipes = null;
+                    state.pipesCount = 0;
+                    state.flowing = false;
+                    if (dest) dest.emit('unpipe', this);
+                    return this;
+                }
+
+                // slow case. multiple pipe destinations.
+
+                if (!dest) {
+                    // remove all.
+                    var dests = state.pipes;
+                    var len = state.pipesCount;
+                    state.pipes = null;
+                    state.pipesCount = 0;
+                    state.flowing = false;
+
+                    for (var _i = 0; _i < len; _i++) {
+                        dests[_i].emit('unpipe', this);
+                    }
+                    return this;
+                }
+
+                // try to find the right one.
+                var i = indexOf(state.pipes, dest);
+                if (i === -1) return this;
+
+                state.pipes.splice(i, 1);
+                state.pipesCount -= 1;
+                if (state.pipesCount === 1) state.pipes = state.pipes[0];
+
+                dest.emit('unpipe', this);
+
+                return this;
+            };
+
+// set up data events if they are asked for
+// Ensure readable listeners eventually get something
+            Readable.prototype.on = function (ev, fn) {
+                var res = Stream.prototype.on.call(this, ev, fn);
+
+                // If listening to data, and it has not explicitly been paused,
+                // then call resume to start the flow of data on the next tick.
+                if (ev === 'data' && false !== this._readableState.flowing) {
+                    this.resume();
+                }
+
+                if (ev === 'readable' && !this._readableState.endEmitted) {
+                    var state = this._readableState;
+                    if (!state.readableListening) {
+                        state.readableListening = true;
+                        state.emittedReadable = false;
+                        state.needReadable = true;
+                        if (!state.reading) {
+                            processNextTick(nReadingNextTick, this);
+                        } else if (state.length) {
+                            emitReadable(this, state);
+                        }
+                    }
+                }
+
+                return res;
+            };
+            Readable.prototype.addListener = Readable.prototype.on;
+
+            function nReadingNextTick(self) {
+                debug('readable nexttick read 0');
+                self.read(0);
+            }
+
+// pause() and resume() are remnants of the legacy readable stream API
+// If the user uses them, then switch into old mode.
+            Readable.prototype.resume = function () {
+                var state = this._readableState;
+                if (!state.flowing) {
+                    debug('resume');
+                    state.flowing = true;
+                    resume(this, state);
+                }
+                return this;
+            };
+
+            function resume(stream, state) {
+                if (!state.resumeScheduled) {
+                    state.resumeScheduled = true;
+                    processNextTick(resume_, stream, state);
+                }
+            }
+
+            function resume_(stream, state) {
+                if (!state.reading) {
+                    debug('resume read 0');
+                    stream.read(0);
+                }
+
+                state.resumeScheduled = false;
+                stream.emit('resume');
+                flow(stream);
+                if (state.flowing && !state.reading) stream.read(0);
+            }
+
+            Readable.prototype.pause = function () {
+                debug('call pause flowing=%j', this._readableState.flowing);
+                if (false !== this._readableState.flowing) {
+                    debug('pause');
+                    this._readableState.flowing = false;
+                    this.emit('pause');
+                }
+                return this;
+            };
+
+            function flow(stream) {
+                var state = stream._readableState;
+                debug('flow', state.flowing);
+                if (state.flowing) {
+                    do {
+                        var chunk = stream.read();
+                    } while (null !== chunk && state.flowing);
+                }
+            }
+
+// wrap an old-style stream as the async data source.
+// This is *not* part of the readable stream interface.
+// It is an ugly unfortunate mess of history.
+            Readable.prototype.wrap = function (stream) {
+                var state = this._readableState;
+                var paused = false;
+
+                var self = this;
+                stream.on('end', function () {
+                    debug('wrapped end');
+                    if (state.decoder && !state.ended) {
+                        var chunk = state.decoder.end();
+                        if (chunk && chunk.length) self.push(chunk);
+                    }
+
+                    self.push(null);
+                });
+
+                stream.on('data', function (chunk) {
+                    debug('wrapped data');
+                    if (state.decoder) chunk = state.decoder.write(chunk);
+
+                    // don't skip over falsy values in objectMode
+                    if (state.objectMode && (chunk === null || chunk === undefined)) return; else if (!state.objectMode && (!chunk || !chunk.length)) return;
+
+                    var ret = self.push(chunk);
+                    if (!ret) {
+                        paused = true;
+                        stream.pause();
+                    }
+                });
+
+                // proxy all the other methods.
+                // important when wrapping filters and duplexes.
+                for (var i in stream) {
+                    if (this[i] === undefined && typeof stream[i] === 'function') {
+                        this[i] = function (method) {
+                            return function () {
+                                return stream[method].apply(stream, arguments);
+                            };
+                        }(i);
+                    }
+                }
+
+                // proxy certain important events.
+                var events = ['error', 'close', 'destroy', 'pause', 'resume'];
+                forEach(events, function (ev) {
+                    stream.on(ev, self.emit.bind(self, ev));
+                });
+
+                // when we try to consume some more bytes, simply unpause the
+                // underlying stream.
+                self._read = function (n) {
+                    debug('wrapped _read', n);
+                    if (paused) {
+                        paused = false;
+                        stream.resume();
+                    }
+                };
+
+                return self;
+            };
+
+// exposed for testing purposes only.
+            Readable._fromList = fromList;
+
+// Pluck off n bytes from an array of buffers.
+// Length is the combined lengths of all the buffers in the list.
+            function fromList(n, state) {
+                var list = state.buffer;
+                var length = state.length;
+                var stringMode = !!state.decoder;
+                var objectMode = !!state.objectMode;
+                var ret;
+
+                // nothing in the list, definitely empty.
+                if (list.length === 0) return null;
+
+                if (length === 0) ret = null; else if (objectMode) ret = list.shift(); else if (!n || n >= length) {
+                    // read it all, truncate the array.
+                    if (stringMode) ret = list.join(''); else if (list.length === 1) ret = list[0]; else ret = Buffer.concat(list, length);
+                    list.length = 0;
+                } else {
+                    // read just some of it.
+                    if (n < list[0].length) {
+                        // just take a part of the first list item.
+                        // slice is the same for buffers and strings.
+                        var buf = list[0];
+                        ret = buf.slice(0, n);
+                        list[0] = buf.slice(n);
+                    } else if (n === list[0].length) {
+                        // first list is a perfect match
+                        ret = list.shift();
+                    } else {
+                        // complex case.
+                        // we have enough to cover it, but it spans past the first buffer.
+                        if (stringMode) ret = ''; else ret = new Buffer(n);
+
+                        var c = 0;
+                        for (var i = 0, l = list.length; i < l && c < n; i++) {
+                            var buf = list[0];
+                            var cpy = Math.min(n - c, buf.length);
+
+                            if (stringMode) ret += buf.slice(0, cpy); else buf.copy(ret, c, 0, cpy);
+
+                            if (cpy < buf.length) list[0] = buf.slice(cpy); else list.shift();
+
+                            c += cpy;
+                        }
+                    }
+                }
+
+                return ret;
+            }
+
+            function endReadable(stream) {
+                var state = stream._readableState;
+
+                // If we get here before consuming all the bytes, then that is a
+                // bug in node.  Should never happen.
+                if (state.length > 0) throw new Error('endReadable called on non-empty stream');
+
+                if (!state.endEmitted) {
+                    state.ended = true;
+                    processNextTick(endReadableNT, state, stream);
+                }
+            }
+
+            function endReadableNT(state, stream) {
+                // Check that we didn't get one last unshift.
+                if (!state.endEmitted && state.length === 0) {
+                    state.endEmitted = true;
+                    stream.readable = false;
+                    stream.emit('end');
+                }
+            }
+
+            function forEach(xs, f) {
+                for (var i = 0, l = xs.length; i < l; i++) {
+                    f(xs[i], i);
+                }
+            }
+
+            function indexOf(xs, x) {
+                for (var i = 0, l = xs.length; i < l; i++) {
+                    if (xs[i] === x) return i;
+                }
+                return -1;
+            }
+        }).call(this, require('_process'))
+    }, {
+        "./_stream_duplex": 45,
+        "_process": 43,
+        "buffer": 36,
+        "core-util-is": 50,
+        "events": 40,
+        "inherits": 41,
+        "isarray": 51,
+        "process-nextick-args": 52,
+        "string_decoder/": 59,
+        "util": 35
+    }],
+    48: [function (require, module, exports) {
+// a transform stream is a readable/writable stream where you do
+// something with the data.  Sometimes it's called a "filter",
+// but that's not a great name for it, since that implies a thing where
+// some bits pass through, and others are simply ignored.  (That would
+// be a valid example of a transform, of course.)
+//
+// While the output is causally related to the input, it's not a
+// necessarily symmetric or synchronous transformation.  For example,
+// a zlib stream might take multiple plain-text writes(), and then
+// emit a single compressed chunk some time in the future.
+//
+// Here's how this works:
+//
+// The Transform stream has all the aspects of the readable and writable
+// stream classes.  When you write(chunk), that calls _write(chunk,cb)
+// internally, and returns false if there's a lot of pending writes
+// buffered up.  When you call read(), that calls _read(n) until
+// there's enough pending readable data buffered up.
+//
+// In a transform stream, the written data is placed in a buffer.  When
+// _read(n) is called, it transforms the queued up data, calling the
+// buffered _write cb's as it consumes chunks.  If consuming a single
+// written chunk would result in multiple output chunks, then the first
+// outputted bit calls the readcb, and subsequent chunks just go into
+// the read buffer, and will cause it to emit 'readable' if necessary.
+//
+// This way, back-pressure is actually determined by the reading side,
+// since _read has to be called to start processing a new chunk.  However,
+// a pathological inflate type of transform can cause excessive buffering
+// here.  For example, imagine a stream where every byte of input is
+// interpreted as an integer from 0-255, and then results in that many
+// bytes of output.  Writing the 4 bytes {ff,ff,ff,ff} would result in
+// 1kb of data being output.  In this case, you could write a very small
+// amount of input, and end up with a very large amount of output.  In
+// such a pathological inflating mechanism, there'd be no way to tell
+// the system to stop doing the transform.  A single 4MB write could
+// cause the system to run out of memory.
+//
+// However, even in such a pathological case, only a single written chunk
+// would be consumed, and then the rest would wait (un-transformed) until
+// the results of the previous transformed chunk were consumed.
+
+        'use strict';
+
+        module.exports = Transform;
+
+        var Duplex = require('./_stream_duplex');
+
+        /*<replacement>*/
+        var util = require('core-util-is');
+        util.inherits = require('inherits');
+        /*</replacement>*/
+
+        util.inherits(Transform, Duplex);
+
+        function TransformState(stream) {
+            this.afterTransform = function (er, data) {
+                return afterTransform(stream, er, data);
+            };
+
+            this.needTransform = false;
+            this.transforming = false;
+            this.writecb = null;
+            this.writechunk = null;
+            this.writeencoding = null;
+        }
+
+        function afterTransform(stream, er, data) {
+            var ts = stream._transformState;
+            ts.transforming = false;
+
+            var cb = ts.writecb;
+
+            if (!cb) return stream.emit('error', new Error('no writecb in Transform class'));
+
+            ts.writechunk = null;
+            ts.writecb = null;
+
+            if (data !== null && data !== undefined) stream.push(data);
+
+            cb(er);
+
+            var rs = stream._readableState;
+            rs.reading = false;
+            if (rs.needReadable || rs.length < rs.highWaterMark) {
+                stream._read(rs.highWaterMark);
+            }
+        }
+
+        function Transform(options) {
+            if (!(this instanceof Transform)) return new Transform(options);
+
+            Duplex.call(this, options);
+
+            this._transformState = new TransformState(this);
+
+            // when the writable side finishes, then flush out anything remaining.
+            var stream = this;
+
+            // start out asking for a readable event once data is transformed.
+            this._readableState.needReadable = true;
+
+            // we have implemented the _read method, and done the other things
+            // that Readable wants before the first _read call, so unset the
+            // sync guard flag.
+            this._readableState.sync = false;
+
+            if (options) {
+                if (typeof options.transform === 'function') this._transform = options.transform;
+
+                if (typeof options.flush === 'function') this._flush = options.flush;
+            }
+
+            this.once('prefinish', function () {
+                if (typeof this._flush === 'function') this._flush(function (er) {
+                    done(stream, er);
+                }); else done(stream);
+            });
+        }
+
+        Transform.prototype.push = function (chunk, encoding) {
+            this._transformState.needTransform = false;
+            return Duplex.prototype.push.call(this, chunk, encoding);
+        };
+
+// This is the part where you do stuff!
+// override this function in implementation classes.
+// 'chunk' is an input chunk.
+//
+// Call `push(newChunk)` to pass along transformed output
+// to the readable side.  You may call 'push' zero or more times.
+//
+// Call `cb(err)` when you are done with this chunk.  If you pass
+// an error, then that'll put the hurt on the whole operation.  If you
+// never call cb(), then you'll never get another chunk.
+        Transform.prototype._transform = function (chunk, encoding, cb) {
+            throw new Error('not implemented');
+        };
+
+        Transform.prototype._write = function (chunk, encoding, cb) {
+            var ts = this._transformState;
+            ts.writecb = cb;
+            ts.writechunk = chunk;
+            ts.writeencoding = encoding;
+            if (!ts.transforming) {
+                var rs = this._readableState;
+                if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark);
+            }
+        };
+
+// Doesn't matter what the args are here.
+// _transform does all the work.
+// That we got here means that the readable side wants more data.
+        Transform.prototype._read = function (n) {
+            var ts = this._transformState;
+
+            if (ts.writechunk !== null && ts.writecb && !ts.transforming) {
+                ts.transforming = true;
+                this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
+            } else {
+                // mark that we need a transform, so that any data that comes in
+                // will get processed, now that we've asked for it.
+                ts.needTransform = true;
+            }
+        };
+
+        function done(stream, er) {
+            if (er) return stream.emit('error', er);
+
+            // if there's nothing in the write buffer, then that means
+            // that nothing more will ever be provided
+            var ws = stream._writableState;
+            var ts = stream._transformState;
+
+            if (ws.length) throw new Error('calling transform done when ws.length != 0');
+
+            if (ts.transforming) throw new Error('calling transform done when still transforming');
+
+            return stream.push(null);
+        }
+    }, {"./_stream_duplex": 45, "core-util-is": 50, "inherits": 41}],
+    49: [function (require, module, exports) {
+        (function (process) {
+// A bit simpler than readable streams.
+// Implement an async ._write(chunk, encoding, cb), and it'll handle all
+// the drain event emission and buffering.
+
+            'use strict';
+
+            module.exports = Writable;
+
+            /*<replacement>*/
+            var processNextTick = require('process-nextick-args');
+            /*</replacement>*/
+
+            /*<replacement>*/
+            var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : processNextTick;
+            /*</replacement>*/
+
+            /*<replacement>*/
+            var Buffer = require('buffer').Buffer;
+            /*</replacement>*/
+
+            Writable.WritableState = WritableState;
+
+            /*<replacement>*/
+            var util = require('core-util-is');
+            util.inherits = require('inherits');
+            /*</replacement>*/
+
+            /*<replacement>*/
+            var internalUtil = {
+                deprecate: require('util-deprecate')
+            };
+            /*</replacement>*/
+
+            /*<replacement>*/
+            var Stream;
+            (function () {
+                try {
+                    Stream = require('st' + 'ream');
+                } catch (_) {
+                } finally {
+                    if (!Stream) Stream = require('events').EventEmitter;
+                }
+            })();
+            /*</replacement>*/
+
+            var Buffer = require('buffer').Buffer;
+
+            util.inherits(Writable, Stream);
+
+            function nop() {
+            }
+
+            function WriteReq(chunk, encoding, cb) {
+                this.chunk = chunk;
+                this.encoding = encoding;
+                this.callback = cb;
+                this.next = null;
+            }
+
+            var Duplex;
+
+            function WritableState(options, stream) {
+                Duplex = Duplex || require('./_stream_duplex');
+
+                options = options || {};
+
+                // object stream flag to indicate whether or not this stream
+                // contains buffers or objects.
+                this.objectMode = !!options.objectMode;
+
+                if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.writableObjectMode;
+
+                // the point at which write() starts returning false
+                // Note: 0 is a valid value, means that we always return false if
+                // the entire buffer is not flushed immediately on write()
+                var hwm = options.highWaterMark;
+                var defaultHwm = this.objectMode ? 16 : 16 * 1024;
+                this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm;
+
+                // cast to ints.
+                this.highWaterMark = ~~this.highWaterMark;
+
+                this.needDrain = false;
+                // at the start of calling end()
+                this.ending = false;
+                // when end() has been called, and returned
+                this.ended = false;
+                // when 'finish' is emitted
+                this.finished = false;
+
+                // should we decode strings into buffers before passing to _write?
+                // this is here so that some node-core streams can optimize string
+                // handling at a lower level.
+                var noDecode = options.decodeStrings === false;
+                this.decodeStrings = !noDecode;
+
+                // Crypto is kind of old and crusty.  Historically, its default string
+                // encoding is 'binary' so we have to make this configurable.
+                // Everything else in the universe uses 'utf8', though.
+                this.defaultEncoding = options.defaultEncoding || 'utf8';
+
+                // not an actual buffer we keep track of, but a measurement
+                // of how much we're waiting to get pushed to some underlying
+                // socket or file.
+                this.length = 0;
+
+                // a flag to see when we're in the middle of a write.
+                this.writing = false;
+
+                // when true all writes will be buffered until .uncork() call
+                this.corked = 0;
+
+                // a flag to be able to tell if the onwrite cb is called immediately,
+                // or on a later tick.  We set this to true at first, because any
+                // actions that shouldn't happen until "later" should generally also
+                // not happen before the first write call.
+                this.sync = true;
+
+                // a flag to know if we're processing previously buffered items, which
+                // may call the _write() callback in the same tick, so that we don't
+                // end up in an overlapped onwrite situation.
+                this.bufferProcessing = false;
+
+                // the callback that's passed to _write(chunk,cb)
+                this.onwrite = function (er) {
+                    onwrite(stream, er);
+                };
+
+                // the callback that the user supplies to write(chunk,encoding,cb)
+                this.writecb = null;
+
+                // the amount that is being written when _write is called.
+                this.writelen = 0;
+
+                this.bufferedRequest = null;
+                this.lastBufferedRequest = null;
+
+                // number of pending user-supplied write callbacks
+                // this must be 0 before 'finish' can be emitted
+                this.pendingcb = 0;
+
+                // emit prefinish if the only thing we're waiting for is _write cbs
+                // This is relevant for synchronous Transform streams
+                this.prefinished = false;
+
+                // True if the error was already emitted and should not be thrown again
+                this.errorEmitted = false;
+
+                // count buffered requests
+                this.bufferedRequestCount = 0;
+
+                // create the two objects needed to store the corked requests
+                // they are not a linked list, as no new elements are inserted in there
+                this.corkedRequestsFree = new CorkedRequest(this);
+                this.corkedRequestsFree.next = new CorkedRequest(this);
+            }
+
+            WritableState.prototype.getBuffer = function writableStateGetBuffer() {
+                var current = this.bufferedRequest;
+                var out = [];
+                while (current) {
+                    out.push(current);
+                    current = current.next;
+                }
+                return out;
+            };
+
+            (function () {
+                try {
+                    Object.defineProperty(WritableState.prototype, 'buffer', {
+                        get: internalUtil.deprecate(function () {
+                            return this.getBuffer();
+                        }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.')
+                    });
+                } catch (_) {
+                }
+            })();
+
+            var Duplex;
+
+            function Writable(options) {
+                Duplex = Duplex || require('./_stream_duplex');
+
+                // Writable ctor is applied to Duplexes, though they're not
+                // instanceof Writable, they're instanceof Readable.
+                if (!(this instanceof Writable) && !(this instanceof Duplex)) return new Writable(options);
+
+                this._writableState = new WritableState(options, this);
+
+                // legacy.
+                this.writable = true;
+
+                if (options) {
+                    if (typeof options.write === 'function') this._write = options.write;
+
+                    if (typeof options.writev === 'function') this._writev = options.writev;
+                }
+
+                Stream.call(this);
+            }
+
+// Otherwise people can pipe Writable streams, which is just wrong.
+            Writable.prototype.pipe = function () {
+                this.emit('error', new Error('Cannot pipe. Not readable.'));
+            };
+
+            function writeAfterEnd(stream, cb) {
+                var er = new Error('write after end');
+                // TODO: defer error events consistently everywhere, not just the cb
+                stream.emit('error', er);
+                processNextTick(cb, er);
+            }
+
+// If we get something that is not a buffer, string, null, or undefined,
+// and we're not in objectMode, then that's an error.
+// Otherwise stream chunks are all considered to be of length=1, and the
+// watermarks determine how many objects to keep in the buffer, rather than
+// how many bytes or characters.
+            function validChunk(stream, state, chunk, cb) {
+                var valid = true;
+
+                if (!Buffer.isBuffer(chunk) && typeof chunk !== 'string' && chunk !== null && chunk !== undefined && !state.objectMode) {
+                    var er = new TypeError('Invalid non-string/buffer chunk');
+                    stream.emit('error', er);
+                    processNextTick(cb, er);
+                    valid = false;
+                }
+                return valid;
+            }
+
+            Writable.prototype.write = function (chunk, encoding, cb) {
+                var state = this._writableState;
+                var ret = false;
+
+                if (typeof encoding === 'function') {
+                    cb = encoding;
+                    encoding = null;
+                }
+
+                if (Buffer.isBuffer(chunk)) encoding = 'buffer'; else if (!encoding) encoding = state.defaultEncoding;
+
+                if (typeof cb !== 'function') cb = nop;
+
+                if (state.ended) writeAfterEnd(this, cb); else if (validChunk(this, state, chunk, cb)) {
+                    state.pendingcb++;
+                    ret = writeOrBuffer(this, state, chunk, encoding, cb);
+                }
+
+                return ret;
+            };
+
+            Writable.prototype.cork = function () {
+                var state = this._writableState;
+
+                state.corked++;
+            };
+
+            Writable.prototype.uncork = function () {
+                var state = this._writableState;
+
+                if (state.corked) {
+                    state.corked--;
+
+                    if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state);
+                }
+            };
+
+            Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
+                // node::ParseEncoding() requires lower case.
+                if (typeof encoding === 'string') encoding = encoding.toLowerCase();
+                if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding);
+                this._writableState.defaultEncoding = encoding;
+            };
+
+            function decodeChunk(state, chunk, encoding) {
+                if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') {
+                    chunk = new Buffer(chunk, encoding);
+                }
+                return chunk;
+            }
+
+// if we're already writing something, then just put this
+// in the queue, and wait our turn.  Otherwise, call _write
+// If we return false, then we need a drain event, so set that flag.
+            function writeOrBuffer(stream, state, chunk, encoding, cb) {
+                chunk = decodeChunk(state, chunk, encoding);
+
+                if (Buffer.isBuffer(chunk)) encoding = 'buffer';
+                var len = state.objectMode ? 1 : chunk.length;
+
+                state.length += len;
+
+                var ret = state.length < state.highWaterMark;
+                // we must ensure that previous needDrain will not be reset to false.
+                if (!ret) state.needDrain = true;
+
+                if (state.writing || state.corked) {
+                    var last = state.lastBufferedRequest;
+                    state.lastBufferedRequest = new WriteReq(chunk, encoding, cb);
+                    if (last) {
+                        last.next = state.lastBufferedRequest;
+                    } else {
+                        state.bufferedRequest = state.lastBufferedRequest;
+                    }
+                    state.bufferedRequestCount += 1;
+                } else {
+                    doWrite(stream, state, false, len, chunk, encoding, cb);
+                }
+
+                return ret;
+            }
+
+            function doWrite(stream, state, writev, len, chunk, encoding, cb) {
+                state.writelen = len;
+                state.writecb = cb;
+                state.writing = true;
+                state.sync = true;
+                if (writev) stream._writev(chunk, state.onwrite); else stream._write(chunk, encoding, state.onwrite);
+                state.sync = false;
+            }
+
+            function onwriteError(stream, state, sync, er, cb) {
+                --state.pendingcb;
+                if (sync) processNextTick(cb, er); else cb(er);
+
+                stream._writableState.errorEmitted = true;
+                stream.emit('error', er);
+            }
+
+            function onwriteStateUpdate(state) {
+                state.writing = false;
+                state.writecb = null;
+                state.length -= state.writelen;
+                state.writelen = 0;
+            }
+
+            function onwrite(stream, er) {
+                var state = stream._writableState;
+                var sync = state.sync;
+                var cb = state.writecb;
+
+                onwriteStateUpdate(state);
+
+                if (er) onwriteError(stream, state, sync, er, cb); else {
+                    // Check if we're actually ready to finish, but don't emit yet
+                    var finished = needFinish(state);
+
+                    if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) {
+                        clearBuffer(stream, state);
+                    }
+
+                    if (sync) {
+                        /*<replacement>*/
+                        asyncWrite(afterWrite, stream, state, finished, cb);
+                        /*</replacement>*/
+                    } else {
+                        afterWrite(stream, state, finished, cb);
+                    }
+                }
+            }
+
+            function afterWrite(stream, state, finished, cb) {
+                if (!finished) onwriteDrain(stream, state);
+                state.pendingcb--;
+                cb();
+                finishMaybe(stream, state);
+            }
+
+// Must force callback to be called on nextTick, so that we don't
+// emit 'drain' before the write() consumer gets the 'false' return
+// value, and has a chance to attach a 'drain' listener.
+            function onwriteDrain(stream, state) {
+                if (state.length === 0 && state.needDrain) {
+                    state.needDrain = false;
+                    stream.emit('drain');
+                }
+            }
+
+// if there's something in the buffer waiting, then process it
+            function clearBuffer(stream, state) {
+                state.bufferProcessing = true;
+                var entry = state.bufferedRequest;
+
+                if (stream._writev && entry && entry.next) {
+                    // Fast case, write everything using _writev()
+                    var l = state.bufferedRequestCount;
+                    var buffer = new Array(l);
+                    var holder = state.corkedRequestsFree;
+                    holder.entry = entry;
+
+                    var count = 0;
+                    while (entry) {
+                        buffer[count] = entry;
+                        entry = entry.next;
+                        count += 1;
+                    }
+
+                    doWrite(stream, state, true, state.length, buffer, '', holder.finish);
+
+                    // doWrite is always async, defer these to save a bit of time
+                    // as the hot path ends with doWrite
+                    state.pendingcb++;
+                    state.lastBufferedRequest = null;
+                    state.corkedRequestsFree = holder.next;
+                    holder.next = null;
+                } else {
+                    // Slow case, write chunks one-by-one
+                    while (entry) {
+                        var chunk = entry.chunk;
+                        var encoding = entry.encoding;
+                        var cb = entry.callback;
+                        var len = state.objectMode ? 1 : chunk.length;
+
+                        doWrite(stream, state, false, len, chunk, encoding, cb);
+                        entry = entry.next;
+                        // if we didn't call the onwrite immediately, then
+                        // it means that we need to wait until it does.
+                        // also, that means that the chunk and cb are currently
+                        // being processed, so move the buffer counter past them.
+                        if (state.writing) {
+                            break;
+                        }
+                    }
+
+                    if (entry === null) state.lastBufferedRequest = null;
+                }
+
+                state.bufferedRequestCount = 0;
+                state.bufferedRequest = entry;
+                state.bufferProcessing = false;
+            }
+
+            Writable.prototype._write = function (chunk, encoding, cb) {
+                cb(new Error('not implemented'));
+            };
+
+            Writable.prototype._writev = null;
+
+            Writable.prototype.end = function (chunk, encoding, cb) {
+                var state = this._writableState;
+
+                if (typeof chunk === 'function') {
+                    cb = chunk;
+                    chunk = null;
+                    encoding = null;
+                } else if (typeof encoding === 'function') {
+                    cb = encoding;
+                    encoding = null;
+                }
+
+                if (chunk !== null && chunk !== undefined) this.write(chunk, encoding);
+
+                // .end() fully uncorks
+                if (state.corked) {
+                    state.corked = 1;
+                    this.uncork();
+                }
+
+                // ignore unnecessary end() calls.
+                if (!state.ending && !state.finished) endWritable(this, state, cb);
+            };
+
+            function needFinish(state) {
+                return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing;
+            }
+
+            function prefinish(stream, state) {
+                if (!state.prefinished) {
+                    state.prefinished = true;
+                    stream.emit('prefinish');
+                }
+            }
+
+            function finishMaybe(stream, state) {
+                var need = needFinish(state);
+                if (need) {
+                    if (state.pendingcb === 0) {
+                        prefinish(stream, state);
+                        state.finished = true;
+                        stream.emit('finish');
+                    } else {
+                        prefinish(stream, state);
+                    }
+                }
+                return need;
+            }
+
+            function endWritable(stream, state, cb) {
+                state.ending = true;
+                finishMaybe(stream, state);
+                if (cb) {
+                    if (state.finished) processNextTick(cb); else stream.once('finish', cb);
+                }
+                state.ended = true;
+                stream.writable = false;
+            }
+
+// It seems a linked list but it is not
+// there will be only 2 of these for each stream
+            function CorkedRequest(state) {
+                var _this = this;
+
+                this.next = null;
+                this.entry = null;
+
+                this.finish = function (err) {
+                    var entry = _this.entry;
+                    _this.entry = null;
+                    while (entry) {
+                        var cb = entry.callback;
+                        state.pendingcb--;
+                        cb(err);
+                        entry = entry.next;
+                    }
+                    if (state.corkedRequestsFree) {
+                        state.corkedRequestsFree.next = _this;
+                    } else {
+                        state.corkedRequestsFree = _this;
+                    }
+                };
+            }
+        }).call(this, require('_process'))
+    }, {
+        "./_stream_duplex": 45,
+        "_process": 43,
+        "buffer": 36,
+        "core-util-is": 50,
+        "events": 40,
+        "inherits": 41,
+        "process-nextick-args": 52,
+        "util-deprecate": 53
+    }],
+    50: [function (require, module, exports) {
+        (function (Buffer) {
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// NOTE: These type checking functions intentionally don't use `instanceof`
+// because it is fragile and can be easily faked with `Object.create()`.
+
+            function isArray(arg) {
+                if (Array.isArray) {
+                    return Array.isArray(arg);
+                }
+                return objectToString(arg) === '[object Array]';
+            }
+
+            exports.isArray = isArray;
+
+            function isBoolean(arg) {
+                return typeof arg === 'boolean';
+            }
+
+            exports.isBoolean = isBoolean;
+
+            function isNull(arg) {
+                return arg === null;
+            }
+
+            exports.isNull = isNull;
+
+            function isNullOrUndefined(arg) {
+                return arg == null;
+            }
+
+            exports.isNullOrUndefined = isNullOrUndefined;
+
+            function isNumber(arg) {
+                return typeof arg === 'number';
+            }
+
+            exports.isNumber = isNumber;
+
+            function isString(arg) {
+                return typeof arg === 'string';
+            }
+
+            exports.isString = isString;
+
+            function isSymbol(arg) {
+                return typeof arg === 'symbol';
+            }
+
+            exports.isSymbol = isSymbol;
+
+            function isUndefined(arg) {
+                return arg === void 0;
+            }
+
+            exports.isUndefined = isUndefined;
+
+            function isRegExp(re) {
+                return objectToString(re) === '[object RegExp]';
+            }
+
+            exports.isRegExp = isRegExp;
+
+            function isObject(arg) {
+                return typeof arg === 'object' && arg !== null;
+            }
+
+            exports.isObject = isObject;
+
+            function isDate(d) {
+                return objectToString(d) === '[object Date]';
+            }
+
+            exports.isDate = isDate;
+
+            function isError(e) {
+                return (objectToString(e) === '[object Error]' || e instanceof Error);
+            }
+
+            exports.isError = isError;
+
+            function isFunction(arg) {
+                return typeof arg === 'function';
+            }
+
+            exports.isFunction = isFunction;
+
+            function isPrimitive(arg) {
+                return arg === null ||
+                    typeof arg === 'boolean' ||
+                    typeof arg === 'number' ||
+                    typeof arg === 'string' ||
+                    typeof arg === 'symbol' ||  // ES6 symbol
+                    typeof arg === 'undefined';
+            }
+
+            exports.isPrimitive = isPrimitive;
+
+            exports.isBuffer = Buffer.isBuffer;
+
+            function objectToString(o) {
+                return Object.prototype.toString.call(o);
+            }
+
+        }).call(this, {"isBuffer": require("../../../../insert-module-globals/node_modules/is-buffer/index.js")})
+    }, {"../../../../insert-module-globals/node_modules/is-buffer/index.js": 42}],
+    51: [function (require, module, exports) {
+        arguments[4][39][0].apply(exports, arguments)
+    }, {"dup": 39}],
+    52: [function (require, module, exports) {
+        (function (process) {
+            'use strict';
+
+            if (!process.version ||
+                process.version.indexOf('v0.') === 0 ||
+                process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) {
+                module.exports = nextTick;
+            } else {
+                module.exports = process.nextTick;
+            }
+
+            function nextTick(fn) {
+                var args = new Array(arguments.length - 1);
+                var i = 0;
+                while (i < args.length) {
+                    args[i++] = arguments[i];
+                }
+                process.nextTick(function afterTick() {
+                    fn.apply(null, args);
+                });
+            }
+
+        }).call(this, require('_process'))
+    }, {"_process": 43}],
+    53: [function (require, module, exports) {
+        (function (global) {
+
+            /**
+             * Module exports.
+             */
+
+            module.exports = deprecate;
+
+            /**
+             * Mark that a method should not be used.
+             * Returns a modified function which warns once by default.
+             *
+             * If `localStorage.noDeprecation = true` is set, then it is a no-op.
+             *
+             * If `localStorage.throwDeprecation = true` is set, then deprecated functions
+             * will throw an Error when invoked.
+             *
+             * If `localStorage.traceDeprecation = true` is set, then deprecated functions
+             * will invoke `console.trace()` instead of `console.error()`.
+             *
+             * @param {Function} fn - the function to deprecate
+             * @param {String} msg - the string to print to the console when `fn` is invoked
+             * @returns {Function} a new "deprecated" version of `fn`
+             * @api public
+             */
+
+            function deprecate(fn, msg) {
+                if (config('noDeprecation')) {
+                    return fn;
+                }
+
+                var warned = false;
+
+                function deprecated() {
+                    if (!warned) {
+                        if (config('throwDeprecation')) {
+                            throw new Error(msg);
+                        } else if (config('traceDeprecation')) {
+                            console.trace(msg);
+                        } else {
+                            console.warn(msg);
+                        }
+                        warned = true;
+                    }
+                    return fn.apply(this, arguments);
+                }
+
+                return deprecated;
+            }
+
+            /**
+             * Checks `localStorage` for boolean values for the given `name`.
+             *
+             * @param {String} name
+             * @returns {Boolean}
+             * @api private
+             */
+
+            function config(name) {
+                // accessing global.localStorage can trigger a DOMException in sandboxed iframes
+                try {
+                    if (!global.localStorage) return false;
+                } catch (_) {
+                    return false;
+                }
+                var val = global.localStorage[name];
+                if (null == val) return false;
+                return String(val).toLowerCase() === 'true';
+            }
+
+        }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+    }, {}],
+    54: [function (require, module, exports) {
+        module.exports = require("./lib/_stream_passthrough.js")
+
+    }, {"./lib/_stream_passthrough.js": 46}],
+    55: [function (require, module, exports) {
+        var Stream = (function () {
+            try {
+                return require('st' + 'ream'); // hack to fix a circular dependency issue when used with browserify
+            } catch (_) {
+            }
+        }());
+        exports = module.exports = require('./lib/_stream_readable.js');
+        exports.Stream = Stream || exports;
+        exports.Readable = exports;
+        exports.Writable = require('./lib/_stream_writable.js');
+        exports.Duplex = require('./lib/_stream_duplex.js');
+        exports.Transform = require('./lib/_stream_transform.js');
+        exports.PassThrough = require('./lib/_stream_passthrough.js');
+
+    }, {
+        "./lib/_stream_duplex.js": 45,
+        "./lib/_stream_passthrough.js": 46,
+        "./lib/_stream_readable.js": 47,
+        "./lib/_stream_transform.js": 48,
+        "./lib/_stream_writable.js": 49
+    }],
+    56: [function (require, module, exports) {
+        module.exports = require("./lib/_stream_transform.js")
+
+    }, {"./lib/_stream_transform.js": 48}],
+    57: [function (require, module, exports) {
+        module.exports = require("./lib/_stream_writable.js")
+
+    }, {"./lib/_stream_writable.js": 49}],
+    58: [function (require, module, exports) {
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+        module.exports = Stream;
+
+        var EE = require('events').EventEmitter;
+        var inherits = require('inherits');
+
+        inherits(Stream, EE);
+        Stream.Readable = require('readable-stream/readable.js');
+        Stream.Writable = require('readable-stream/writable.js');
+        Stream.Duplex = require('readable-stream/duplex.js');
+        Stream.Transform = require('readable-stream/transform.js');
+        Stream.PassThrough = require('readable-stream/passthrough.js');
+
+// Backwards-compat with node 0.4.x
+        Stream.Stream = Stream;
+
+
+// old-style streams.  Note that the pipe method (the only relevant
+// part of this class) is overridden in the Readable class.
+
+        function Stream() {
+            EE.call(this);
+        }
+
+        Stream.prototype.pipe = function (dest, options) {
+            var source = this;
+
+            function ondata(chunk) {
+                if (dest.writable) {
+                    if (false === dest.write(chunk) && source.pause) {
+                        source.pause();
+                    }
+                }
+            }
+
+            source.on('data', ondata);
+
+            function ondrain() {
+                if (source.readable && source.resume) {
+                    source.resume();
+                }
+            }
+
+            dest.on('drain', ondrain);
+
+            // If the 'end' option is not supplied, dest.end() will be called when
+            // source gets the 'end' or 'close' events.  Only dest.end() once.
+            if (!dest._isStdio && (!options || options.end !== false)) {
+                source.on('end', onend);
+                source.on('close', onclose);
+            }
+
+            var didOnEnd = false;
+
+            function onend() {
+                if (didOnEnd) return;
+                didOnEnd = true;
+
+                dest.end();
+            }
+
+
+            function onclose() {
+                if (didOnEnd) return;
+                didOnEnd = true;
+
+                if (typeof dest.destroy === 'function') dest.destroy();
+            }
+
+            // don't leave dangling pipes when there are errors.
+            function onerror(er) {
+                cleanup();
+                if (EE.listenerCount(this, 'error') === 0) {
+                    throw er; // Unhandled stream error in pipe.
+                }
+            }
+
+            source.on('error', onerror);
+            dest.on('error', onerror);
+
+            // remove all the event listeners that were added.
+            function cleanup() {
+                source.removeListener('data', ondata);
+                dest.removeListener('drain', ondrain);
+
+                source.removeListener('end', onend);
+                source.removeListener('close', onclose);
+
+                source.removeListener('error', onerror);
+                dest.removeListener('error', onerror);
+
+                source.removeListener('end', cleanup);
+                source.removeListener('close', cleanup);
+
+                dest.removeListener('close', cleanup);
+            }
+
+            source.on('end', cleanup);
+            source.on('close', cleanup);
+
+            dest.on('close', cleanup);
+
+            dest.emit('pipe', source);
+
+            // Allow for unix-like usage: A.pipe(B).pipe(C)
+            return dest;
+        };
+
+    }, {
+        "events": 40,
+        "inherits": 41,
+        "readable-stream/duplex.js": 44,
+        "readable-stream/passthrough.js": 54,
+        "readable-stream/readable.js": 55,
+        "readable-stream/transform.js": 56,
+        "readable-stream/writable.js": 57
+    }],
+    59: [function (require, module, exports) {
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+        var Buffer = require('buffer').Buffer;
+
+        var isBufferEncoding = Buffer.isEncoding
+            || function (encoding) {
+                switch (encoding && encoding.toLowerCase()) {
+                    case 'hex':
+                    case 'utf8':
+                    case 'utf-8':
+                    case 'ascii':
+                    case 'binary':
+                    case 'base64':
+                    case 'ucs2':
+                    case 'ucs-2':
+                    case 'utf16le':
+                    case 'utf-16le':
+                    case 'raw':
+                        return true;
+                    default:
+                        return false;
+                }
+            }
+
+
+        function assertEncoding(encoding) {
+            if (encoding && !isBufferEncoding(encoding)) {
+                throw new Error('Unknown encoding: ' + encoding);
+            }
+        }
+
+// StringDecoder provides an interface for efficiently splitting a series of
+// buffers into a series of JS strings without breaking apart multi-byte
+// characters. CESU-8 is handled as part of the UTF-8 encoding.
+//
+// @TODO Handling all encodings inside a single object makes it very difficult
+// to reason about this code, so it should be split up in the future.
+// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code
+// points as used by CESU-8.
+        var StringDecoder = exports.StringDecoder = function (encoding) {
+            this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, '');
+            assertEncoding(encoding);
+            switch (this.encoding) {
+                case 'utf8':
+                    // CESU-8 represents each of Surrogate Pair by 3-bytes
+                    this.surrogateSize = 3;
+                    break;
+                case 'ucs2':
+                case 'utf16le':
+                    // UTF-16 represents each of Surrogate Pair by 2-bytes
+                    this.surrogateSize = 2;
+                    this.detectIncompleteChar = utf16DetectIncompleteChar;
+                    break;
+                case 'base64':
+                    // Base-64 stores 3 bytes in 4 chars, and pads the remainder.
+                    this.surrogateSize = 3;
+                    this.detectIncompleteChar = base64DetectIncompleteChar;
+                    break;
+                default:
+                    this.write = passThroughWrite;
+                    return;
+            }
+
+            // Enough space to store all bytes of a single character. UTF-8 needs 4
+            // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate).
+            this.charBuffer = new Buffer(6);
+            // Number of bytes received for the current incomplete multi-byte character.
+            this.charReceived = 0;
+            // Number of bytes expected for the current incomplete multi-byte character.
+            this.charLength = 0;
+        };
+
+
+// write decodes the given buffer and returns it as JS string that is
+// guaranteed to not contain any partial multi-byte characters. Any partial
+// character found at the end of the buffer is buffered up, and will be
+// returned when calling write again with the remaining bytes.
+//
+// Note: Converting a Buffer containing an orphan surrogate to a String
+// currently works, but converting a String to a Buffer (via `new Buffer`, or
+// Buffer#write) will replace incomplete surrogates with the unicode
+// replacement character. See https://codereview.chromium.org/121173009/ .
+        StringDecoder.prototype.write = function (buffer) {
+            var charStr = '';
+            // if our last write ended with an incomplete multibyte character
+            while (this.charLength) {
+                // determine how many remaining bytes this buffer has to offer for this char
+                var available = (buffer.length >= this.charLength - this.charReceived) ?
+                    this.charLength - this.charReceived :
+                    buffer.length;
+
+                // add the new bytes to the char buffer
+                buffer.copy(this.charBuffer, this.charReceived, 0, available);
+                this.charReceived += available;
+
+                if (this.charReceived < this.charLength) {
+                    // still not enough chars in this buffer? wait for more ...
+                    return '';
+                }
+
+                // remove bytes belonging to the current character from the buffer
+                buffer = buffer.slice(available, buffer.length);
+
+                // get the character that was split
+                charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding);
+
+                // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
+                var charCode = charStr.charCodeAt(charStr.length - 1);
+                if (charCode >= 0xD800 && charCode <= 0xDBFF) {
+                    this.charLength += this.surrogateSize;
+                    charStr = '';
+                    continue;
+                }
+                this.charReceived = this.charLength = 0;
+
+                // if there are no more bytes in this buffer, just emit our char
+                if (buffer.length === 0) {
+                    return charStr;
+                }
+                break;
+            }
+
+            // determine and set charLength / charReceived
+            this.detectIncompleteChar(buffer);
+
+            var end = buffer.length;
+            if (this.charLength) {
+                // buffer the incomplete character bytes we got
+                buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end);
+                end -= this.charReceived;
+            }
+
+            charStr += buffer.toString(this.encoding, 0, end);
+
+            var end = charStr.length - 1;
+            var charCode = charStr.charCodeAt(end);
+            // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
+            if (charCode >= 0xD800 && charCode <= 0xDBFF) {
+                var size = this.surrogateSize;
+                this.charLength += size;
+                this.charReceived += size;
+                this.charBuffer.copy(this.charBuffer, size, 0, size);
+                buffer.copy(this.charBuffer, 0, 0, size);
+                return charStr.substring(0, end);
+            }
+
+            // or just emit the charStr
+            return charStr;
+        };
+
+// detectIncompleteChar determines if there is an incomplete UTF-8 character at
+// the end of the given buffer. If so, it sets this.charLength to the byte
+// length that character, and sets this.charReceived to the number of bytes
+// that are available for this character.
+        StringDecoder.prototype.detectIncompleteChar = function (buffer) {
+            // determine how many bytes we have to check at the end of this buffer
+            var i = (buffer.length >= 3) ? 3 : buffer.length;
+
+            // Figure out if one of the last i bytes of our buffer announces an
+            // incomplete char.
+            for (; i > 0; i--) {
+                var c = buffer[buffer.length - i];
+
+                // See http://en.wikipedia.org/wiki/UTF-8#Description
+
+                // 110XXXXX
+                if (i == 1 && c >> 5 == 0x06) {
+                    this.charLength = 2;
+                    break;
+                }
+
+                // 1110XXXX
+                if (i <= 2 && c >> 4 == 0x0E) {
+                    this.charLength = 3;
+                    break;
+                }
+
+                // 11110XXX
+                if (i <= 3 && c >> 3 == 0x1E) {
+                    this.charLength = 4;
+                    break;
+                }
+            }
+            this.charReceived = i;
+        };
+
+        StringDecoder.prototype.end = function (buffer) {
+            var res = '';
+            if (buffer && buffer.length)
+                res = this.write(buffer);
+
+            if (this.charReceived) {
+                var cr = this.charReceived;
+                var buf = this.charBuffer;
+                var enc = this.encoding;
+                res += buf.slice(0, cr).toString(enc);
+            }
+
+            return res;
+        };
+
+        function passThroughWrite(buffer) {
+            return buffer.toString(this.encoding);
+        }
+
+        function utf16DetectIncompleteChar(buffer) {
+            this.charReceived = buffer.length % 2;
+            this.charLength = this.charReceived ? 2 : 0;
+        }
+
+        function base64DetectIncompleteChar(buffer) {
+            this.charReceived = buffer.length % 3;
+            this.charLength = this.charReceived ? 3 : 0;
+        }
+
+    }, {"buffer": 36}],
+    60: [function (require, module, exports) {
+        module.exports = function isBuffer(arg) {
+            return arg && typeof arg === 'object'
+                && typeof arg.copy === 'function'
+                && typeof arg.fill === 'function'
+                && typeof arg.readUInt8 === 'function';
+        }
+    }, {}],
+    61: [function (require, module, exports) {
+        (function (process, global) {
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+            var formatRegExp = /%[sdj%]/g;
+            exports.format = function (f) {
+                if (!isString(f)) {
+                    var objects = [];
+                    for (var i = 0; i < arguments.length; i++) {
+                        objects.push(inspect(arguments[i]));
+                    }
+                    return objects.join(' ');
+                }
+
+                var i = 1;
+                var args = arguments;
+                var len = args.length;
+                var str = String(f).replace(formatRegExp, function (x) {
+                    if (x === '%%') return '%';
+                    if (i >= len) return x;
+                    switch (x) {
+                        case '%s':
+                            return String(args[i++]);
+                        case '%d':
+                            return Number(args[i++]);
+                        case '%j':
+                            try {
+                                return JSON.stringify(args[i++]);
+                            } catch (_) {
+                                return '[Circular]';
+                            }
+                        default:
+                            return x;
+                    }
+                });
+                for (var x = args[i]; i < len; x = args[++i]) {
+                    if (isNull(x) || !isObject(x)) {
+                        str += ' ' + x;
+                    } else {
+                        str += ' ' + inspect(x);
+                    }
+                }
+                return str;
+            };
+
+
+// Mark that a method should not be used.
+// Returns a modified function which warns once by default.
+// If --no-deprecation is set, then it is a no-op.
+            exports.deprecate = function (fn, msg) {
+                // Allow for deprecating things in the process of starting up.
+                if (isUndefined(global.process)) {
+                    return function () {
+                        return exports.deprecate(fn, msg).apply(this, arguments);
+                    };
+                }
+
+                if (process.noDeprecation === true) {
+                    return fn;
+                }
+
+                var warned = false;
+
+                function deprecated() {
+                    if (!warned) {
+                        if (process.throwDeprecation) {
+                            throw new Error(msg);
+                        } else if (process.traceDeprecation) {
+                            console.trace(msg);
+                        } else {
+                            console.error(msg);
+                        }
+                        warned = true;
+                    }
+                    return fn.apply(this, arguments);
+                }
+
+                return deprecated;
+            };
+
+
+            var debugs = {};
+            var debugEnviron;
+            exports.debuglog = function (set) {
+                if (isUndefined(debugEnviron))
+                    debugEnviron = process.env.NODE_DEBUG || '';
+                set = set.toUpperCase();
+                if (!debugs[set]) {
+                    if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
+                        var pid = process.pid;
+                        debugs[set] = function () {
+                            var msg = exports.format.apply(exports, arguments);
+                            console.error('%s %d: %s', set, pid, msg);
+                        };
+                    } else {
+                        debugs[set] = function () {
+                        };
+                    }
+                }
+                return debugs[set];
+            };
+
+
+            /**
+             * Echos the value of a value. Trys to print the value out
+             * in the best way possible given the different types.
+             *
+             * @param {Object} obj The object to print out.
+             * @param {Object} opts Optional options object that alters the output.
+             */
+
+            /* legacy: obj, showHidden, depth, colors*/
+            function inspect(obj, opts) {
+                // default options
+                var ctx = {
+                    seen: [],
+                    stylize: stylizeNoColor
+                };
+                // legacy...
+                if (arguments.length >= 3) ctx.depth = arguments[2];
+                if (arguments.length >= 4) ctx.colors = arguments[3];
+                if (isBoolean(opts)) {
+                    // legacy...
+                    ctx.showHidden = opts;
+                } else if (opts) {
+                    // got an "options" object
+                    exports._extend(ctx, opts);
+                }
+                // set default options
+                if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
+                if (isUndefined(ctx.depth)) ctx.depth = 2;
+                if (isUndefined(ctx.colors)) ctx.colors = false;
+                if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
+                if (ctx.colors) ctx.stylize = stylizeWithColor;
+                return formatValue(ctx, obj, ctx.depth);
+            }
+
+            exports.inspect = inspect;
+
+
+// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
+            inspect.colors = {
+                'bold': [1, 22],
+                'italic': [3, 23],
+                'underline': [4, 24],
+                'inverse': [7, 27],
+                'white': [37, 39],
+                'grey': [90, 39],
+                'black': [30, 39],
+                'blue': [34, 39],
+                'cyan': [36, 39],
+                'green': [32, 39],
+                'magenta': [35, 39],
+                'red': [31, 39],
+                'yellow': [33, 39]
+            };
+
+// Don't use 'blue' not visible on cmd.exe
+            inspect.styles = {
+                'special': 'cyan',
+                'number': 'yellow',
+                'boolean': 'yellow',
+                'undefined': 'grey',
+                'null': 'bold',
+                'string': 'green',
+                'date': 'magenta',
+                // "name": intentionally not styling
+                'regexp': 'red'
+            };
+
+
+            function stylizeWithColor(str, styleType) {
+                var style = inspect.styles[styleType];
+
+                if (style) {
+                    return '\u001b[' + inspect.colors[style][0] + 'm' + str +
+                        '\u001b[' + inspect.colors[style][1] + 'm';
+                } else {
+                    return str;
+                }
+            }
+
+
+            function stylizeNoColor(str, styleType) {
+                return str;
+            }
+
+
+            function arrayToHash(array) {
+                var hash = {};
+
+                array.forEach(function (val, idx) {
+                    hash[val] = true;
+                });
+
+                return hash;
+            }
+
+
+            function formatValue(ctx, value, recurseTimes) {
+                // Provide a hook for user-specified inspect functions.
+                // Check that value is an object with an inspect function on it
+                if (ctx.customInspect &&
+                    value &&
+                    isFunction(value.inspect) &&
+                    // Filter out the util module, it's inspect function is special
+                    value.inspect !== exports.inspect &&
+                    // Also filter out any prototype objects using the circular check.
+                    !(value.constructor && value.constructor.prototype === value)) {
+                    var ret = value.inspect(recurseTimes, ctx);
+                    if (!isString(ret)) {
+                        ret = formatValue(ctx, ret, recurseTimes);
+                    }
+                    return ret;
+                }
+
+                // Primitive types cannot have properties
+                var primitive = formatPrimitive(ctx, value);
+                if (primitive) {
+                    return primitive;
+                }
+
+                // Look up the keys of the object.
+                var keys = Object.keys(value);
+                var visibleKeys = arrayToHash(keys);
+
+                if (ctx.showHidden) {
+                    keys = Object.getOwnPropertyNames(value);
+                }
+
+                // IE doesn't make error fields non-enumerable
+                // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
+                if (isError(value)
+                    && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
+                    return formatError(value);
+                }
+
+                // Some type of object without properties can be shortcutted.
+                if (keys.length === 0) {
+                    if (isFunction(value)) {
+                        var name = value.name ? ': ' + value.name : '';
+                        return ctx.stylize('[Function' + name + ']', 'special');
+                    }
+                    if (isRegExp(value)) {
+                        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
+                    }
+                    if (isDate(value)) {
+                        return ctx.stylize(Date.prototype.toString.call(value), 'date');
+                    }
+                    if (isError(value)) {
+                        return formatError(value);
+                    }
+                }
+
+                var base = '', array = false, braces = ['{', '}'];
+
+                // Make Array say that they are Array
+                if (isArray(value)) {
+                    array = true;
+                    braces = ['[', ']'];
+                }
+
+                // Make functions say that they are functions
+                if (isFunction(value)) {
+                    var n = value.name ? ': ' + value.name : '';
+                    base = ' [Function' + n + ']';
+                }
+
+                // Make RegExps say that they are RegExps
+                if (isRegExp(value)) {
+                    base = ' ' + RegExp.prototype.toString.call(value);
+                }
+
+                // Make dates with properties first say the date
+                if (isDate(value)) {
+                    base = ' ' + Date.prototype.toUTCString.call(value);
+                }
+
+                // Make error with message first say the error
+                if (isError(value)) {
+                    base = ' ' + formatError(value);
+                }
+
+                if (keys.length === 0 && (!array || value.length == 0)) {
+                    return braces[0] + base + braces[1];
+                }
+
+                if (recurseTimes < 0) {
+                    if (isRegExp(value)) {
+                        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
+                    } else {
+                        return ctx.stylize('[Object]', 'special');
+                    }
+                }
+
+                ctx.seen.push(value);
+
+                var output;
+                if (array) {
+                    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
+                } else {
+                    output = keys.map(function (key) {
+                        return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
+                    });
+                }
+
+                ctx.seen.pop();
+
+                return reduceToSingleString(output, base, braces);
+            }
+
+
+            function formatPrimitive(ctx, value) {
+                if (isUndefined(value))
+                    return ctx.stylize('undefined', 'undefined');
+                if (isString(value)) {
+                    var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
+                        .replace(/'/g, "\\'")
+                        .replace(/\\"/g, '"') + '\'';
+                    return ctx.stylize(simple, 'string');
+                }
+                if (isNumber(value))
+                    return ctx.stylize('' + value, 'number');
+                if (isBoolean(value))
+                    return ctx.stylize('' + value, 'boolean');
+                // For some reason typeof null is "object", so special case here.
+                if (isNull(value))
+                    return ctx.stylize('null', 'null');
+            }
+
+
+            function formatError(value) {
+                return '[' + Error.prototype.toString.call(value) + ']';
+            }
+
+
+            function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
+                var output = [];
+                for (var i = 0, l = value.length; i < l; ++i) {
+                    if (hasOwnProperty(value, String(i))) {
+                        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
+                            String(i), true));
+                    } else {
+                        output.push('');
+                    }
+                }
+                keys.forEach(function (key) {
+                    if (!key.match(/^\d+$/)) {
+                        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
+                            key, true));
+                    }
+                });
+                return output;
+            }
+
+
+            function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
+                var name, str, desc;
+                desc = Object.getOwnPropertyDescriptor(value, key) || {value: value[key]};
+                if (desc.get) {
+                    if (desc.set) {
+                        str = ctx.stylize('[Getter/Setter]', 'special');
+                    } else {
+                        str = ctx.stylize('[Getter]', 'special');
+                    }
+                } else {
+                    if (desc.set) {
+                        str = ctx.stylize('[Setter]', 'special');
+                    }
+                }
+                if (!hasOwnProperty(visibleKeys, key)) {
+                    name = '[' + key + ']';
+                }
+                if (!str) {
+                    if (ctx.seen.indexOf(desc.value) < 0) {
+                        if (isNull(recurseTimes)) {
+                            str = formatValue(ctx, desc.value, null);
+                        } else {
+                            str = formatValue(ctx, desc.value, recurseTimes - 1);
+                        }
+                        if (str.indexOf('\n') > -1) {
+                            if (array) {
+                                str = str.split('\n').map(function (line) {
+                                    return '  ' + line;
+                                }).join('\n').substr(2);
+                            } else {
+                                str = '\n' + str.split('\n').map(function (line) {
+                                    return '   ' + line;
+                                }).join('\n');
+                            }
+                        }
+                    } else {
+                        str = ctx.stylize('[Circular]', 'special');
+                    }
+                }
+                if (isUndefined(name)) {
+                    if (array && key.match(/^\d+$/)) {
+                        return str;
+                    }
+                    name = JSON.stringify('' + key);
+                    if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
+                        name = name.substr(1, name.length - 2);
+                        name = ctx.stylize(name, 'name');
+                    } else {
+                        name = name.replace(/'/g, "\\'")
+                            .replace(/\\"/g, '"')
+                            .replace(/(^"|"$)/g, "'");
+                        name = ctx.stylize(name, 'string');
+                    }
+                }
+
+                return name + ': ' + str;
+            }
+
+
+            function reduceToSingleString(output, base, braces) {
+                var numLinesEst = 0;
+                var length = output.reduce(function (prev, cur) {
+                    numLinesEst++;
+                    if (cur.indexOf('\n') >= 0) numLinesEst++;
+                    return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
+                }, 0);
+
+                if (length > 60) {
+                    return braces[0] +
+                        (base === '' ? '' : base + '\n ') +
+                        ' ' +
+                        output.join(',\n  ') +
+                        ' ' +
+                        braces[1];
+                }
+
+                return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
+            }
+
+
+// NOTE: These type checking functions intentionally don't use `instanceof`
+// because it is fragile and can be easily faked with `Object.create()`.
+            function isArray(ar) {
+                return Array.isArray(ar);
+            }
+
+            exports.isArray = isArray;
+
+            function isBoolean(arg) {
+                return typeof arg === 'boolean';
+            }
+
+            exports.isBoolean = isBoolean;
+
+            function isNull(arg) {
+                return arg === null;
+            }
+
+            exports.isNull = isNull;
+
+            function isNullOrUndefined(arg) {
+                return arg == null;
+            }
+
+            exports.isNullOrUndefined = isNullOrUndefined;
+
+            function isNumber(arg) {
+                return typeof arg === 'number';
+            }
+
+            exports.isNumber = isNumber;
+
+            function isString(arg) {
+                return typeof arg === 'string';
+            }
+
+            exports.isString = isString;
+
+            function isSymbol(arg) {
+                return typeof arg === 'symbol';
+            }
+
+            exports.isSymbol = isSymbol;
+
+            function isUndefined(arg) {
+                return arg === void 0;
+            }
+
+            exports.isUndefined = isUndefined;
+
+            function isRegExp(re) {
+                return isObject(re) && objectToString(re) === '[object RegExp]';
+            }
+
+            exports.isRegExp = isRegExp;
+
+            function isObject(arg) {
+                return typeof arg === 'object' && arg !== null;
+            }
+
+            exports.isObject = isObject;
+
+            function isDate(d) {
+                return isObject(d) && objectToString(d) === '[object Date]';
+            }
+
+            exports.isDate = isDate;
+
+            function isError(e) {
+                return isObject(e) &&
+                    (objectToString(e) === '[object Error]' || e instanceof Error);
+            }
+
+            exports.isError = isError;
+
+            function isFunction(arg) {
+                return typeof arg === 'function';
+            }
+
+            exports.isFunction = isFunction;
+
+            function isPrimitive(arg) {
+                return arg === null ||
+                    typeof arg === 'boolean' ||
+                    typeof arg === 'number' ||
+                    typeof arg === 'string' ||
+                    typeof arg === 'symbol' ||  // ES6 symbol
+                    typeof arg === 'undefined';
+            }
+
+            exports.isPrimitive = isPrimitive;
+
+            exports.isBuffer = require('./support/isBuffer');
+
+            function objectToString(o) {
+                return Object.prototype.toString.call(o);
+            }
+
+
+            function pad(n) {
+                return n < 10 ? '0' + n.toString(10) : n.toString(10);
+            }
+
+
+            var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
+                'Oct', 'Nov', 'Dec'];
+
+// 26 Feb 16:19:34
+            function timestamp() {
+                var d = new Date();
+                var time = [pad(d.getHours()),
+                    pad(d.getMinutes()),
+                    pad(d.getSeconds())].join(':');
+                return [d.getDate(), months[d.getMonth()], time].join(' ');
+            }
+
+
+// log is just a thin wrapper to console.log that prepends a timestamp
+            exports.log = function () {
+                console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
+            };
+
+
+            /**
+             * Inherit the prototype methods from one constructor into another.
+             *
+             * The Function.prototype.inherits from lang.js rewritten as a standalone
+             * function (not on Function.prototype). NOTE: If this file is to be loaded
+             * during bootstrapping this function needs to be rewritten using some native
+             * functions as prototype setup using normal JavaScript does not work as
+             * expected during bootstrapping (see mirror.js in r114903).
+             *
+             * @param {function} ctor Constructor function which needs to inherit the
+             *     prototype.
+             * @param {function} superCtor Constructor function to inherit prototype from.
+             */
+            exports.inherits = require('inherits');
+
+            exports._extend = function (origin, add) {
+                // Don't do anything if add isn't an object
+                if (!add || !isObject(add)) return origin;
+
+                var keys = Object.keys(add);
+                var i = keys.length;
+                while (i--) {
+                    origin[keys[i]] = add[keys[i]];
+                }
+                return origin;
+            };
+
+            function hasOwnProperty(obj, prop) {
+                return Object.prototype.hasOwnProperty.call(obj, prop);
+            }
+
+        }).call(this, require('_process'), typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+    }, {"./support/isBuffer": 60, "_process": 43, "inherits": 41}]
+}, {}, [1]);
+
+module.exports = window.h2m;

+ 1725 - 0
apps/static/vendor/h2m/markdown.js

@@ -0,0 +1,1725 @@
+// Released under MIT license
+// Copyright (c) 2009-2010 Dominic Baggott
+// Copyright (c) 2009-2010 Ash Berlin
+// Copyright (c) 2011 Christoph Dorn <[email protected]> (http://www.christophdorn.com)
+
+/*jshint browser:true, devel:true */
+
+(function( expose ) {
+
+/**
+ *  class Markdown
+ *
+ *  Markdown processing in Javascript done right. We have very particular views
+ *  on what constitutes 'right' which include:
+ *
+ *  - produces well-formed HTML (this means that em and strong nesting is
+ *    important)
+ *
+ *  - has an intermediate representation to allow processing of parsed data (We
+ *    in fact have two, both as [JsonML]: a markdown tree and an HTML tree).
+ *
+ *  - is easily extensible to add new dialects without having to rewrite the
+ *    entire parsing mechanics
+ *
+ *  - has a good test suite
+ *
+ *  This implementation fulfills all of these (except that the test suite could
+ *  do with expanding to automatically run all the fixtures from other Markdown
+ *  implementations.)
+ *
+ *  ##### Intermediate Representation
+ *
+ *  *TODO* Talk about this :) Its JsonML, but document the node names we use.
+ *
+ *  [JsonML]: http://jsonml.org/ "JSON Markup Language"
+ **/
+var Markdown = expose.Markdown = function(dialect) {
+  switch (typeof dialect) {
+    case "undefined":
+      this.dialect = Markdown.dialects.Gruber;
+      break;
+    case "object":
+      this.dialect = dialect;
+      break;
+    default:
+      if ( dialect in Markdown.dialects ) {
+        this.dialect = Markdown.dialects[dialect];
+      }
+      else {
+        throw new Error("Unknown Markdown dialect '" + String(dialect) + "'");
+      }
+      break;
+  }
+  this.em_state = [];
+  this.strong_state = [];
+  this.debug_indent = "";
+};
+
+/**
+ *  parse( markdown, [dialect] ) -> JsonML
+ *  - markdown (String): markdown string to parse
+ *  - dialect (String | Dialect): the dialect to use, defaults to gruber
+ *
+ *  Parse `markdown` and return a markdown document as a Markdown.JsonML tree.
+ **/
+expose.parse = function( source, dialect ) {
+  // dialect will default if undefined
+  var md = new Markdown( dialect );
+  return md.toTree( source );
+};
+
+/**
+ *  toHTML( markdown, [dialect]  ) -> String
+ *  toHTML( md_tree ) -> String
+ *  - markdown (String): markdown string to parse
+ *  - md_tree (Markdown.JsonML): parsed markdown tree
+ *
+ *  Take markdown (either as a string or as a JsonML tree) and run it through
+ *  [[toHTMLTree]] then turn it into a well-formated HTML fragment.
+ **/
+expose.toHTML = function toHTML( source , dialect , options ) {
+  var input = expose.toHTMLTree( source , dialect , options );
+
+  return expose.renderJsonML( input );
+};
+
+/**
+ *  toHTMLTree( markdown, [dialect] ) -> JsonML
+ *  toHTMLTree( md_tree ) -> JsonML
+ *  - markdown (String): markdown string to parse
+ *  - dialect (String | Dialect): the dialect to use, defaults to gruber
+ *  - md_tree (Markdown.JsonML): parsed markdown tree
+ *
+ *  Turn markdown into HTML, represented as a JsonML tree. If a string is given
+ *  to this function, it is first parsed into a markdown tree by calling
+ *  [[parse]].
+ **/
+expose.toHTMLTree = function toHTMLTree( input, dialect , options ) {
+  // convert string input to an MD tree
+  if ( typeof input ==="string" ) input = this.parse( input, dialect );
+
+  // Now convert the MD tree to an HTML tree
+
+  // remove references from the tree
+  var attrs = extract_attr( input ),
+      refs = {};
+
+  if ( attrs && attrs.references ) {
+    refs = attrs.references;
+  }
+
+  var html = convert_tree_to_html( input, refs , options );
+  merge_text_nodes( html );
+  return html;
+};
+
+// For Spidermonkey based engines
+function mk_block_toSource() {
+  return "Markdown.mk_block( " +
+          uneval(this.toString()) +
+          ", " +
+          uneval(this.trailing) +
+          ", " +
+          uneval(this.lineNumber) +
+          " )";
+}
+
+// node
+function mk_block_inspect() {
+  var util = require("util");
+  return "Markdown.mk_block( " +
+          util.inspect(this.toString()) +
+          ", " +
+          util.inspect(this.trailing) +
+          ", " +
+          util.inspect(this.lineNumber) +
+          " )";
+
+}
+
+var mk_block = Markdown.mk_block = function(block, trail, line) {
+  // Be helpful for default case in tests.
+  if ( arguments.length == 1 ) trail = "\n\n";
+
+  var s = new String(block);
+  s.trailing = trail;
+  // To make it clear its not just a string
+  s.inspect = mk_block_inspect;
+  s.toSource = mk_block_toSource;
+
+  if ( line != undefined )
+    s.lineNumber = line;
+
+  return s;
+};
+
+function count_lines( str ) {
+  var n = 0, i = -1;
+  while ( ( i = str.indexOf("\n", i + 1) ) !== -1 ) n++;
+  return n;
+}
+
+// Internal - split source into rough blocks
+Markdown.prototype.split_blocks = function splitBlocks( input, startLine ) {
+  input = input.replace(/(\r\n|\n|\r)/g, "\n");
+  // [\s\S] matches _anything_ (newline or space)
+  // [^] is equivalent but doesn't work in IEs.
+  var re = /([\s\S]+?)($|\n#|\n(?:\s*\n|$)+)/g,
+      blocks = [],
+      m;
+
+  var line_no = 1;
+
+  if ( ( m = /^(\s*\n)/.exec(input) ) != null ) {
+    // skip (but count) leading blank lines
+    line_no += count_lines( m[0] );
+    re.lastIndex = m[0].length;
+  }
+
+  while ( ( m = re.exec(input) ) !== null ) {
+    if (m[2] == "\n#") {
+      m[2] = "\n";
+      re.lastIndex--;
+    }
+    blocks.push( mk_block( m[1], m[2], line_no ) );
+    line_no += count_lines( m[0] );
+  }
+
+  return blocks;
+};
+
+/**
+ *  Markdown#processBlock( block, next ) -> undefined | [ JsonML, ... ]
+ *  - block (String): the block to process
+ *  - next (Array): the following blocks
+ *
+ * Process `block` and return an array of JsonML nodes representing `block`.
+ *
+ * It does this by asking each block level function in the dialect to process
+ * the block until one can. Succesful handling is indicated by returning an
+ * array (with zero or more JsonML nodes), failure by a false value.
+ *
+ * Blocks handlers are responsible for calling [[Markdown#processInline]]
+ * themselves as appropriate.
+ *
+ * If the blocks were split incorrectly or adjacent blocks need collapsing you
+ * can adjust `next` in place using shift/splice etc.
+ *
+ * If any of this default behaviour is not right for the dialect, you can
+ * define a `__call__` method on the dialect that will get invoked to handle
+ * the block processing.
+ */
+Markdown.prototype.processBlock = function processBlock( block, next ) {
+  var cbs = this.dialect.block,
+      ord = cbs.__order__;
+
+  if ( "__call__" in cbs ) {
+    return cbs.__call__.call(this, block, next);
+  }
+
+  for ( var i = 0; i < ord.length; i++ ) {
+    //D:this.debug( "Testing", ord[i] );
+    var res = cbs[ ord[i] ].call( this, block, next );
+    if ( res ) {
+      //D:this.debug("  matched");
+      if ( !isArray(res) || ( res.length > 0 && !( isArray(res[0]) ) ) )
+        this.debug(ord[i], "didn't return a proper array");
+      //D:this.debug( "" );
+      return res;
+    }
+  }
+
+  // Uhoh! no match! Should we throw an error?
+  return [];
+};
+
+Markdown.prototype.processInline = function processInline( block ) {
+  return this.dialect.inline.__call__.call( this, String( block ) );
+};
+
+/**
+ *  Markdown#toTree( source ) -> JsonML
+ *  - source (String): markdown source to parse
+ *
+ *  Parse `source` into a JsonML tree representing the markdown document.
+ **/
+// custom_tree means set this.tree to `custom_tree` and restore old value on return
+Markdown.prototype.toTree = function toTree( source, custom_root ) {
+  var blocks = source instanceof Array ? source : this.split_blocks( source );
+
+  // Make tree a member variable so its easier to mess with in extensions
+  var old_tree = this.tree;
+  try {
+    this.tree = custom_root || this.tree || [ "markdown" ];
+
+    blocks:
+    while ( blocks.length ) {
+      var b = this.processBlock( blocks.shift(), blocks );
+
+      // Reference blocks and the like won't return any content
+      if ( !b.length ) continue blocks;
+
+      this.tree.push.apply( this.tree, b );
+    }
+    return this.tree;
+  }
+  finally {
+    if ( custom_root ) {
+      this.tree = old_tree;
+    }
+  }
+};
+
+// Noop by default
+Markdown.prototype.debug = function () {
+  var args = Array.prototype.slice.call( arguments);
+  args.unshift(this.debug_indent);
+  if ( typeof print !== "undefined" )
+      print.apply( print, args );
+  if ( typeof console !== "undefined" && typeof console.log !== "undefined" )
+      console.log.apply( null, args );
+}
+
+Markdown.prototype.loop_re_over_block = function( re, block, cb ) {
+  // Dont use /g regexps with this
+  var m,
+      b = block.valueOf();
+
+  while ( b.length && (m = re.exec(b) ) != null ) {
+    b = b.substr( m[0].length );
+    cb.call(this, m);
+  }
+  return b;
+};
+
+/**
+ * Markdown.dialects
+ *
+ * Namespace of built-in dialects.
+ **/
+Markdown.dialects = {};
+
+/**
+ * Markdown.dialects.Gruber
+ *
+ * The default dialect that follows the rules set out by John Gruber's
+ * markdown.pl as closely as possible. Well actually we follow the behaviour of
+ * that script which in some places is not exactly what the syntax web page
+ * says.
+ **/
+Markdown.dialects.Gruber = {
+  block: {
+    atxHeader: function atxHeader( block, next ) {
+      var m = block.match( /^(#{1,6})\s*(.*?)\s*#*\s*(?:\n|$)/ );
+
+      if ( !m ) return undefined;
+
+      var header = [ "header", { level: m[ 1 ].length } ];
+      Array.prototype.push.apply(header, this.processInline(m[ 2 ]));
+
+      if ( m[0].length < block.length )
+        next.unshift( mk_block( block.substr( m[0].length ), block.trailing, block.lineNumber + 2 ) );
+
+      return [ header ];
+    },
+
+    setextHeader: function setextHeader( block, next ) {
+      var m = block.match( /^(.*)\n([-=])\2\2+(?:\n|$)/ );
+
+      if ( !m ) return undefined;
+
+      var level = ( m[ 2 ] === "=" ) ? 1 : 2;
+      var header = [ "header", { level : level }, m[ 1 ] ];
+
+      if ( m[0].length < block.length )
+        next.unshift( mk_block( block.substr( m[0].length ), block.trailing, block.lineNumber + 2 ) );
+
+      return [ header ];
+    },
+
+    code: function code( block, next ) {
+      // |    Foo
+      // |bar
+      // should be a code block followed by a paragraph. Fun
+      //
+      // There might also be adjacent code block to merge.
+
+      var ret = [],
+          re = /^(?: {0,3}\t| {4})(.*)\n?/,
+          lines;
+
+      // 4 spaces + content
+      if ( !block.match( re ) ) return undefined;
+
+      block_search:
+      do {
+        // Now pull out the rest of the lines
+        var b = this.loop_re_over_block(
+                  re, block.valueOf(), function( m ) { ret.push( m[1] ); } );
+
+        if ( b.length ) {
+          // Case alluded to in first comment. push it back on as a new block
+          next.unshift( mk_block(b, block.trailing) );
+          break block_search;
+        }
+        else if ( next.length ) {
+          // Check the next block - it might be code too
+          if ( !next[0].match( re ) ) break block_search;
+
+          // Pull how how many blanks lines follow - minus two to account for .join
+          ret.push ( block.trailing.replace(/[^\n]/g, "").substring(2) );
+
+          block = next.shift();
+        }
+        else {
+          break block_search;
+        }
+      } while ( true );
+
+      return [ [ "code_block", ret.join("\n") ] ];
+    },
+
+    horizRule: function horizRule( block, next ) {
+      // this needs to find any hr in the block to handle abutting blocks
+      var m = block.match( /^(?:([\s\S]*?)\n)?[ \t]*([-_*])(?:[ \t]*\2){2,}[ \t]*(?:\n([\s\S]*))?$/ );
+
+      if ( !m ) {
+        return undefined;
+      }
+
+      var jsonml = [ [ "hr" ] ];
+
+      // if there's a leading abutting block, process it
+      if ( m[ 1 ] ) {
+        jsonml.unshift.apply( jsonml, this.processBlock( m[ 1 ], [] ) );
+      }
+
+      // if there's a trailing abutting block, stick it into next
+      if ( m[ 3 ] ) {
+        next.unshift( mk_block( m[ 3 ] ) );
+      }
+
+      return jsonml;
+    },
+
+    // There are two types of lists. Tight and loose. Tight lists have no whitespace
+    // between the items (and result in text just in the <li>) and loose lists,
+    // which have an empty line between list items, resulting in (one or more)
+    // paragraphs inside the <li>.
+    //
+    // There are all sorts weird edge cases about the original markdown.pl's
+    // handling of lists:
+    //
+    // * Nested lists are supposed to be indented by four chars per level. But
+    //   if they aren't, you can get a nested list by indenting by less than
+    //   four so long as the indent doesn't match an indent of an existing list
+    //   item in the 'nest stack'.
+    //
+    // * The type of the list (bullet or number) is controlled just by the
+    //    first item at the indent. Subsequent changes are ignored unless they
+    //    are for nested lists
+    //
+    lists: (function( ) {
+      // Use a closure to hide a few variables.
+      var any_list = "[*+-]|\\d+\\.",
+          bullet_list = /[*+-]/,
+          number_list = /\d+\./,
+          // Capture leading indent as it matters for determining nested lists.
+          is_list_re = new RegExp( "^( {0,3})(" + any_list + ")[ \t]+" ),
+          indent_re = "(?: {0,3}\\t| {4})";
+
+      // TODO: Cache this regexp for certain depths.
+      // Create a regexp suitable for matching an li for a given stack depth
+      function regex_for_depth( depth ) {
+
+        return new RegExp(
+          // m[1] = indent, m[2] = list_type
+          "(?:^(" + indent_re + "{0," + depth + "} {0,3})(" + any_list + ")\\s+)|" +
+          // m[3] = cont
+          "(^" + indent_re + "{0," + (depth-1) + "}[ ]{0,4})"
+        );
+      }
+      function expand_tab( input ) {
+        return input.replace( / {0,3}\t/g, "    " );
+      }
+
+      // Add inline content `inline` to `li`. inline comes from processInline
+      // so is an array of content
+      function add(li, loose, inline, nl) {
+        if ( loose ) {
+          li.push( [ "para" ].concat(inline) );
+          return;
+        }
+        // Hmmm, should this be any block level element or just paras?
+        var add_to = li[li.length -1] instanceof Array && li[li.length - 1][0] == "para"
+                   ? li[li.length -1]
+                   : li;
+
+        // If there is already some content in this list, add the new line in
+        if ( nl && li.length > 1 ) inline.unshift(nl);
+
+        for ( var i = 0; i < inline.length; i++ ) {
+          var what = inline[i],
+              is_str = typeof what == "string";
+          if ( is_str && add_to.length > 1 && typeof add_to[add_to.length-1] == "string" ) {
+            add_to[ add_to.length-1 ] += what;
+          }
+          else {
+            add_to.push( what );
+          }
+        }
+      }
+
+      // contained means have an indent greater than the current one. On
+      // *every* line in the block
+      function get_contained_blocks( depth, blocks ) {
+
+        var re = new RegExp( "^(" + indent_re + "{" + depth + "}.*?\\n?)*$" ),
+            replace = new RegExp("^" + indent_re + "{" + depth + "}", "gm"),
+            ret = [];
+
+        while ( blocks.length > 0 ) {
+          if ( re.exec( blocks[0] ) ) {
+            var b = blocks.shift(),
+                // Now remove that indent
+                x = b.replace( replace, "");
+
+            ret.push( mk_block( x, b.trailing, b.lineNumber ) );
+          }
+          else {
+            break;
+          }
+        }
+        return ret;
+      }
+
+      // passed to stack.forEach to turn list items up the stack into paras
+      function paragraphify(s, i, stack) {
+        var list = s.list;
+        var last_li = list[list.length-1];
+
+        if ( last_li[1] instanceof Array && last_li[1][0] == "para" ) {
+          return;
+        }
+        if ( i + 1 == stack.length ) {
+          // Last stack frame
+          // Keep the same array, but replace the contents
+          last_li.push( ["para"].concat( last_li.splice(1, last_li.length - 1) ) );
+        }
+        else {
+          var sublist = last_li.pop();
+          last_li.push( ["para"].concat( last_li.splice(1, last_li.length - 1) ), sublist );
+        }
+      }
+
+      // The matcher function
+      return function( block, next ) {
+        var m = block.match( is_list_re );
+        if ( !m ) return undefined;
+
+        function make_list( m ) {
+          var list = bullet_list.exec( m[2] )
+                   ? ["bulletlist"]
+                   : ["numberlist"];
+
+          stack.push( { list: list, indent: m[1] } );
+          return list;
+        }
+
+
+        var stack = [], // Stack of lists for nesting.
+            list = make_list( m ),
+            last_li,
+            loose = false,
+            ret = [ stack[0].list ],
+            i;
+
+        // Loop to search over block looking for inner block elements and loose lists
+        loose_search:
+        while ( true ) {
+          // Split into lines preserving new lines at end of line
+          var lines = block.split( /(?=\n)/ );
+
+          // We have to grab all lines for a li and call processInline on them
+          // once as there are some inline things that can span lines.
+          var li_accumulate = "";
+
+          // Loop over the lines in this block looking for tight lists.
+          tight_search:
+          for ( var line_no = 0; line_no < lines.length; line_no++ ) {
+            var nl = "",
+                l = lines[line_no].replace(/^\n/, function(n) { nl = n; return ""; });
+
+            // TODO: really should cache this
+            var line_re = regex_for_depth( stack.length );
+
+            m = l.match( line_re );
+            //print( "line:", uneval(l), "\nline match:", uneval(m) );
+
+            // We have a list item
+            if ( m[1] !== undefined ) {
+              // Process the previous list item, if any
+              if ( li_accumulate.length ) {
+                add( last_li, loose, this.processInline( li_accumulate ), nl );
+                // Loose mode will have been dealt with. Reset it
+                loose = false;
+                li_accumulate = "";
+              }
+
+              m[1] = expand_tab( m[1] );
+              var wanted_depth = Math.floor(m[1].length/4)+1;
+              //print( "want:", wanted_depth, "stack:", stack.length);
+              if ( wanted_depth > stack.length ) {
+                // Deep enough for a nested list outright
+                //print ( "new nested list" );
+                list = make_list( m );
+                last_li.push( list );
+                last_li = list[1] = [ "listitem" ];
+              }
+              else {
+                // We aren't deep enough to be strictly a new level. This is
+                // where Md.pl goes nuts. If the indent matches a level in the
+                // stack, put it there, else put it one deeper then the
+                // wanted_depth deserves.
+                var found = false;
+                for ( i = 0; i < stack.length; i++ ) {
+                  if ( stack[ i ].indent != m[1] ) continue;
+                  list = stack[ i ].list;
+                  stack.splice( i+1, stack.length - (i+1) );
+                  found = true;
+                  break;
+                }
+
+                if (!found) {
+                  //print("not found. l:", uneval(l));
+                  wanted_depth++;
+                  if ( wanted_depth <= stack.length ) {
+                    stack.splice(wanted_depth, stack.length - wanted_depth);
+                    //print("Desired depth now", wanted_depth, "stack:", stack.length);
+                    list = stack[wanted_depth-1].list;
+                    //print("list:", uneval(list) );
+                  }
+                  else {
+                    //print ("made new stack for messy indent");
+                    list = make_list(m);
+                    last_li.push(list);
+                  }
+                }
+
+                //print( uneval(list), "last", list === stack[stack.length-1].list );
+                last_li = [ "listitem" ];
+                list.push(last_li);
+              } // end depth of shenegains
+              nl = "";
+            }
+
+            // Add content
+            if ( l.length > m[0].length ) {
+              li_accumulate += nl + l.substr( m[0].length );
+            }
+          } // tight_search
+
+          if ( li_accumulate.length ) {
+            add( last_li, loose, this.processInline( li_accumulate ), nl );
+            // Loose mode will have been dealt with. Reset it
+            loose = false;
+            li_accumulate = "";
+          }
+
+          // Look at the next block - we might have a loose list. Or an extra
+          // paragraph for the current li
+          var contained = get_contained_blocks( stack.length, next );
+
+          // Deal with code blocks or properly nested lists
+          if ( contained.length > 0 ) {
+            // Make sure all listitems up the stack are paragraphs
+            forEach( stack, paragraphify, this);
+
+            last_li.push.apply( last_li, this.toTree( contained, [] ) );
+          }
+
+          var next_block = next[0] && next[0].valueOf() || "";
+
+          if ( next_block.match(is_list_re) || next_block.match( /^ / ) ) {
+            block = next.shift();
+
+            // Check for an HR following a list: features/lists/hr_abutting
+            var hr = this.dialect.block.horizRule( block, next );
+
+            if ( hr ) {
+              ret.push.apply(ret, hr);
+              break;
+            }
+
+            // Make sure all listitems up the stack are paragraphs
+            forEach( stack, paragraphify, this);
+
+            loose = true;
+            continue loose_search;
+          }
+          break;
+        } // loose_search
+
+        return ret;
+      };
+    })(),
+
+    blockquote: function blockquote( block, next ) {
+      if ( !block.match( /^>/m ) )
+        return undefined;
+
+      var jsonml = [];
+
+      // separate out the leading abutting block, if any. I.e. in this case:
+      //
+      //  a
+      //  > b
+      //
+      if ( block[ 0 ] != ">" ) {
+        var lines = block.split( /\n/ ),
+            prev = [],
+            line_no = block.lineNumber;
+
+        // keep shifting lines until you find a crotchet
+        while ( lines.length && lines[ 0 ][ 0 ] != ">" ) {
+            prev.push( lines.shift() );
+            line_no++;
+        }
+
+        var abutting = mk_block( prev.join( "\n" ), "\n", block.lineNumber );
+        jsonml.push.apply( jsonml, this.processBlock( abutting, [] ) );
+        // reassemble new block of just block quotes!
+        block = mk_block( lines.join( "\n" ), block.trailing, line_no );
+      }
+
+
+      // if the next block is also a blockquote merge it in
+      while ( next.length && next[ 0 ][ 0 ] == ">" ) {
+        var b = next.shift();
+        block = mk_block( block + block.trailing + b, b.trailing, block.lineNumber );
+      }
+
+      // Strip off the leading "> " and re-process as a block.
+      var input = block.replace( /^> ?/gm, "" ),
+          old_tree = this.tree,
+          processedBlock = this.toTree( input, [ "blockquote" ] ),
+          attr = extract_attr( processedBlock );
+
+      // If any link references were found get rid of them
+      if ( attr && attr.references ) {
+        delete attr.references;
+        // And then remove the attribute object if it's empty
+        if ( isEmpty( attr ) ) {
+          processedBlock.splice( 1, 1 );
+        }
+      }
+
+      jsonml.push( processedBlock );
+      return jsonml;
+    },
+
+    referenceDefn: function referenceDefn( block, next) {
+      var re = /^\s*\[(.*?)\]:\s*(\S+)(?:\s+(?:(['"])(.*?)\3|\((.*?)\)))?\n?/;
+      // interesting matches are [ , ref_id, url, , title, title ]
+
+      if ( !block.match(re) )
+        return undefined;
+
+      // make an attribute node if it doesn't exist
+      if ( !extract_attr( this.tree ) ) {
+        this.tree.splice( 1, 0, {} );
+      }
+
+      var attrs = extract_attr( this.tree );
+
+      // make a references hash if it doesn't exist
+      if ( attrs.references === undefined ) {
+        attrs.references = {};
+      }
+
+      var b = this.loop_re_over_block(re, block, function( m ) {
+
+        if ( m[2] && m[2][0] == "<" && m[2][m[2].length-1] == ">" )
+          m[2] = m[2].substring( 1, m[2].length - 1 );
+
+        var ref = attrs.references[ m[1].toLowerCase() ] = {
+          href: m[2]
+        };
+
+        if ( m[4] !== undefined )
+          ref.title = m[4];
+        else if ( m[5] !== undefined )
+          ref.title = m[5];
+
+      } );
+
+      if ( b.length )
+        next.unshift( mk_block( b, block.trailing ) );
+
+      return [];
+    },
+
+    para: function para( block, next ) {
+      // everything's a para!
+      return [ ["para"].concat( this.processInline( block ) ) ];
+    }
+  }
+};
+
+Markdown.dialects.Gruber.inline = {
+
+    __oneElement__: function oneElement( text, patterns_or_re, previous_nodes ) {
+      var m,
+          res,
+          lastIndex = 0;
+
+      patterns_or_re = patterns_or_re || this.dialect.inline.__patterns__;
+      var re = new RegExp( "([\\s\\S]*?)(" + (patterns_or_re.source || patterns_or_re) + ")" );
+
+      m = re.exec( text );
+      if (!m) {
+        // Just boring text
+        return [ text.length, text ];
+      }
+      else if ( m[1] ) {
+        // Some un-interesting text matched. Return that first
+        return [ m[1].length, m[1] ];
+      }
+
+      var res;
+      if ( m[2] in this.dialect.inline ) {
+        res = this.dialect.inline[ m[2] ].call(
+                  this,
+                  text.substr( m.index ), m, previous_nodes || [] );
+      }
+      // Default for now to make dev easier. just slurp special and output it.
+      res = res || [ m[2].length, m[2] ];
+      return res;
+    },
+
+    __call__: function inline( text, patterns ) {
+
+      var out = [],
+          res;
+
+      function add(x) {
+        //D:self.debug("  adding output", uneval(x));
+        if ( typeof x == "string" && typeof out[out.length-1] == "string" )
+          out[ out.length-1 ] += x;
+        else
+          out.push(x);
+      }
+
+      while ( text.length > 0 ) {
+        res = this.dialect.inline.__oneElement__.call(this, text, patterns, out );
+        text = text.substr( res.shift() );
+        forEach(res, add )
+      }
+
+      return out;
+    },
+
+    // These characters are intersting elsewhere, so have rules for them so that
+    // chunks of plain text blocks don't include them
+    "]": function () {},
+    "}": function () {},
+
+    __escape__ : /^\\[\\`\*_{}\[\]()#\+.!\-]/,
+
+    "\\": function escaped( text ) {
+      // [ length of input processed, node/children to add... ]
+      // Only esacape: \ ` * _ { } [ ] ( ) # * + - . !
+      if ( this.dialect.inline.__escape__.exec( text ) )
+        return [ 2, text.charAt( 1 ) ];
+      else
+        // Not an esacpe
+        return [ 1, "\\" ];
+    },
+
+    "![": function image( text ) {
+
+      // Unlike images, alt text is plain text only. no other elements are
+      // allowed in there
+
+      // ![Alt text](/path/to/img.jpg "Optional title")
+      //      1          2            3       4         <--- captures
+      var m = text.match( /^!\[(.*?)\][ \t]*\([ \t]*([^")]*?)(?:[ \t]+(["'])(.*?)\3)?[ \t]*\)/ );
+
+      if ( m ) {
+        if ( m[2] && m[2][0] == "<" && m[2][m[2].length-1] == ">" )
+          m[2] = m[2].substring( 1, m[2].length - 1 );
+
+        m[2] = this.dialect.inline.__call__.call( this, m[2], /\\/ )[0];
+
+        var attrs = { alt: m[1], href: m[2] || "" };
+        if ( m[4] !== undefined)
+          attrs.title = m[4];
+
+        return [ m[0].length, [ "img", attrs ] ];
+      }
+
+      // ![Alt text][id]
+      m = text.match( /^!\[(.*?)\][ \t]*\[(.*?)\]/ );
+
+      if ( m ) {
+        // We can't check if the reference is known here as it likely wont be
+        // found till after. Check it in md tree->hmtl tree conversion
+        return [ m[0].length, [ "img_ref", { alt: m[1], ref: m[2].toLowerCase(), original: m[0] } ] ];
+      }
+
+      // Just consume the '!['
+      return [ 2, "![" ];
+    },
+
+    "[": function link( text ) {
+
+      var orig = String(text);
+      // Inline content is possible inside `link text`
+      var res = Markdown.DialectHelpers.inline_until_char.call( this, text.substr(1), "]" );
+
+      // No closing ']' found. Just consume the [
+      if ( !res ) return [ 1, "[" ];
+
+      var consumed = 1 + res[ 0 ],
+          children = res[ 1 ],
+          link,
+          attrs;
+
+      // At this point the first [...] has been parsed. See what follows to find
+      // out which kind of link we are (reference or direct url)
+      text = text.substr( consumed );
+
+      // [link text](/path/to/img.jpg "Optional title")
+      //                 1            2       3         <--- captures
+      // This will capture up to the last paren in the block. We then pull
+      // back based on if there a matching ones in the url
+      //    ([here](/url/(test))
+      // The parens have to be balanced
+      var m = text.match( /^\s*\([ \t]*([^"']*)(?:[ \t]+(["'])(.*?)\2)?[ \t]*\)/ );
+      if ( m ) {
+        var url = m[1];
+        consumed += m[0].length;
+
+        if ( url && url[0] == "<" && url[url.length-1] == ">" )
+          url = url.substring( 1, url.length - 1 );
+
+        // If there is a title we don't have to worry about parens in the url
+        if ( !m[3] ) {
+          var open_parens = 1; // One open that isn't in the capture
+          for ( var len = 0; len < url.length; len++ ) {
+            switch ( url[len] ) {
+            case "(":
+              open_parens++;
+              break;
+            case ")":
+              if ( --open_parens == 0) {
+                consumed -= url.length - len;
+                url = url.substring(0, len);
+              }
+              break;
+            }
+          }
+        }
+
+        // Process escapes only
+        url = this.dialect.inline.__call__.call( this, url, /\\/ )[0];
+
+        attrs = { href: url || "" };
+        if ( m[3] !== undefined)
+          attrs.title = m[3];
+
+        link = [ "link", attrs ].concat( children );
+        return [ consumed, link ];
+      }
+
+      // [Alt text][id]
+      // [Alt text] [id]
+      m = text.match( /^\s*\[(.*?)\]/ );
+
+      if ( m ) {
+
+        consumed += m[ 0 ].length;
+
+        // [links][] uses links as its reference
+        attrs = { ref: ( m[ 1 ] || String(children) ).toLowerCase(),  original: orig.substr( 0, consumed ) };
+
+        link = [ "link_ref", attrs ].concat( children );
+
+        // We can't check if the reference is known here as it likely wont be
+        // found till after. Check it in md tree->hmtl tree conversion.
+        // Store the original so that conversion can revert if the ref isn't found.
+        return [ consumed, link ];
+      }
+
+      // [id]
+      // Only if id is plain (no formatting.)
+      if ( children.length == 1 && typeof children[0] == "string" ) {
+
+        attrs = { ref: children[0].toLowerCase(),  original: orig.substr( 0, consumed ) };
+        link = [ "link_ref", attrs, children[0] ];
+        return [ consumed, link ];
+      }
+
+      // Just consume the "["
+      return [ 1, "[" ];
+    },
+
+
+    "<": function autoLink( text ) {
+      var m;
+
+      if ( ( m = text.match( /^<(?:((https?|ftp|mailto):[^>]+)|(.*?@.*?\.[a-zA-Z]+))>/ ) ) != null ) {
+        if ( m[3] ) {
+          return [ m[0].length, [ "link", { href: "mailto:" + m[3] }, m[3] ] ];
+
+        }
+        else if ( m[2] == "mailto" ) {
+          return [ m[0].length, [ "link", { href: m[1] }, m[1].substr("mailto:".length ) ] ];
+        }
+        else
+          return [ m[0].length, [ "link", { href: m[1] }, m[1] ] ];
+      }
+
+      return [ 1, "<" ];
+    },
+
+    "`": function inlineCode( text ) {
+      // Inline code block. as many backticks as you like to start it
+      // Always skip over the opening ticks.
+      var m = text.match( /(`+)(([\s\S]*?)\1)/ );
+
+      if ( m && m[2] )
+        return [ m[1].length + m[2].length, [ "inlinecode", m[3] ] ];
+      else {
+        // TODO: No matching end code found - warn!
+        return [ 1, "`" ];
+      }
+    },
+
+    "  \n": function lineBreak( text ) {
+      return [ 3, [ "linebreak" ] ];
+    }
+
+};
+
+// Meta Helper/generator method for em and strong handling
+function strong_em( tag, md ) {
+
+  var state_slot = tag + "_state",
+      other_slot = tag == "strong" ? "em_state" : "strong_state";
+
+  function CloseTag(len) {
+    this.len_after = len;
+    this.name = "close_" + md;
+  }
+
+  return function ( text, orig_match ) {
+
+    if ( this[state_slot][0] == md ) {
+      // Most recent em is of this type
+      //D:this.debug("closing", md);
+      this[state_slot].shift();
+
+      // "Consume" everything to go back to the recrusion in the else-block below
+      return[ text.length, new CloseTag(text.length-md.length) ];
+    }
+    else {
+      // Store a clone of the em/strong states
+      var other = this[other_slot].slice(),
+          state = this[state_slot].slice();
+
+      this[state_slot].unshift(md);
+
+      //D:this.debug_indent += "  ";
+
+      // Recurse
+      var res = this.processInline( text.substr( md.length ) );
+      //D:this.debug_indent = this.debug_indent.substr(2);
+
+      var last = res[res.length - 1];
+
+      //D:this.debug("processInline from", tag + ": ", uneval( res ) );
+
+      var check = this[state_slot].shift();
+      if ( last instanceof CloseTag ) {
+        res.pop();
+        // We matched! Huzzah.
+        var consumed = text.length - last.len_after;
+        return [ consumed, [ tag ].concat(res) ];
+      }
+      else {
+        // Restore the state of the other kind. We might have mistakenly closed it.
+        this[other_slot] = other;
+        this[state_slot] = state;
+
+        // We can't reuse the processed result as it could have wrong parsing contexts in it.
+        return [ md.length, md ];
+      }
+    }
+  }; // End returned function
+}
+
+Markdown.dialects.Gruber.inline["**"] = strong_em("strong", "**");
+Markdown.dialects.Gruber.inline["__"] = strong_em("strong", "__");
+Markdown.dialects.Gruber.inline["*"]  = strong_em("em", "*");
+Markdown.dialects.Gruber.inline["_"]  = strong_em("em", "_");
+
+
+// Build default order from insertion order.
+Markdown.buildBlockOrder = function(d) {
+  var ord = [];
+  for ( var i in d ) {
+    if ( i == "__order__" || i == "__call__" ) continue;
+    ord.push( i );
+  }
+  d.__order__ = ord;
+};
+
+// Build patterns for inline matcher
+Markdown.buildInlinePatterns = function(d) {
+  var patterns = [];
+
+  for ( var i in d ) {
+    // __foo__ is reserved and not a pattern
+    if ( i.match( /^__.*__$/) ) continue;
+    var l = i.replace( /([\\.*+?|()\[\]{}])/g, "\\$1" )
+             .replace( /\n/, "\\n" );
+    patterns.push( i.length == 1 ? l : "(?:" + l + ")" );
+  }
+
+  patterns = patterns.join("|");
+  d.__patterns__ = patterns;
+  //print("patterns:", uneval( patterns ) );
+
+  var fn = d.__call__;
+  d.__call__ = function(text, pattern) {
+    if ( pattern != undefined ) {
+      return fn.call(this, text, pattern);
+    }
+    else
+    {
+      return fn.call(this, text, patterns);
+    }
+  };
+};
+
+Markdown.DialectHelpers = {};
+Markdown.DialectHelpers.inline_until_char = function( text, want ) {
+  var consumed = 0,
+      nodes = [];
+
+  while ( true ) {
+    if ( text.charAt( consumed ) == want ) {
+      // Found the character we were looking for
+      consumed++;
+      return [ consumed, nodes ];
+    }
+
+    if ( consumed >= text.length ) {
+      // No closing char found. Abort.
+      return null;
+    }
+
+    var res = this.dialect.inline.__oneElement__.call(this, text.substr( consumed ) );
+    consumed += res[ 0 ];
+    // Add any returned nodes.
+    nodes.push.apply( nodes, res.slice( 1 ) );
+  }
+}
+
+// Helper function to make sub-classing a dialect easier
+Markdown.subclassDialect = function( d ) {
+  function Block() {}
+  Block.prototype = d.block;
+  function Inline() {}
+  Inline.prototype = d.inline;
+
+  return { block: new Block(), inline: new Inline() };
+};
+
+Markdown.buildBlockOrder ( Markdown.dialects.Gruber.block );
+Markdown.buildInlinePatterns( Markdown.dialects.Gruber.inline );
+
+Markdown.dialects.Maruku = Markdown.subclassDialect( Markdown.dialects.Gruber );
+
+Markdown.dialects.Maruku.processMetaHash = function processMetaHash( meta_string ) {
+  var meta = split_meta_hash( meta_string ),
+      attr = {};
+
+  for ( var i = 0; i < meta.length; ++i ) {
+    // id: #foo
+    if ( /^#/.test( meta[ i ] ) ) {
+      attr.id = meta[ i ].substring( 1 );
+    }
+    // class: .foo
+    else if ( /^\./.test( meta[ i ] ) ) {
+      // if class already exists, append the new one
+      if ( attr["class"] ) {
+        attr["class"] = attr["class"] + meta[ i ].replace( /./, " " );
+      }
+      else {
+        attr["class"] = meta[ i ].substring( 1 );
+      }
+    }
+    // attribute: foo=bar
+    else if ( /\=/.test( meta[ i ] ) ) {
+      var s = meta[ i ].split( /\=/ );
+      attr[ s[ 0 ] ] = s[ 1 ];
+    }
+  }
+
+  return attr;
+}
+
+function split_meta_hash( meta_string ) {
+  var meta = meta_string.split( "" ),
+      parts = [ "" ],
+      in_quotes = false;
+
+  while ( meta.length ) {
+    var letter = meta.shift();
+    switch ( letter ) {
+      case " " :
+        // if we're in a quoted section, keep it
+        if ( in_quotes ) {
+          parts[ parts.length - 1 ] += letter;
+        }
+        // otherwise make a new part
+        else {
+          parts.push( "" );
+        }
+        break;
+      case "'" :
+      case '"' :
+        // reverse the quotes and move straight on
+        in_quotes = !in_quotes;
+        break;
+      case "\\" :
+        // shift off the next letter to be used straight away.
+        // it was escaped so we'll keep it whatever it is
+        letter = meta.shift();
+      default :
+        parts[ parts.length - 1 ] += letter;
+        break;
+    }
+  }
+
+  return parts;
+}
+
+Markdown.dialects.Maruku.block.document_meta = function document_meta( block, next ) {
+  // we're only interested in the first block
+  if ( block.lineNumber > 1 ) return undefined;
+
+  // document_meta blocks consist of one or more lines of `Key: Value\n`
+  if ( ! block.match( /^(?:\w+:.*\n)*\w+:.*$/ ) ) return undefined;
+
+  // make an attribute node if it doesn't exist
+  if ( !extract_attr( this.tree ) ) {
+    this.tree.splice( 1, 0, {} );
+  }
+
+  var pairs = block.split( /\n/ );
+  for ( p in pairs ) {
+    var m = pairs[ p ].match( /(\w+):\s*(.*)$/ ),
+        key = m[ 1 ].toLowerCase(),
+        value = m[ 2 ];
+
+    this.tree[ 1 ][ key ] = value;
+  }
+
+  // document_meta produces no content!
+  return [];
+};
+
+Markdown.dialects.Maruku.block.block_meta = function block_meta( block, next ) {
+  // check if the last line of the block is an meta hash
+  var m = block.match( /(^|\n) {0,3}\{:\s*((?:\\\}|[^\}])*)\s*\}$/ );
+  if ( !m ) return undefined;
+
+  // process the meta hash
+  var attr = this.dialect.processMetaHash( m[ 2 ] );
+
+  var hash;
+
+  // if we matched ^ then we need to apply meta to the previous block
+  if ( m[ 1 ] === "" ) {
+    var node = this.tree[ this.tree.length - 1 ];
+    hash = extract_attr( node );
+
+    // if the node is a string (rather than JsonML), bail
+    if ( typeof node === "string" ) return undefined;
+
+    // create the attribute hash if it doesn't exist
+    if ( !hash ) {
+      hash = {};
+      node.splice( 1, 0, hash );
+    }
+
+    // add the attributes in
+    for ( a in attr ) {
+      hash[ a ] = attr[ a ];
+    }
+
+    // return nothing so the meta hash is removed
+    return [];
+  }
+
+  // pull the meta hash off the block and process what's left
+  var b = block.replace( /\n.*$/, "" ),
+      result = this.processBlock( b, [] );
+
+  // get or make the attributes hash
+  hash = extract_attr( result[ 0 ] );
+  if ( !hash ) {
+    hash = {};
+    result[ 0 ].splice( 1, 0, hash );
+  }
+
+  // attach the attributes to the block
+  for ( a in attr ) {
+    hash[ a ] = attr[ a ];
+  }
+
+  return result;
+};
+
+Markdown.dialects.Maruku.block.definition_list = function definition_list( block, next ) {
+  // one or more terms followed by one or more definitions, in a single block
+  var tight = /^((?:[^\s:].*\n)+):\s+([\s\S]+)$/,
+      list = [ "dl" ],
+      i, m;
+
+  // see if we're dealing with a tight or loose block
+  if ( ( m = block.match( tight ) ) ) {
+    // pull subsequent tight DL blocks out of `next`
+    var blocks = [ block ];
+    while ( next.length && tight.exec( next[ 0 ] ) ) {
+      blocks.push( next.shift() );
+    }
+
+    for ( var b = 0; b < blocks.length; ++b ) {
+      var m = blocks[ b ].match( tight ),
+          terms = m[ 1 ].replace( /\n$/, "" ).split( /\n/ ),
+          defns = m[ 2 ].split( /\n:\s+/ );
+
+      // print( uneval( m ) );
+
+      for ( i = 0; i < terms.length; ++i ) {
+        list.push( [ "dt", terms[ i ] ] );
+      }
+
+      for ( i = 0; i < defns.length; ++i ) {
+        // run inline processing over the definition
+        list.push( [ "dd" ].concat( this.processInline( defns[ i ].replace( /(\n)\s+/, "$1" ) ) ) );
+      }
+    }
+  }
+  else {
+    return undefined;
+  }
+
+  return [ list ];
+};
+
+// splits on unescaped instances of @ch. If @ch is not a character the result
+// can be unpredictable
+
+Markdown.dialects.Maruku.block.table = function table (block, next) {
+
+    var _split_on_unescaped = function(s, ch) {
+        ch = ch || '\\s';
+        if (ch.match(/^[\\|\[\]{}?*.+^$]$/)) { ch = '\\' + ch; }
+        var res = [ ],
+            r = new RegExp('^((?:\\\\.|[^\\\\' + ch + '])*)' + ch + '(.*)'),
+            m;
+        while(m = s.match(r)) {
+            res.push(m[1]);
+            s = m[2];
+        }
+        res.push(s);
+        return res;
+    }
+
+    var leading_pipe = /^ {0,3}\|(.+)\n {0,3}\|\s*([\-:]+[\-| :]*)\n((?:\s*\|.*(?:\n|$))*)(?=\n|$)/,
+        // find at least an unescaped pipe in each line
+        no_leading_pipe = /^ {0,3}(\S(?:\\.|[^\\|])*\|.*)\n {0,3}([\-:]+\s*\|[\-| :]*)\n((?:(?:\\.|[^\\|])*\|.*(?:\n|$))*)(?=\n|$)/,
+        i, m;
+    if (m = block.match(leading_pipe)) {
+        // remove leading pipes in contents
+        // (header and horizontal rule already have the leading pipe left out)
+        m[3] = m[3].replace(/^\s*\|/gm, '');
+    } else if (! ( m = block.match(no_leading_pipe))) {
+        return undefined;
+    }
+
+    var table = [ "table", [ "thead", [ "tr" ] ], [ "tbody" ] ];
+
+    // remove trailing pipes, then split on pipes
+    // (no escaped pipes are allowed in horizontal rule)
+    m[2] = m[2].replace(/\|\s*$/, '').split('|');
+
+    // process alignment
+    var html_attrs = [ ];
+    forEach (m[2], function (s) {
+        if (s.match(/^\s*-+:\s*$/))       html_attrs.push({align: "right"});
+        else if (s.match(/^\s*:-+\s*$/))  html_attrs.push({align: "left"});
+        else if (s.match(/^\s*:-+:\s*$/)) html_attrs.push({align: "center"});
+        else                              html_attrs.push({});
+    });
+
+    // now for the header, avoid escaped pipes
+    m[1] = _split_on_unescaped(m[1].replace(/\|\s*$/, ''), '|');
+    for (i = 0; i < m[1].length; i++) {
+        table[1][1].push(['th', html_attrs[i] || {}].concat(
+            this.processInline(m[1][i].trim())));
+    }
+
+    // now for body contents
+    forEach (m[3].replace(/\|\s*$/mg, '').split('\n'), function (row) {
+        var html_row = ['tr'];
+        row = _split_on_unescaped(row, '|');
+        for (i = 0; i < row.length; i++) {
+            html_row.push(['td', html_attrs[i] || {}].concat(this.processInline(row[i].trim())));
+        }
+        table[2].push(html_row);
+    }, this);
+
+    return [table];
+}
+
+Markdown.dialects.Maruku.inline[ "{:" ] = function inline_meta( text, matches, out ) {
+  if ( !out.length ) {
+    return [ 2, "{:" ];
+  }
+
+  // get the preceeding element
+  var before = out[ out.length - 1 ];
+
+  if ( typeof before === "string" ) {
+    return [ 2, "{:" ];
+  }
+
+  // match a meta hash
+  var m = text.match( /^\{:\s*((?:\\\}|[^\}])*)\s*\}/ );
+
+  // no match, false alarm
+  if ( !m ) {
+    return [ 2, "{:" ];
+  }
+
+  // attach the attributes to the preceeding element
+  var meta = this.dialect.processMetaHash( m[ 1 ] ),
+      attr = extract_attr( before );
+
+  if ( !attr ) {
+    attr = {};
+    before.splice( 1, 0, attr );
+  }
+
+  for ( var k in meta ) {
+    attr[ k ] = meta[ k ];
+  }
+
+  // cut out the string and replace it with nothing
+  return [ m[ 0 ].length, "" ];
+};
+
+Markdown.dialects.Maruku.inline.__escape__ = /^\\[\\`\*_{}\[\]()#\+.!\-|:]/;
+
+Markdown.buildBlockOrder ( Markdown.dialects.Maruku.block );
+Markdown.buildInlinePatterns( Markdown.dialects.Maruku.inline );
+
+var isArray = Array.isArray || function(obj) {
+  return Object.prototype.toString.call(obj) == "[object Array]";
+};
+
+var forEach;
+// Don't mess with Array.prototype. Its not friendly
+if ( Array.prototype.forEach ) {
+  forEach = function( arr, cb, thisp ) {
+    return arr.forEach( cb, thisp );
+  };
+}
+else {
+  forEach = function(arr, cb, thisp) {
+    for (var i = 0; i < arr.length; i++) {
+      cb.call(thisp || arr, arr[i], i, arr);
+    }
+  }
+}
+
+var isEmpty = function( obj ) {
+  for ( var key in obj ) {
+    if ( hasOwnProperty.call( obj, key ) ) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+function extract_attr( jsonml ) {
+  return isArray(jsonml)
+      && jsonml.length > 1
+      && typeof jsonml[ 1 ] === "object"
+      && !( isArray(jsonml[ 1 ]) )
+      ? jsonml[ 1 ]
+      : undefined;
+}
+
+
+
+/**
+ *  renderJsonML( jsonml[, options] ) -> String
+ *  - jsonml (Array): JsonML array to render to XML
+ *  - options (Object): options
+ *
+ *  Converts the given JsonML into well-formed XML.
+ *
+ *  The options currently understood are:
+ *
+ *  - root (Boolean): wether or not the root node should be included in the
+ *    output, or just its children. The default `false` is to not include the
+ *    root itself.
+ */
+expose.renderJsonML = function( jsonml, options ) {
+  options = options || {};
+  // include the root element in the rendered output?
+  options.root = options.root || false;
+
+  var content = [];
+
+  if ( options.root ) {
+    content.push( render_tree( jsonml ) );
+  }
+  else {
+    jsonml.shift(); // get rid of the tag
+    if ( jsonml.length && typeof jsonml[ 0 ] === "object" && !( jsonml[ 0 ] instanceof Array ) ) {
+      jsonml.shift(); // get rid of the attributes
+    }
+
+    while ( jsonml.length ) {
+      content.push( render_tree( jsonml.shift() ) );
+    }
+  }
+
+  return content.join( "\n\n" );
+};
+
+function escapeHTML( text ) {
+  return text.replace( /&/g, "&amp;" )
+             .replace( /</g, "&lt;" )
+             .replace( />/g, "&gt;" )
+             .replace( /"/g, "&quot;" )
+             .replace( /'/g, "&#39;" );
+}
+
+function render_tree( jsonml ) {
+  // basic case
+  if ( typeof jsonml === "string" ) {
+    return escapeHTML( jsonml );
+  }
+
+  var tag = jsonml.shift(),
+      attributes = {},
+      content = [];
+
+  if ( jsonml.length && typeof jsonml[ 0 ] === "object" && !( jsonml[ 0 ] instanceof Array ) ) {
+    attributes = jsonml.shift();
+  }
+
+  while ( jsonml.length ) {
+    content.push( render_tree( jsonml.shift() ) );
+  }
+
+  var tag_attrs = "";
+  for ( var a in attributes ) {
+    tag_attrs += " " + a + '="' + escapeHTML( attributes[ a ] ) + '"';
+  }
+
+  // be careful about adding whitespace here for inline elements
+  if ( tag == "img" || tag == "br" || tag == "hr" ) {
+    return "<"+ tag + tag_attrs + "/>";
+  }
+  else {
+    return "<"+ tag + tag_attrs + ">" + content.join( "" ) + "</" + tag + ">";
+  }
+}
+
+function convert_tree_to_html( tree, references, options ) {
+  var i;
+  options = options || {};
+
+  // shallow clone
+  var jsonml = tree.slice( 0 );
+
+  if ( typeof options.preprocessTreeNode === "function" ) {
+      jsonml = options.preprocessTreeNode(jsonml, references);
+  }
+
+  // Clone attributes if they exist
+  var attrs = extract_attr( jsonml );
+  if ( attrs ) {
+    jsonml[ 1 ] = {};
+    for ( i in attrs ) {
+      jsonml[ 1 ][ i ] = attrs[ i ];
+    }
+    attrs = jsonml[ 1 ];
+  }
+
+  // basic case
+  if ( typeof jsonml === "string" ) {
+    return jsonml;
+  }
+
+  // convert this node
+  switch ( jsonml[ 0 ] ) {
+    case "header":
+      jsonml[ 0 ] = "h" + jsonml[ 1 ].level;
+      delete jsonml[ 1 ].level;
+      break;
+    case "bulletlist":
+      jsonml[ 0 ] = "ul";
+      break;
+    case "numberlist":
+      jsonml[ 0 ] = "ol";
+      break;
+    case "listitem":
+      jsonml[ 0 ] = "li";
+      break;
+    case "para":
+      jsonml[ 0 ] = "p";
+      break;
+    case "markdown":
+      jsonml[ 0 ] = "html";
+      if ( attrs ) delete attrs.references;
+      break;
+    case "code_block":
+      jsonml[ 0 ] = "pre";
+      i = attrs ? 2 : 1;
+      var code = [ "code" ];
+      code.push.apply( code, jsonml.splice( i, jsonml.length - i ) );
+      jsonml[ i ] = code;
+      break;
+    case "inlinecode":
+      jsonml[ 0 ] = "code";
+      break;
+    case "img":
+      jsonml[ 1 ].src = jsonml[ 1 ].href;
+      delete jsonml[ 1 ].href;
+      break;
+    case "linebreak":
+      jsonml[ 0 ] = "br";
+    break;
+    case "link":
+      jsonml[ 0 ] = "a";
+      break;
+    case "link_ref":
+      jsonml[ 0 ] = "a";
+
+      // grab this ref and clean up the attribute node
+      var ref = references[ attrs.ref ];
+
+      // if the reference exists, make the link
+      if ( ref ) {
+        delete attrs.ref;
+
+        // add in the href and title, if present
+        attrs.href = ref.href;
+        if ( ref.title ) {
+          attrs.title = ref.title;
+        }
+
+        // get rid of the unneeded original text
+        delete attrs.original;
+      }
+      // the reference doesn't exist, so revert to plain text
+      else {
+        return attrs.original;
+      }
+      break;
+    case "img_ref":
+      jsonml[ 0 ] = "img";
+
+      // grab this ref and clean up the attribute node
+      var ref = references[ attrs.ref ];
+
+      // if the reference exists, make the link
+      if ( ref ) {
+        delete attrs.ref;
+
+        // add in the href and title, if present
+        attrs.src = ref.href;
+        if ( ref.title ) {
+          attrs.title = ref.title;
+        }
+
+        // get rid of the unneeded original text
+        delete attrs.original;
+      }
+      // the reference doesn't exist, so revert to plain text
+      else {
+        return attrs.original;
+      }
+      break;
+  }
+
+  // convert all the children
+  i = 1;
+
+  // deal with the attribute node, if it exists
+  if ( attrs ) {
+    // if there are keys, skip over it
+    for ( var key in jsonml[ 1 ] ) {
+        i = 2;
+        break;
+    }
+    // if there aren't, remove it
+    if ( i === 1 ) {
+      jsonml.splice( i, 1 );
+    }
+  }
+
+  for ( ; i < jsonml.length; ++i ) {
+    jsonml[ i ] = convert_tree_to_html( jsonml[ i ], references, options );
+  }
+
+  return jsonml;
+}
+
+
+// merges adjacent text nodes into a single node
+function merge_text_nodes( jsonml ) {
+  // skip the tag name and attribute hash
+  var i = extract_attr( jsonml ) ? 2 : 1;
+
+  while ( i < jsonml.length ) {
+    // if it's a string check the next item too
+    if ( typeof jsonml[ i ] === "string" ) {
+      if ( i + 1 < jsonml.length && typeof jsonml[ i + 1 ] === "string" ) {
+        // merge the second string into the first and remove it
+        jsonml[ i ] += jsonml.splice( i + 1, 1 )[ 0 ];
+      }
+      else {
+        ++i;
+      }
+    }
+    // if it's not a string recurse
+    else {
+      merge_text_nodes( jsonml[ i ] );
+      ++i;
+    }
+  }
+}
+
+} )( (function() {
+  if ( typeof module === "undefined" ) {
+    window.markdown = {};
+    return window.markdown;
+  }
+  else {
+    return module.exports;
+  }
+} )() );

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff